-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathidx.html
477 lines (452 loc) · 29.3 KB
/
idx.html
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
<!DOCTYPE html>
<html lang="en">
<head>
<meta http-equiv="pragma" content="no-cache; charset=utf-8" />
<meta http-equiv="Content-type" content="text/html; charset=utf-8" />
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<title>RD60.py, python control for RD60xx power supplies</title>
<style type="text/css">
body {background-color:#FFFFDD}
//td {vertical-align:top;padding:0px;margin:0px}
p {text-align:justify;margin-bottom:0px}
td.gchord {font-size:75%;font-weight:bold;padding:0px;margin:0px;padding-top:0px;padding-right:3px;text-align:left;font-family:verdana,arial;color:#888888;position:relative;top:3px}
td.gtxt {text-align:left}
.dettitle {border-bottom:1px lightgray dashed}
.dettitle2 {border-bottom:1px lightgray dashed}
h2 {margin-top:20px; background-color:xgray}
h3 {background-color:xyellow;margin-top:30px;text-decoration:underline}
h4 {padding-left:0px;margin-left:0px;text-decoration:underline;color:#333333}
ul {margin-top:0px;padding-top:0px}
.ref {color:gray}
.gr {color:gray}
.grsm {color:gray;font-size:80%}
.err {color:red;font-weight:bold}
a {text-color:blue;text-decoration:underline}
a:HOVER {border-bottom:1px blue;color:red}
a.index {text-decoration:none}
a.index:HOVER {text-decoration:underline;color:red}
.preFile {background-color:lightgray;padding:0.5em}
td.imgthumb {vertical-align:top;padding:5px;font-size:80%}
img.ico {width:12px;height:12px;overflow:visible;position:relative;margin-top:-5px}
.imginc {max-width:100%;max-height:80vh}
.imginccap {text-align:left;padding-bottom:0.5em}
div.code {margin:0px;padding:0px;padding-left:30px;}
.code {font-family:courier,fixed;color:green;}
.cmd {font-family:courier,fixed;color:red;background-color:#FFEEDD;font-weight:bold;white-space:pre-wrap;padding-left:0.5em;;padding-right:0.5em;padding-top:0.5em;padding-bottom:0.5em}
.cmd::first-line {color:darkred;}
.cmd::before {content:'> ';}
.cmdresp {font-family:courier,fixed;color:blue;background-color:#EEEEFF;white-space:pre-wrap;padding-left:0.5em;;padding-right:0.5em;}
.cmdresp::first-line {color:darkblue;}
.cmdresp::before {content:' ';}
.comm {font-family:courier,fixed;color:red;background-color:#FFEEDD;font-weight:bold;white-space:pre-wrap;padding-left:0.5em;;padding-right:0.5em;}
.comm::first-line {color:darkred;}
.comm::before {content:'> ';}
.commresp {font-family:courier,fixed;color:blue;background-color:#EEEEFF;white-space:pre-wrap;padding-left:0.5em;;padding-right:0.5em;}
.commresp::first-line {color:darkblue;}
.commresp::before {content:'< ';}
.bang {font-weight:bold;color:red}
// unsupported by everything except apple, so far
//@media screen and (inverted-colors: inverted) {
//.cmd {background-color:#0000CC;color:lightblue;}
//.cmd::first-line: {color:blue}
//.cmdresp {background-color:#CC0000;color:lightred}
//.cmdresp::first-line: {color:red}
//}
@media print{
body {font-size:80%}
.noprint {display:none;visibility:hidden}
.xnopbr {page-break-inside:avoid}
td.gchord: {color:black}
.nopbr {}
.preFile {background-color:white;border:1px dotted black}
}
</style>
<meta property="og:title" content="RD60.py, python control for RD60xx power supplies" />
<meta property="og:type" content="website" />
<meta property="og:x-url" content="http://:" />
<meta property="og:description" content="software for control of Riden RD6024 power supply and some others" />
</head>
<body>
<h1>RD60.py, python control for RD60xx power supplies</h1><hr class="noprint" /><div class="noprint"><a class="index indexlev2" href="#Why" title="">Why</a><br /><a class="index indexlev2" href="#How" title="How">How</a><br /> <small><a class="index indexlev3" href="#dependencies" title="How.dependencies">dependencies</a></small><br /><a class="index indexlev2" href="#Usage" title="Usage">Usage</a><br /> <small><a class="index indexlev3" href="#hardwareconfiguration" title="Usage.hardware configuration">hardware configuration</a></small><br /> <small><a class="index indexlev3" href="#commands" title="Usage.commands">commands</a></small><br /> <small><a class="index indexlev3" href="#registers" title="Usage.registers">registers</a></small><br /> <small><a class="index indexlev3" href="#settings" title="Usage.settings">settings</a></small><br /> <small><a class="index indexlev3" href="#miniscripts" title="Usage.miniscripts">miniscripts</a></small><br /> <small><a class="index indexlev4" href="#loops" title="Usage.miniscripts.loops">loops</a></small><br /> <small><a class="index indexlev4" href="#stdin" title="Usage.miniscripts.stdin">stdin</a></small><br /> <small><a class="index indexlev4" href="#dataononeline" title="Usage.miniscripts.data on one line">data on one line</a></small><br /> <small><a class="index indexlev4" href="#connectionpersistence" title="Usage.miniscripts.connection persistence">connection persistence</a></small><br /> <small><a class="index indexlev3" href="#verbosity" title="Usage.verbosity">verbosity</a></small><br /> <small><a class="index indexlev3" href="#temperatures" title="Usage.temperatures">temperatures</a></small><br /> <small><a class="index indexlev3" href="#batterymode" title="Usage.battery mode">battery mode</a></small><br /> <small><a class="index indexlev3" href="#autoconfiguration" title="Usage.autoconfiguration">autoconfiguration</a></small><br /><a class="index indexlev2" href="#Files" title="Files">Files</a><br /><a class="index indexlev2" href="#TODO" title="TODO">TODO</a><br /></div><hr /><a name="Why"></a><h2> Why
</h2>
<p>
It was necessary to control a Riden power supply for some lab automation purposes.
The stock software was useless for the purpose.
</p>
<p>
Fortunately, the protocol is documented enough, and based on MODBUS.
</p>
<p>
All available software is in this or that form dependent on some MODBUS library, which
relies on the assumption of a fully functional local or at least virtual serial port of /dev/ttySx
or /dev/ttyUSBx or such nature.
</p>
<p>
The wired ports require... umm... wires. USB to a nearby computer. Which is not always feasible.
The virtual COM ports require OS-specific (and often capricious) port emulating software on the
computer side. All when all that's necessary is a pipe for bytes in, bytes out.
</p>
<p>
An expedient plain <a class="P" href="https://www.improwis.com/projects/hw_SerialOverTCP" title="local project" target="_blank">serial-over-TCP</a> ("TasmoCOM") solution was chosen, leveraging ESP8266
and <a class="w" href="https://en.wikipedia.org/wiki/Tasmota" title="Wikipedia link: Tasmota" target="_blank">Tasmota</a>, a proven cheap and opensource approach.
</p>
<p>
For the hardware, see <a class="P" href="https://www.improwis.com/projects/hw_RD6024powersupply" title="local project" target="_blank">hw_RD6024powersupply</a>.
</p>
<p>
For the control code for an artificial load, see <a class="P" href="https://www.improwis.com/projects/sw_dl24" title="local project" target="_blank">sw_dl24</a>.
</p>
<p>
Tested with:
<ul><li> RD6024, deviceID 60241
</li><li> RK6006, deviceID 60066
</li></ul></p>
<hr /><a name="How"></a><h2> How
</h2>
<p>
<span class="code">rd60.py</span>, a python-based (for portability) script, was written. The software allows both
using a tty-style port and a raw TCP socket, with no fancy RFC2217 support. If the latter is needed, URI-style
pyserial syntax is available with the port.
</p>
<p>
The software defines a hierarchy of classes:
<ul><li> <span class="code">class LowLevelSerPort</span> - for wired /dev/ttyX ports or full virtual ports
</li><li> <span class="code">class LowLevelTcpPort</span> - for raw TCP sockets, TasmoCOM style
</li><li> <span class="code">class RDModbus</span> - <a class="w" href="https://en.wikipedia.org/wiki/MODBUS" title="Wikipedia link: MODBUS" target="_blank">MODBUS</a> protocol, implementing the Riden function subset (3, 6, 16)
</li><li> <span class="code">class PSU_RD60XX</span> - functions specific for the RD60xx power supplies, register lists
</li><li> <span class="code">class PowerSupply</span> - command interpreter, configfile reader
</li></ul></p>
<a name="dependencies"></a><h3> dependencies
</h3>
<p>
The software tries to minimize dependencies.
</p>
<p>
The mandatory ones, and mostly standard ones, are:
<ul><li> <span class="code">socket</span> (for TCP communication)
</li><li> <span class="code">time</span> (for sleep)
</li><li> <span class="code">struct</span> (pack/unpack, for conversion of packets to/from byte stream)
</li></ul>The nonmandatory, imported only as needed (so the process would run when a missing dependency is not required), are:
<ul><li> <span class="code">serial</span> (pyserial, for serial ports)
</li><li> <span class="code">datetime</span> (for date/time settings)
</li><li> <span class="code">json</span> (for JSON format output)
</li></ul></p>
<hr /><a name="Usage"></a><h2> Usage
</h2>
<pre class="preFile">RD60 Riden RD60xx power supply control
Usage: ./rd60.py <command> [command]...
Commands:
ON enable output
OFF disable output
nn.nnV set output voltage
nn.nnMA set output current
nn.nnA set output current
nn.nnVO set overvoltage protection
nn.nnMAO set overcurrent protection
nn.nnAO set overcurrent protection
QV query actual voltage
QA query actual current
QBV query battery voltage
QTE query external temperature
QTI query internal temperature
QREGxx or Qxx query register xx (name or decimal)
STATE[:opts] print setting state in JSON format
STATEJ[:opts] print setting state in JSON format, like opts=J
opts: J=JSON, S=short (V/A only), T=show time, U=show UTC time, B=force battery
REGxx=yy write register xx to value yy (decimal)
REGS dump registers
REGSALL dump registers including memories and calibration
REGSALL:n dump n registers
REGSDIFF show registers difference
TCP=addr[:port] set connection via TCP
PORT=/dev/ttyport[@baud] set connection via serial port
ROBUST increase timeouts and retries
BAT enable battery charging related registers
NOBAT disable battery charging related registers
STDIN read commands from stdin
LOOP:[xx] loop for xx time or endless if not specified
SLEEPxx sleep for xx seconds
VERB or -V list MODBUS transactions; affects subsequent commands
LINE output the Q-queries as space-separated instead of newline-separated
SETMEMx=v,a,vo,ao set memory x to values
MEMS dump memories
SETCLOCK set clock to current datetime
CFGFILE generate config file template to stdout
For volt and amp setting, prefixing the value with + or - marks it as relative, to be added/subtracted to the current value
Commands are executed in sequence. Writes are cached and grouped together to minimize bus transactions.
Commands are case-insensitive.
Command "-" forces a newline into output.
</pre><a name="hardwareconfiguration"></a><h3> hardware configuration
</h3>
<p>
The host:port or serport:baudrate are saved in ~/.rd60.cfg (or other name, where filename is derived from
the command by stripping the .py suffix and prefixing a home directory and a dot). This variability allows
to use several symlinks for different power supplies simultaneously used, eg. as rd60a, rd60b,...
</p>
<p>
The configfile template can be generated on demand by command <span class="code">CFGFILE</span>.
</p>
<p>
Directly, the devices may be specified as <span class="code">TCP=<host>[:port] </span> or <span class="code">PORT=/dev/ttyUSBx@baudrate</span>,
eg. <span class="code">TCP=10.0.1.15:8888</span> or <span class="code">PORT=/dev/ttyUSB1@115200</span> or <span class="code">PORT=/dev/ttyUSB1</span> (default speed is 115200).
</p>
<p>
The PORT directive, both in command and in config, also supports the <a class="a" href="https://pyserial.readthedocs.io/en/latest/url_handlers.html" title="remote link: https://pyserial.readthedocs.io/en/latest/url_handlers.html" target="_blank">URL form</a>.
</p>
<a name="commands"></a><h3> commands
</h3>
<p>
The script takes a sequence of commands from commandline, separated by spaces. Each command is a single token,
optionally containing separator characters.
</p>
<p>
The commands can be a fixed string (<span class="code">STATE</span>, <span class="code">REGS</span>, <span class="code">QV</span>, ...) or a prefix with value, or value with suffix (12.5<span class="code">V</span>,
<span class="code">SLEEP</span>1.5, <span class="code">REG</span>12<span class="code">=</span>8123, <span class="code">Q</span>VIN...)
</p>
<p>
Register names can be sent as decimal address or as a name. <span class="code">Q3</span> and <span class="code">QFW</span> are the same.
</p>
<p>
Some commands look like register commands but refer directly to values:
<ul><li> <span class="code">QV</span>, <span class="code">QA</span> - for querying output voltage/amperage
</li><li> <span class="code">QMV</span>, <span class="code">QMA</span> - same, but integer value in millivolts/milliamps instead of float, for bash comparisons
</li></ul></p>
<a name="registers"></a><h3> registers
</h3>
<p>
The <span class="code">REGS</span> and <span class="code">REGSALL</span> commands read and dump the power supply's MODBS registers. REGS only first 42, REGSALL take in 122 (which
includes calibration registers (do not touch unless you MUST) and the memories (M0 is for the currently set overvoltage and overcurrent
protections (OVP and OCP), M1..M9 are for presets).
</p>
<p>
The registers dump shows register address in hex and decimal, value in decimal and hex, r/rw for readonly and readwrite, short name, and description.
Registers with zero value and no known name are assumed unused and are skipped.
</p>
<div class="cmd">./rd60.py regs</div><pre class="">x00 0 60241 0xeb51 r ID type ID
x01 1 0 0x0000 r SN_H serial number H
x02 2 10542 0xXXXX r SN_L serial number L
x03 3 138 0x008a r FW firmware version *100
x04 4 0 0x0000 r INT_C_S INT_C_S
x05 5 44 0x002c r INT_C internal temperature C
x06 6 0 0x0000 r INT_F_S INT_F_S
x07 7 111 0x006f r INT_F internal temperature F
x08 8 1000 0x03e8 rw V_SET set voltage
x09 9 210 0x00d2 rw I_SET set current
x0a 10 998 0x03e6 r V_OUT actual voltage
x0b 11 0 0x0000 r I_OUT actual current
x0c 12 0 0x0000 r AH AH
x0d 13 0 0x0000 r P_OUT actual power
x0e 14 6789 0x1a85 r V_IN input voltage
x0f 15 1 0x0001 r KEYPAD keyboard locked
x10 16 0 0x0000 r OVP_OCP OVP-OCP active
x11 17 0 0x0000 r CV_CC output at constant current
x12 18 1 0x0001 rw OUTPUT output enabled
x13 19 0 0x0000 rw PRESET preset number
x14 20 0 0x0000 r I_RANGE I_RANGE
x20 32 0 0x0000 r BAT_MODE battery mode enabled
x21 33 0 0x0000 r V_BAT battery voltage
x22 34 1 0x0001 r EXT_C_S EXT_C_S
x23 35 89 0x0059 r EXT_C battery temperature C
x24 36 1 0x0001 r EXT_F_S EXT_F_S
x25 37 129 0x0081 r EXT_F battery temperature F
x26 38 0 0x0000 r AH_H amphour H
x27 39 0 0x0000 r AH_L amphour L
x28 40 0 0x0000 r WH_H watthour H
x29 41 0 0x0000 r WH_L watthour L
</pre><p>
or, for <span class="code">REGSALL</span>, also
<pre class="">x30 48 2023 0x07e7 rw YEAR clock year
x31 49 12 0x000c rw MONTH clock month
x32 50 16 0x0010 rw DAY clock day
x33 51 0 0x0000 rw HOUR clock hour
x34 52 20 0x0014 rw MINUTE clock minute
x35 53 44 0x002c rw SECOND clock second
x37 55 24 0xXXXX rw V_OUT_ZERO calibration V_OUT_ZERO
x38 56 24859 0xXXXX rw V_OUT_SCALE calibration V_OUT_SCALE
x39 57 33 0xXXXX rw V_BACK_ZERO calibration V_BACK_ZERO
x3a 58 24543 0xXXXX rw V_BACK_SCALE calibration V_BACK_SCALE
x3b 59 334 0xXXXX rw I_OUT_ZERO calibration I_OUT_ZERO
x3c 60 4327 0xXXXX rw I_OUT_SCALE calibration I_OUT_SCALE
x3d 61 59 0xXXXX rw I_BACK_ZERO calibration I_BACK_ZERO
x3e 62 4663 0xXXXX rw I_BACK_SCALE calibration I_BACK_SCALE
x42 66 1 0x0001 rw OPT_TAKE_OK OPT_TAKE_OK
x43 67 0 0x0000 rw OPT_TAKE_OUT output enabled on memory select
x44 68 0 0x0000 rw OPT_BOOT_POW output enabled on boot
x45 69 1 0x0001 rw OPT_BUZZ buzzer enabled
x46 70 1 0x0001 rw OPT_LOGO logo enabled on boot
x47 71 0 0x0000 rw OPT_LANG interface language
x48 72 3 0x0003 rw OPT_LIGHT display backlight level
x50 80 300 0x012c rw M0_V currently set V
x51 81 200 0x00c8 rw M0_I currently set I
x52 82 2000 0x07d0 rw M0_OVP currently set OVP
x53 83 220 0x00dc rw M0_OCP currently set OCP
x54 84 600 0x0258 rw M1_V memory M1 V
x55 85 200 0x00c8 rw M1_I memory M1 I
x56 86 700 0x02bc rw M1_OVP memory M1 OVP
x57 87 500 0x01f4 rw M1_OCP memory M1 OCP
x58 88 500 0x01f4 rw M2_V memory M2 V
x59 89 2410 0x096a rw M2_I memory M2 I
x5a 90 6200 0x1838 rw M2_OVP memory M2 OVP
x5b 91 2420 0x0974 rw M2_OCP memory M2 OCP
x5c 92 500 0x01f4 rw M3_V memory M3 V
x5d 93 2410 0x096a rw M3_I memory M3 I
x5e 94 6200 0x1838 rw M3_OVP memory M3 OVP
x5f 95 2420 0x0974 rw M3_OCP memory M3 OCP
x60 96 500 0x01f4 rw M4_V memory M4 V
x61 97 2410 0x096a rw M4_I memory M4 I
x62 98 6200 0x1838 rw M4_OVP memory M4 OVP
x63 99 2420 0x0974 rw M4_OCP memory M4 OCP
x64 100 500 0x01f4 rw M5_V memory M5 V
x65 101 2410 0x096a rw M5_I memory M5 I
x66 102 6200 0x1838 rw M5_OVP memory M5 OVP
x67 103 2420 0x0974 rw M5_OCP memory M5 OCP
x68 104 500 0x01f4 rw M6_V memory M6 V
x69 105 2410 0x096a rw M6_I memory M6 I
x6a 106 6200 0x1838 rw M6_OVP memory M6 OVP
x6b 107 2420 0x0974 rw M6_OCP memory M6 OCP
x6c 108 500 0x01f4 rw M7_V memory M7 V
x6d 109 2410 0x096a rw M7_I memory M7 I
x6e 110 6200 0x1838 rw M7_OVP memory M7 OVP
x6f 111 2420 0x0974 rw M7_OCP memory M7 OCP
x70 112 500 0x01f4 rw M8_V memory M8 V
x71 113 2410 0x096a rw M8_I memory M8 I
x72 114 6200 0x1838 rw M8_OVP memory M8 OVP
x73 115 2420 0x0974 rw M8_OCP memory M8 OCP
x74 116 500 0x01f4 rw M9_V memory M9 V
x75 117 2410 0x096a rw M9_I memory M9 I
x76 118 6200 0x1838 rw M9_OVP memory M9 OVP
x77 119 2420 0x0974 rw M9_OCP memory M9 OCP
</pre></p>
<a name="settings"></a><h3> settings
</h3>
<p>
The voltage, current, and overvoltage/overcurrent protection can be set with suffix-based commands.
For the value of 1.23, the commands are
<ul><li> <span class="code">1.23V</span> - set output voltage
</li><li> <span class="code">1.23A</span> - set output current
</li><li> <span class="code">1230MA</span> - set output current in milliamps
</li><li> <span class="code">1.23VO</span> - set overvoltage protection (OVP)
</li><li> <span class="code">1.23AO</span> - set overcurrent protection (OCP)
</li><li> <span class="code">1230MAO</span> - set overcurrent protection (OCP) in milliamps
</li><li> <span class="code">+1.23V</span> - increase output voltage
</li><li> <span class="code">-1.23V</span> - decrease output voltage
</li><li> <span class="code">+1.23A</span> - increase output current
</li><li> <span class="code">+1230MA</span> - increase output current in milliamps
</li></ul></p>
<p>
The battery-related registers are not refreshed during usual operations. If the power supply is to be used in battery charging duty,
enable related reporting with command <span class="code">BAT</span>.
<pre class=""><del><b></b></del></pre></p>
<a name="miniscripts"></a><h3> miniscripts
</h3>
<p>
The commands are executed in order. To minimize bus transactions, the ones from the low memory area (first 42 registers) are grouped into a single write.
</p>
<ul><li> set voltage and current, enable output
</li><ul><li> <span class="code">rd60.py 12v 550ma on</span>
</li></ul><li> toggle output, wait half second, show state
</li><ul><li> <span class="code">rd60.py toggle sleep0.5 state</span>
</li></ul><li> set output to 5 volts and enable, wait a second, increase by volt, wait a second, increase by another two volts, show state and power off
</li><ul><li> <span class="code">rd60.py on 5v sleep1 +1v sleep1 +2v sleep0.5 state off</span>
</li></ul><li> show output voltage and power, one per line (QP_OUT queries register by name)
</li><ul><li> <span class="code">rd60.py qv qP_OUT</span>
</li></ul><li> show output voltage in millivolts and current in milliamps, space-separated
</li><ul><li> <span class="code">rd60.py qmv qma | tr '\n' ' '</span>
</li></ul><li> disable output, set output voltage and current, overvoltage and overcurrent, enable output
</li><ul><li> <span class="code">rd60.py off 4.9v 1250ma 5.5vo 2.1ao on</span>
</li></ul></ul><a name="loops"></a><h4> loops
</h4>
<p>
The <span class="code">LOOP:</span> statement can be used for repeating of commands. The subsequent command set is repeated forever, or for specified number of times.
</p>
<ul><li> show status in JSON format, forever
</li><ul><li> <span class="code">rd60.py loop: jstate</span>
</li></ul><li> ramp voltage by 20mV over time, from 5 to 15V, watch status:
</li><ul><li> <span class="code">rd60.py 5v on loop:500 +0.02v sleep0.5 jstat</span>
</li></ul></ul><a name="stdin"></a><h4> stdin
</h4>
<p>
The commands can be sent from another script, via stdin. The <span class="code">STDIN</span> statement has to be the last on the command line, everything after it is ignored.
<ul><li> enable output, take file with voltages, send in one per second, then disable output
</li><ul><li> <span class="code">cat file.txt | while read x; do echo $x; sleep 1; done | ./rd60.py on stdin; ./rd60.py off</span>
</li></ul></ul></p>
<a name="dataononeline"></a><h4> data on one line
</h4>
<p>
The <span class="code">LINE</span> command sets the separator character between Q-values from default newline to a space. Groups of values then can be sent as single lines.
<ul><li> check every 5 seconds, send millivolts/battery millivolts/milliamps/internal temperature/constant-current register state, use battery mode:
</li><ul><li> <span class="code">rd60.py bat line loop: qmv qbmv qma qti qcv_cc sleep5</span>
</li></ul></ul></p>
<a name="connectionpersistence"></a><h4> connection persistence
</h4>
<p>
The connection to the port is opened when first needed, then kept open until the process closes.
</p>
<p>
In some cases this may be detrimental to reliability (connection fail crashes the process). Running it anew each time may be beneficial then.
</p>
<a name="verbosity"></a><h3> verbosity
</h3>
<p>
To see the port/socket opening/closing, and the bus transactions dumped in hex, use <span class="code">VERB</span> as the first command.
</p>
<div class="cmd">./rd60.py verb state</div><pre class="">CONFIGFILE:filename: /home/user/.rd60.cfg
CONFIGFILE: {'host': 'rd60', 'port': '8888'}
SOCK:connecting to rd60 : 8888
SOCK:connected
MODBUS:CMND:READREGS 0 42
MODBUS:SEND 01:03:00:00:00:2a:c4:15 (correct)
MODBUS:RECV 01:03:54:eb:51:00:00:XX:XX:00:8a:00:00:00:2c:00:00:00:70:03:e8:00:d2:03:e6:00:00:00:00:00:00:1a:84:00:00:00:00:00:00:00:01:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:00:01:00:59:00:01:00:81:00:00:00:00:00:00:00:00:XX:cd (correct)
MODBUS:CMND:READREGS 82 2
MODBUS:SEND 01:03:00:52:00:02:65:da (correct)
MODBUS:RECV 01:03:04:07:d0:00:dc:fb:27 (correct)
Vin =67.88 v tempin =44 'c tempext=89 'c
Vset=10.00 v OVP =20.00 v
Iset= 2.10 a OCP = 2.20 a
OUTPUT ENABLED
Vout= 9.98 v
Iout= 0.00 a
SOCK:closed
</pre><a name="temperatures"></a><h3> temperatures
</h3>
<p>
The <span class="code">INT_C</span> and <span class="code">EXT_C</span> registers contain the power supply board temperature and the external NTC probe temperature in degrees C. (The corresponding _F registers
use the Fahrenheit abomination.)
</p>
<p>
Caution, if the external probe is not attached the register value contains swinging nonsense.
</p>
<a name="batterymode"></a><h3> battery mode
</h3>
<p>
The power supply has a range of registers for specific use with battery charging (battery voltage measurements, watthours, amphours).
To conserve socket/port transfers volume, this registers block is read only if the power supply is in battery mode.
</p>
<p>
The battery mode is autodetected when the program starts; for prolonged loop-based operation, this will miss the battery detection event and the mode won't be changed,
as the register is in the area that's read only during first start (unless in battery mode).
</p>
<p>
The battery mode can be also manually forced by <span class="code">BAT</span> or disabled by <span class="code">NOBAT</span>.
</p>
<a name="autoconfiguration"></a><h3> autoconfiguration
</h3>
<p>
The software borrows a trick (and table of devices) from <a class="w" href="https://en.wikipedia.org/wiki/Sigrok" title="Wikipedia link: Sigrok" target="_blank">Sigrok</a>'s libsigrok, the <a class="a" href="https://sigrok.org/gitweb/?p=libsigrok.git;a=tree;f=src/hardware/rdtech-dps" title="remote link: https://sigrok.org/gitweb/?p=libsigrok.git;a=tree;f=src/hardware/rdtech-dps" target="_blank">rdtech-dps</a>
component. From the table of devices, based on the device ID (register 0), the type is identified and the voltage and amperage multipliers are loaded.
(The registers provide data as 16bit integers, which have to be converted to the floats. With multiplier of 100, a 1.28 amp is set or read as 128.
The multiplier has to be known, and is type-specific, otherwise the voltages/currents can be off by a magnitude or two. 100 and 100 is default when the
type is unknown.
</p>
<hr /><a name="Files"></a><h2> Files
</h2>
<ul><li> <b><a class="F" href="rd60.py" title="local file">rd60.py</a></b> - code itself
</li></ul><hr /><a name="TODO"></a><h2> TODO
</h2>
<ul><li> better windows compatibility
</li><li> hardware mod for attaching an adc to the wifi unit, for streaming of measurements independent on the MODBUS
</li><li> <a class="w" href="https://en.wikipedia.org/wiki/Standard_Commands_for_Programmable_Instruments" title="Wikipedia link: Standard Commands for Programmable Instruments" target="_blank">SCPI</a> emulation/gateway
</li></ul><!-- feedback -->
<!-- /feedback -->
</body>
</html>