Prerequisites
- Rust toolchain with
thumbv7em-none-eabihftarget - probe-rs for flashing (
cargo install probe-rs-tools) - A USB-UART adapter (CH340 or FTDI) for the UART interface
- A J-Link or ST-Link connected to the 10-pin SWD header (J3)
1. Clone the Repository
git clone https://github.com/yasimbt/gas-sensor-fw.git
cd gas-sensor-fw
2. Build and Flash
cd fw
cargo run --release
On boot the firmware sends:
{"cmd":"FW","data":"0.1.0"}
3. Verify UART Communication
Connect a USB-UART adapter: PA9 → RX, PA10 → TX, GND → GND. 9600 baud, 8N1.
import serial, json
ser = serial.Serial('/dev/ttyUSB0', 9600, timeout=2)
def cmd(c, d=""):
ser.write((json.dumps({"cmd": c, "data": d}) + "\n").encode())
return json.loads(ser.readline())
print(cmd("FW")) # {'cmd': 'ACK', 'data': '0.1.0'}
print(cmd("STATUS")) # {'cmd': 'STATUS', 'data': '1021.50:UNCALIBRATED'}
4. Two-Point Calibration
Zero (clean air)
1. Expose sensor to clean air (0 ppm)
2. Poll STABILITY → wait until is_stable=1 (~30 s)
3. Send ZERO → baseline stored to flash
Span (known concentration)
1. Apply certified span gas cylinder (e.g. 25 ppm)
2. Wait T90 (~30–35 s)
3. Send SPAN:25 → ChA and ChB computed and applied simultaneously
4. Verify GAS reads ≈ 25 ppm
5. Remove gas → verify return to ≈ 0 ppm
Calibration survives power cycles (stored in flash page 63).
5. Read Concentration
print(cmd("GAS")) # {'cmd': 'GAS', 'data': '24.87'}
print(cmd("TEMP")) # {'cmd': 'TEMP', 'data': '23.6'}
print(cmd("STABILITY")) # {'cmd': 'STABILITY', 'data': '1250:30:1'}
See UART Command Interface for the full command reference.