672 lines
12 KiB
Markdown
672 lines
12 KiB
Markdown
# MightyWatt Linux CLI Help
|
||
|
||
This document matches the current backend/CLI tree in this repository.
|
||
|
||
## Scope
|
||
|
||
Current features:
|
||
- serial communication with MightyWatt hardware
|
||
- reusable C backend (`libmightywatt_core` style project layout)
|
||
- CLI control and monitoring
|
||
- CSV logging
|
||
- JSON-driven sequence runner
|
||
- loops in the sequence engine
|
||
- mandatory `abort_sequence` for safe shutdown / cleanup
|
||
|
||
Current sequence format:
|
||
- **JSON only**
|
||
- YAML is **not** supported in the current C implementation
|
||
|
||
---
|
||
|
||
## General usage
|
||
|
||
```bash
|
||
mwcli -d /dev/ttyACM0 [global options] <command> [command args]
|
||
```
|
||
|
||
Example:
|
||
|
||
```bash
|
||
./mwcli -d /dev/ttyACM0 caps
|
||
```
|
||
|
||
---
|
||
|
||
## Global options
|
||
|
||
These options go before the command.
|
||
|
||
### `-d, --device PATH`
|
||
Serial device path.
|
||
|
||
Example:
|
||
|
||
```bash
|
||
./mwcli -d /dev/ttyACM0 caps
|
||
```
|
||
|
||
### `-s, --settle-ms N`
|
||
Delay after opening the serial port, in milliseconds.
|
||
|
||
Default:
|
||
|
||
```text
|
||
2200
|
||
```
|
||
|
||
Use this because Arduino-class boards often reset when the port is opened.
|
||
|
||
Example:
|
||
|
||
```bash
|
||
./mwcli -d /dev/ttyACM0 -s 2500 caps
|
||
```
|
||
|
||
### `-i, --interval-ms N`
|
||
Polling interval in milliseconds.
|
||
|
||
Used by:
|
||
- `monitor`
|
||
- `hold`
|
||
|
||
Default:
|
||
|
||
```text
|
||
500
|
||
```
|
||
|
||
### `-c, --count N`
|
||
Number of samples.
|
||
|
||
Used by:
|
||
- `monitor`
|
||
- `hold`
|
||
|
||
If omitted, the stream continues until interrupted with `Ctrl+C`.
|
||
|
||
### `--sample-period-ms N`
|
||
Override `sample_period_ms` from the JSON sequence file.
|
||
|
||
Used by:
|
||
- `run-sequence`
|
||
|
||
### `--csv PATH`
|
||
Write measurement samples to a CSV file.
|
||
|
||
Works with:
|
||
- `report`
|
||
- `monitor`
|
||
- `hold`
|
||
- `load-on`
|
||
- `load-off`
|
||
- `safe`
|
||
- `remote`
|
||
- `set-*`
|
||
- `run-sequence`
|
||
|
||
### `-j, --json`
|
||
Print JSON to stdout instead of plain text.
|
||
|
||
Useful for:
|
||
- scripts
|
||
- wrappers
|
||
- future GUI integration
|
||
|
||
Current behaviour:
|
||
- one-shot commands print one JSON object
|
||
- `monitor` and `hold` print JSON lines
|
||
- `run-sequence` prints one summary object at the end
|
||
|
||
### `-h, --help`
|
||
Show built-in CLI help.
|
||
|
||
---
|
||
|
||
# Commands
|
||
|
||
## `idn`
|
||
Query the device identity string.
|
||
|
||
## `caps`
|
||
Read device capabilities.
|
||
|
||
Typical fields:
|
||
- firmware version
|
||
- board revision
|
||
- max current DAC / ADC
|
||
- max voltage DAC / ADC
|
||
- max power
|
||
- DVM input resistance
|
||
- temperature threshold
|
||
|
||
## `report`
|
||
Read one measurement report.
|
||
|
||
Returns:
|
||
- current
|
||
- voltage
|
||
- power
|
||
- temperature
|
||
- remote state
|
||
- status
|
||
|
||
## `monitor`
|
||
Continuously poll and print measurements.
|
||
|
||
Examples:
|
||
|
||
```bash
|
||
./mwcli -d /dev/ttyACM0 monitor
|
||
./mwcli -d /dev/ttyACM0 -i 500 -c 20 monitor
|
||
./mwcli -d /dev/ttyACM0 -j monitor
|
||
```
|
||
|
||
## `set-current <amps>`
|
||
Stage/set current target.
|
||
|
||
## `set-voltage <volts>`
|
||
Stage/set voltage target.
|
||
|
||
## `set-power <watts>`
|
||
Stage/set power target.
|
||
|
||
## `set-resistance <ohms>`
|
||
Stage/set resistance target.
|
||
|
||
## `set-vinv <volts>`
|
||
Stage/set inverted-voltage target.
|
||
|
||
This is a firmware-supported special mode.
|
||
|
||
## `hold <mode> <value>`
|
||
Enable and keep a target alive by polling continuously.
|
||
|
||
This is the right command for real bench work because the MightyWatt watchdog requires regular host traffic.
|
||
|
||
Modes:
|
||
- `current`
|
||
- `voltage`
|
||
- `power`
|
||
- `resistance`
|
||
- `vinv`
|
||
|
||
Aliases accepted:
|
||
- `CC`
|
||
- `CV`
|
||
- `CP`
|
||
- `CR`
|
||
|
||
Examples:
|
||
|
||
```bash
|
||
./mwcli -d /dev/ttyACM0 hold current 0.250
|
||
./mwcli -d /dev/ttyACM0 -i 500 -c 10 hold power 1.000
|
||
./mwcli -d /dev/ttyACM0 -j hold resistance 20.000
|
||
```
|
||
|
||
## `load-on <mode> <value>`
|
||
Apply a target once and return one report.
|
||
|
||
Important:
|
||
- this is a one-shot command
|
||
- the hardware may fall back after ~1–2 seconds if no more host traffic follows
|
||
- for sustained load use `hold`
|
||
|
||
## `load-off`
|
||
Turn the load off.
|
||
|
||
Current implementation:
|
||
- host-side load-off via zero-current target
|
||
- the MightyWatt protocol has no dedicated hardware output-enable bit
|
||
|
||
## `safe`
|
||
Go to safe state.
|
||
|
||
Current implementation:
|
||
- load off
|
||
- remote sense off
|
||
|
||
## `remote on|off`
|
||
Enable or disable remote sense.
|
||
|
||
## `get-series`
|
||
Read configured series resistance.
|
||
|
||
Output unit:
|
||
- ohms
|
||
|
||
## `set-series <ohms>`
|
||
Set series resistance.
|
||
|
||
## `run-sequence <sequence.json>`
|
||
Run a JSON sequence file.
|
||
|
||
Examples:
|
||
|
||
```bash
|
||
./mwcli -d /dev/ttyACM0 run-sequence profile.json
|
||
./mwcli -d /dev/ttyACM0 --csv run.csv run-sequence profile.json
|
||
./mwcli -d /dev/ttyACM0 --sample-period-ms 200 run-sequence profile.json
|
||
```
|
||
|
||
---
|
||
|
||
# CSV logging
|
||
|
||
When `--csv <file>` is used, the logger writes:
|
||
|
||
- `timestamp_utc`
|
||
- `elapsed_s`
|
||
- `context`
|
||
- `step_index`
|
||
- `current_a`
|
||
- `voltage_v`
|
||
- `power_w`
|
||
- `temperature_c`
|
||
- `remote`
|
||
- `status_bits`
|
||
- `status_text`
|
||
|
||
Example:
|
||
|
||
```bash
|
||
./mwcli -d /dev/ttyACM0 --csv monitor.csv -c 20 monitor
|
||
```
|
||
|
||
---
|
||
|
||
# JSON sequence format
|
||
|
||
## Top-level structure
|
||
|
||
A sequence file is a JSON object with these top-level keys:
|
||
|
||
```json
|
||
{
|
||
"name": "example_name",
|
||
"sample_period_ms": 500,
|
||
"safety": {
|
||
"max_voltage": 30.0,
|
||
"max_current": 2.0,
|
||
"max_power": 20.0,
|
||
"abort_on_disconnect": true
|
||
},
|
||
"steps": [
|
||
...
|
||
],
|
||
"abort_sequence": [
|
||
{ "action": "safe" }
|
||
]
|
||
}
|
||
```
|
||
|
||
Important:
|
||
- `steps` is required and must be non-empty
|
||
- `abort_sequence` is required and must be non-empty
|
||
- `abort_sequence` runs at the normal end of the main sequence and also after runtime abort/error paths whenever possible
|
||
|
||
## Top-level fields
|
||
|
||
### `name`
|
||
Optional string.
|
||
|
||
### `sample_period_ms`
|
||
Optional number.
|
||
|
||
Default:
|
||
|
||
```text
|
||
500
|
||
```
|
||
|
||
Purpose:
|
||
- polling interval during `hold`, `hold_until`, loops, ramps, and CSV logging
|
||
|
||
### `safety`
|
||
Optional object.
|
||
|
||
Supported fields:
|
||
- `max_voltage` in volts
|
||
- `max_current` in amps
|
||
- `max_power` in watts
|
||
- `abort_on_disconnect` boolean
|
||
|
||
Practical note:
|
||
- the current engine attempts the `abort_sequence` on runtime failures in general
|
||
- `abort_on_disconnect` is kept in the profile format for future separation of policies, but is not yet handled as a dedicated branch different from other runtime failures
|
||
|
||
### `steps`
|
||
Required array.
|
||
|
||
### `abort_sequence`
|
||
Required array.
|
||
|
||
Typical safe form:
|
||
|
||
```json
|
||
"abort_sequence": [
|
||
{ "action": "safe" }
|
||
]
|
||
```
|
||
|
||
---
|
||
|
||
# Supported actions
|
||
|
||
## `set_mode`
|
||
Stage the operating mode.
|
||
|
||
```json
|
||
{ "action": "set_mode", "mode": "CC" }
|
||
```
|
||
|
||
Accepted `mode` values:
|
||
- `CC` / `current`
|
||
- `CV` / `voltage`
|
||
- `CP` / `power`
|
||
- `CR` / `resistance`
|
||
- `CVINV` / `vinv` / `voltage_inverted`
|
||
|
||
## `set_current`
|
||
```json
|
||
{ "action": "set_current", "value": 0.20 }
|
||
```
|
||
Unit: amps.
|
||
|
||
## `set_voltage`
|
||
```json
|
||
{ "action": "set_voltage", "value": 4.80 }
|
||
```
|
||
Unit: volts.
|
||
|
||
## `set_power`
|
||
```json
|
||
{ "action": "set_power", "value": 2.00 }
|
||
```
|
||
Unit: watts.
|
||
|
||
## `set_resistance`
|
||
```json
|
||
{ "action": "set_resistance", "value": 10.0 }
|
||
```
|
||
Unit: ohms.
|
||
|
||
## `set_vinv`
|
||
```json
|
||
{ "action": "set_vinv", "value": 4.50 }
|
||
```
|
||
Unit: volts.
|
||
|
||
## `output`
|
||
Enable or disable the staged output.
|
||
|
||
```json
|
||
{ "action": "output", "enabled": true }
|
||
```
|
||
|
||
or
|
||
|
||
```json
|
||
{ "action": "output", "enabled": false }
|
||
```
|
||
|
||
## `hold`
|
||
Keep the current staged/active target alive for a duration.
|
||
|
||
```json
|
||
{ "action": "hold", "duration_s": 30 }
|
||
```
|
||
|
||
## `hold_until`
|
||
Keep polling until a condition becomes true or timeout is reached.
|
||
|
||
```json
|
||
{
|
||
"action": "hold_until",
|
||
"timeout_s": 300,
|
||
"condition": {
|
||
"type": "voltage_below",
|
||
"value": 3.00
|
||
}
|
||
}
|
||
```
|
||
|
||
## `ramp_current`
|
||
```json
|
||
{
|
||
"action": "ramp_current",
|
||
"start": 0.20,
|
||
"stop": 1.00,
|
||
"step": 0.10,
|
||
"dwell_s": 20
|
||
}
|
||
```
|
||
|
||
## `ramp_voltage`
|
||
```json
|
||
{
|
||
"action": "ramp_voltage",
|
||
"start": 4.0,
|
||
"stop": 5.0,
|
||
"step": 0.1,
|
||
"dwell_s": 10
|
||
}
|
||
```
|
||
|
||
## `ramp_power`
|
||
```json
|
||
{
|
||
"action": "ramp_power",
|
||
"start": 0.5,
|
||
"stop": 5.0,
|
||
"step": 0.5,
|
||
"dwell_s": 15
|
||
}
|
||
```
|
||
|
||
## `ramp_resistance`
|
||
```json
|
||
{
|
||
"action": "ramp_resistance",
|
||
"start": 100.0,
|
||
"stop": 10.0,
|
||
"step": 10.0,
|
||
"dwell_s": 5
|
||
}
|
||
```
|
||
|
||
## `ramp_vinv`
|
||
```json
|
||
{
|
||
"action": "ramp_vinv",
|
||
"start": 4.8,
|
||
"stop": 4.0,
|
||
"step": 0.1,
|
||
"dwell_s": 10
|
||
}
|
||
```
|
||
|
||
## `repeat`
|
||
Run a nested block a fixed number of times.
|
||
|
||
```json
|
||
{
|
||
"action": "repeat",
|
||
"times": 5,
|
||
"steps": [
|
||
{ "action": "set_current", "value": 0.20 },
|
||
{ "action": "output", "enabled": true },
|
||
{ "action": "hold", "duration_s": 10 },
|
||
{ "action": "output", "enabled": false },
|
||
{ "action": "hold", "duration_s": 5 }
|
||
]
|
||
}
|
||
```
|
||
|
||
## `repeat_until`
|
||
Run a nested block until a condition becomes true.
|
||
|
||
```json
|
||
{
|
||
"action": "repeat_until",
|
||
"timeout_s": 1800,
|
||
"condition": { "type": "voltage_below", "value": 3.20 },
|
||
"steps": [ ... ]
|
||
}
|
||
```
|
||
|
||
Notes:
|
||
- the block runs at least once
|
||
- `timeout_s` is optional
|
||
- if omitted or `0`, the loop is unlimited
|
||
|
||
## `repeat_while`
|
||
Run a nested block while a condition remains true.
|
||
|
||
```json
|
||
{
|
||
"action": "repeat_while",
|
||
"timeout_s": 7200,
|
||
"condition": { "type": "temperature_above", "value": 20.0 },
|
||
"steps": [ ... ]
|
||
}
|
||
```
|
||
|
||
Notes:
|
||
- the condition is checked before each iteration
|
||
- `timeout_s` is optional
|
||
- if omitted or `0`, the loop is unlimited
|
||
|
||
## `safe`
|
||
Immediate safe-state action.
|
||
|
||
```json
|
||
{ "action": "safe" }
|
||
```
|
||
|
||
## `remote`
|
||
Set remote sense on or off.
|
||
|
||
```json
|
||
{ "action": "remote", "enabled": true }
|
||
```
|
||
|
||
---
|
||
|
||
# Conditions
|
||
|
||
Supported condition types:
|
||
- `voltage_below`
|
||
- `voltage_above`
|
||
- `current_below`
|
||
- `current_above`
|
||
- `power_below`
|
||
- `power_above`
|
||
- `temperature_above`
|
||
|
||
Units:
|
||
- voltage conditions: volts
|
||
- current conditions: amps
|
||
- power conditions: watts
|
||
- temperature condition: °C
|
||
|
||
---
|
||
|
||
# `break_if`
|
||
|
||
Any step can carry an optional `break_if` object.
|
||
|
||
Format:
|
||
|
||
```json
|
||
"break_if": {
|
||
"type": "temperature_above",
|
||
"value": 45.0
|
||
}
|
||
```
|
||
|
||
Behaviour:
|
||
- `break_if` is checked whenever a report is read during that step
|
||
- on block steps like `repeat`, `repeat_until`, or `repeat_while`, the `break_if` stays active for the whole nested block
|
||
- if `break_if` becomes true, the main sequence stops and the mandatory `abort_sequence` starts
|
||
|
||
Typical use:
|
||
- thermal guard during long tests
|
||
- abort if measured voltage/current/power crosses a forbidden threshold
|
||
|
||
---
|
||
|
||
# Sequence execution model
|
||
|
||
Recommended staging pattern:
|
||
|
||
1. `set_mode`
|
||
2. `set_current` / `set_voltage` / `set_power` / `set_resistance` / `set_vinv`
|
||
3. `output true`
|
||
4. `hold`, `hold_until`, `ramp_*`, or loop block
|
||
5. `output false` or rely on `abort_sequence`
|
||
|
||
Important:
|
||
- the MightyWatt watchdog requires regular host traffic
|
||
- `hold`, `hold_until`, ramps, and loop checks all provide that traffic
|
||
- a plain one-shot `output true` step with no later polling logic is not suitable for long unattended operation
|
||
|
||
---
|
||
|
||
# Example sequence with loop and safe abort
|
||
|
||
```json
|
||
{
|
||
"name": "repeat_until_cutoff",
|
||
"sample_period_ms": 1000,
|
||
"safety": {
|
||
"max_voltage": 5.0,
|
||
"max_current": 0.6,
|
||
"max_power": 3.0,
|
||
"abort_on_disconnect": true
|
||
},
|
||
"steps": [
|
||
{ "action": "set_mode", "mode": "CC" },
|
||
{
|
||
"action": "repeat_until",
|
||
"timeout_s": 14400,
|
||
"condition": { "type": "voltage_below", "value": 3.20 },
|
||
"break_if": { "type": "temperature_above", "value": 45.0 },
|
||
"steps": [
|
||
{ "action": "set_current", "value": 0.30 },
|
||
{ "action": "output", "enabled": true },
|
||
{ "action": "hold", "duration_s": 60 },
|
||
{ "action": "output", "enabled": false },
|
||
{ "action": "hold", "duration_s": 10 }
|
||
]
|
||
}
|
||
],
|
||
"abort_sequence": [
|
||
{ "action": "safe" }
|
||
]
|
||
}
|
||
```
|
||
|
||
Run it with:
|
||
|
||
```bash
|
||
./mwcli -d /dev/ttyACM0 --csv run.csv run-sequence repeat_until_cutoff.json
|
||
```
|
||
|
||
---
|
||
|
||
# Practical notes
|
||
|
||
- Use `hold` or `run-sequence` for anything longer than a quick manual check.
|
||
- Use `--csv` whenever the data matters.
|
||
- Keep `abort_sequence` simple and safe.
|
||
- Start with conservative limits.
|
||
- `set-vinv` / `ramp_vinv` are advanced functions.
|
||
- Loop timing in practice is affected by serial round-trip time and sample period; do not expect hard real-time behaviour.
|
||
|
||
|
||
## CSV raw mode
|
||
|
||
Use `--csv-raw` together with `--csv <file>` to write elapsed time in **ms** and electrical values in **mA / mV / mW**. This is useful for spreadsheet tools that handle decimal separators poorly.
|