Commands are sent as plain text terminated with \n. JSON mode is also supported — send a valid JSON object and the device will respond in JSON.
hello- Response:
MiniPAR,1.1(plain) /{"device":"MiniPAR","version":"1.1"}(JSON)
- Response:
reboot- Restarts the device. Prints boot info ending with
Ready.
- Restarts the device. Prints boot info ending with
delay_ms,<value>- Example:
delay_ms,500 - Blocks for
<value>milliseconds, then responds with the delay value:500(plain) /{"delay_ms":500}(JSON). Missing/negative value is treated as0.
- Example:
battery- Response:
NaN(plain) /{"battery":"NaN"}(JSON) - Battery measurement not yet implemented.
- Response:
i2c_scan- Response: comma-separated list of I2C addresses that ACK (e.g.
0x39)
- Response: comma-separated list of I2C addresses that ACK (e.g.
spec[,<count>]- Response:
{"spectrometer":{"model":"AS7341","channels":{"f1_415":1.2345,"f2_445":6.7890,...},"par":123.45}}(JSON) /model,ch0,ch1,...,par(plain) - Returns basic counts per channel:
raw_reading / gain / integration_time(counts per second per gain unit). Values are comparable across different gain and integration-time settings. - Also includes the calculated PAR value (same as the
parcommand), computed from this same reading. <count>repeats the measurement that many times (omit, or1, for a single reading); each reading is printed as soon as it's taken. With<count> > 1: JSON response becomes an array of the single-reading objects ([{"spectrometer":{...}},{"spectrometer":{...}},...]); plain response is the single-reading lines joined with;on one line.
- Response:
spec_raw- Response: same format as
specbut raw unscaled integer counts (no normalization applied).
- Response: same format as
spec_flash,<mA>- Example:
spec_flash,10 - Dark read → LED on → lit read. Response:
dark:<values>;lit:<values>;diff:<values>(plain).
- Example:
spec_set_atime,<0-255>- Set spectrometer ATIME integration register. Response: the value set.
spec_set_astep,<0-65534>- Set spectrometer ASTEP register. Response: the value set.
spec_set_gain,<0-10 (AS7341) | 0-12 (AS7343)>- Set spectrometer gain index. Response: the value set.
spec_statusorstatus- Response:
model=<name>,available=<0|1>,atime=<val>,astep=<val>,gain=<val>(plain)
- Response:
set_led,<mA>- Example:
set_led,20 - Response:
{"spectrometer":{"led_current_ma":20}}(JSON) / actual mA set (plain) - LED current capped at 20 mA.
- Example:
par[,<count>]- Response:
123.45 - PAR value in µmol/m²/s, scaled by linear calibration:
y = a·par_raw + b <count>repeats the measurement that many times (omit, or1, for a single reading); each reading is printed as soon as it's taken. With<count> > 1: JSON response becomes an array ([{"par":1.2},{"par":3.4},...]); plain response is the values joined with;on one line.
- Response:
par_raw- Response:
1.23 - Weighted dot product of basic counts (raw / gain / integration_time) and per-channel PAR coefficients. Independent of gain and integration-time settings.
- Response:
cal_par_slope,<value>- Example:
cal_par_slope,10.0 - Response:
{"calibration":{"slope":10.0}} - Set the
acoefficient fory = ax + bscaling. Persisted to NVS.
- Example:
cal_par_intercept,<value>- Example:
cal_par_intercept,2.3 - Response:
{"calibration":{"intercept":2.3}} - Set the
bcoefficient fory = ax + bscaling. Persisted to NVS.
- Example:
get_cal_par- Response:
{"calibration":{"slope":10.0,"intercept":2.3}}(JSON) /slope=10.0,intercept=2.3(plain) - Get the current
a(slope) andb(intercept) coefficients fory = ax + bscaling.
- Response:
set_spec_coeff,<channel>,<value>- Example:
set_spec_coeff,0,0.614975 - Response:
{"spectrometer_coeff":{"channel":0,"value":0.614975}} - Set per-channel PAR coefficient (channel 0–17). Coefficients are applied to basic counts (raw / gain / integration_time), so they must account for the desired normalization. Persisted to NVS.
- Default coefficients are pre-scaled for the default AS7341 settings (ATIME=100, ASTEP=999, GAIN=2×); re-derive from calibration if defaults are changed.
- Example:
get_spec_coeff- Response:
{"spectrometer_coeffs":{"channels":{"0":0.614975,"1":0.053037,...}}} - Get all 18 per-channel PAR coefficients.
- Response:
get_spec_coeff,<channel>- Example:
get_spec_coeff,0 - Response:
{"spectrometer_coeff":{"channel":0,"value":0.614975}} - Get a specific per-channel PAR coefficient.
- Example:
set_name,<string>- Response:
{"device_name":"MyDevice"} - Set custom device name. Persisted to NVS.
- Response:
get_name- Response:
{"device_name":"MyDevice"} - Get current device name.
- Response:
Detected automatically at boot (I2C address 0x76 or 0x77); all commands below respond with error:not_available (plain) / {"bme280":{"error":"not_available"}} (JSON) if no BME280 is fitted. Temperature, pressure, and humidity are all enabled by default, at the highest oversampling (x16), IIR filter off, one-shot read mode.
bme_status- Response (plain):
continuous=<0|1>,continuous_active=<0|1>,temp_comp=<value>,temp_en=<0|1>,temp_osrs=<0-5>,press_en=<0|1>,press_osrs=<0-5>,hum_en=<0|1>,hum_osrs=<0-5>,iir=<0-4> - Response (JSON):
{"bme280_status":{"available":true,"continuous_mode":false,"continuous_active":false,"temperature_compensation_c":0.00,"temperature":{"enabled":true,"oversampling":5},"pressure":{"enabled":true,"oversampling":5},"humidity":{"enabled":true,"oversampling":5},"iir_filter":0}}
- Response (plain):
bme_set_temp_enable,<0|1>- Enable/disable temperature in
bme_get_tphoutput. Temperature is still sampled internally regardless (pressure/humidity compensation depend on it) — this only affects reporting.
- Enable/disable temperature in
bme_set_press_enable,<0|1>- Enable/disable pressure in
bme_get_tphoutput.
- Enable/disable pressure in
bme_set_hum_enable,<0|1>- Enable/disable humidity in
bme_get_tphoutput.
- Enable/disable humidity in
bme_set_temp_oversample,<0-5>- Oversampling:
0=off (clamped to1, since temperature must always be sampled),1=x1,2=x2,3=x4,4=x8,5=x16 (default).
- Oversampling:
bme_set_press_oversample,<0-5>- Same scale as above;
0=channel skipped by the sensor.
- Same scale as above;
bme_set_hum_oversample,<0-5>- Same scale as above;
0=channel skipped by the sensor.
- Same scale as above;
bme_set_iir,<0-4>- IIR filter coefficient:
0=off (default),1=x2,2=x4,3=x8,4=x16.
- IIR filter coefficient:
bme_set_continuous,<0|1>0(default) = one-shot: everybme_get_tphcall takes its own forced-mode measurement.1= continuous: the chip free-runs in normal mode;bme_get_tphblocks only on the first call after enabling (waiting for that first conversion), then returns whatever the chip's background cycle last produced.
bme_set_temp_comp,<value>- Set the temperature compensation offset in °C, added to every raw temperature reading (and folded into the pressure/humidity compensation math) to null out self-heating bias. Persisted to NVS.
bme_get_temp_comp- Response: current temperature compensation offset in °C.
bme_get_tph[,<count>](alias:tph[,<count>])- Response (plain):
<temperature_c>,<pressure_hpa>,<humidity_pct>— positional CSV, blank field for a disabled channel. - Response (JSON):
{"bme280":{"temperature_c":23.45,"pressure_hpa":1013.25,"humidity_pct":45.20}}—nullfor a disabled channel. - Behavior depends on
bme_set_continuous: one-shot mode (default) takes a fresh forced-mode reading every call; continuous mode waits for the first conversion only on the first call after being enabled, then returns the most recent free-running reading on every call after that. <count>repeats the measurement that many times (omit, or1, for a single reading); each reading is printed as soon as it's taken. With<count> > 1: JSON response becomes an array of the single-reading objects; plain response is the single-reading CSV rows joined with;on one line.
- Response (plain):
The LED on GPIO 10 provides a visual indication of spectrometer state:
| LED state | Meaning |
|---|---|
| Off | No spectrometer detected at boot |
| Solid on | Spectrometer detected, all channels within range |
| Blinking 20 Hz | At least one spectrometer channel is saturated |
Saturation is checked automatically on every spectrometer read (spec, spec_raw, par, par_raw, etc.). The LED returns to solid-on as soon as the next read finds all channels within range. Reduce gain or integration time (spec_set_gain, spec_set_atime, spec_set_astep) to clear saturation.
- Command terminator:
\n(\ris ignored) - PAR units: µmol/m²/s
- Basic counts:
raw_reading / gain / integration_time, whereintegration_time = (ATIME+1) × (ASTEP+1) × 2.78 µs. Used byspec,par, andpar_raw— values are gain/integration-time independent. - Default AS7341 settings: ATIME=100, ASTEP=999, GAIN=2× (integration time ≈ 280.8 ms). Per-channel PAR coefficients stored in NVS are calibrated for basic counts at these defaults.
FW Design (L. Grabowski, L. Caracciolo),
HW Design (L. Grabowski)
