A modular embedded telemetry system built in C (STM32 firmware) and Python (host application). The firmware streams structured UART telemetry packets; the host app parses, logs, analyzes, and reports on them.
| Layer | Technology | Purpose |
|---|---|---|
| Firmware | C99, STM32 HAL | Sample sensors, detect faults, stream JSON telemetry |
| Transport | USB serial / UART 115200 bps | Newline-delimited JSON packets |
| Host app | Python 3.10+ | Parse, log to CSV/JSONL, live dashboard, Markdown report |
No hardware required to run the Python pipeline — use simulate mode to generate fake telemetry.
- STM32 Nucleo-F401RE (or compatible Nucleo board)
- 10 kΩ potentiometer on PA0 (ADC input)
- B1 USER push button on PC13 (onboard)
- Green LED LD2 on PA5 (onboard)
- Red LED on PB3 with 220 Ω series resistor
- MPU-6050 or BME280 on I2C1 (PB8/PB9)
See docs/wiring.md for full wiring diagrams.
- Firmware: C99,
stdio.h/string.honly (portable; swaps to STM32 HAL for hardware) - Host: Python 3.10+, pyserial, pandas, matplotlib, pytest
- Protocol: Newline-delimited JSON — human-readable, easily parsed
pip install -r host/requirements.txtpython -m telemetry_client.cli simulate \
--csv data/sample_logs/simulated.csv \
--jsonl data/sample_logs/simulated.jsonl \
--duration 30python -m telemetry_client.cli run \
--port COM5 \
--baud 115200 \
--csv data/logs/run.csv \
--jsonl data/logs/run.jsonlpython -m telemetry_client.cli command --port COM5 --cmd PING
python -m telemetry_client.cli command --port COM5 --cmd "SET_RATE 50"python -m telemetry_client.cli report \
--input data/sample_logs/sample_run.jsonl \
--output reports/run_report.mdpytest host/tests -vAll 19 tests pass without hardware using the built-in simulator.
The firmware is written in STM32-oriented C but currently runs as a host-PC simulation.
All hardware dependencies (HAL_GetTick, HAL_Delay, GPIO, ADC, I2C) are stubbed with
portable C99 equivalents so the packet protocol and module structure can be developed and
validated without hardware.
cd firmware
make
./firmware_simThis runs 30 simulated loop iterations, printing JSON telemetry packets to stdout that are directly parsable by the Python host.
Porting to real STM32 hardware requires: replacing system_time.c with HAL calls,
wiring sensor_adc.c to HAL_ADC_*, sensor_i2c.c to HAL_I2C_*, gpio_status.c
to HAL_GPIO_*, and adding a CubeMX-generated project (main.h, clock config, linker
script). The module interfaces are designed to make this a drop-in replacement.
| Command | Description |
|---|---|
PING |
Check connectivity |
START |
Begin streaming telemetry |
STOP |
Stop streaming |
GET_STATUS |
Query status and active faults |
GET_SENSOR |
Request sensor snapshot |
SET_RATE <ms> |
Set telemetry period (10–5000 ms) |
CLEAR_FAULTS |
Clear all active faults |
RESET_STATS |
Reset packet/fault counters |
Telemetry packet:
{"type":"telemetry","seq":42,"time_ms":4200,"adc_mv":1820,"sensor_x":0.02,"sensor_y":-0.01,"sensor_z":0.98,"button":0,"status":"OK","faults":[]}Fault packet:
{"type":"telemetry","seq":91,"time_ms":9100,"adc_mv":4095,"sensor_x":0.00,"sensor_y":0.00,"sensor_z":0.00,"button":1,"status":"FAULT","faults":["ADC_OUT_OF_RANGE","BUTTON_EVENT"]}(Add media/dashboard_screenshot.png and media/wiring_photo.png after first run)
| File | Contents |
|---|---|
| docs/architecture.md | Firmware + host architecture, data flow |
| docs/serial_protocol.md | Packet schema, commands, fault types |
| docs/test_plan.md | Unit tests, hardware tests, acceptance criteria |
| docs/wiring.md | STM32 Nucleo wiring for all peripherals |