{"id":31056063,"url":"https://github.com/ka5j/obd2_development","last_synced_at":"2026-04-09T02:02:06.434Z","repository":{"id":313548824,"uuid":"1051805287","full_name":"ka5j/obd2_development","owner":"ka5j","description":"Bench-only, read-only OBD-Lite MVP pairing Raspberry Pi with STM32 (NUCLEO-F446RE). MCU streams newline-terminated JSON over UART (115200) via ST-LINK VCP; Pi reads and logs now. Next: BLE/GATT bridge and a simulated two-node CAN bench. Simple, reproducible, Pi-first workflow with VS Code + PlatformIO.","archived":false,"fork":false,"pushed_at":"2025-09-06T23:36:31.000Z","size":42,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2025-09-15T05:22:37.258Z","etag":null,"topics":["ble","bluetooth-low-energy","c","cpp","linux","matplotlib","obd2","obd2-monitor","obd2-reader","obd2-scanner","platformio","python","python3","rasberry-pi","rasberry-pi-5","rasberrypi","stm32","stm32cube","stm32f446re-nucleo","vscode"],"latest_commit_sha":null,"homepage":"","language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ka5j.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.md","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2025-09-06T18:54:15.000Z","updated_at":"2025-09-06T23:36:34.000Z","dependencies_parsed_at":"2025-09-06T21:22:57.011Z","dependency_job_id":"7baa70aa-f7a6-4f76-875c-ad672b722708","html_url":"https://github.com/ka5j/obd2_development","commit_stats":null,"previous_names":["ka5j/obd2_development"],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/ka5j/obd2_development","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ka5j%2Fobd2_development","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ka5j%2Fobd2_development/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ka5j%2Fobd2_development/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ka5j%2Fobd2_development/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ka5j","download_url":"https://codeload.github.com/ka5j/obd2_development/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ka5j%2Fobd2_development/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31581864,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-08T14:31:17.711Z","status":"online","status_checked_at":"2026-04-09T02:00:06.848Z","response_time":112,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ble","bluetooth-low-energy","c","cpp","linux","matplotlib","obd2","obd2-monitor","obd2-reader","obd2-scanner","platformio","python","python3","rasberry-pi","rasberry-pi-5","rasberrypi","stm32","stm32cube","stm32f446re-nucleo","vscode"],"created_at":"2025-09-15T05:01:41.845Z","updated_at":"2026-04-09T02:02:06.413Z","avatar_url":"https://github.com/ka5j.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# obd2_development — Raspberry Pi + STM32 (OBD‑Lite Bench MVP)\n\nThis repo builds a **bench‑only, read‑only OBD‑lite MVP**: an STM32 device emits telemetry as **newline‑terminated JSON**; a Raspberry Pi reads it and (later) forwards it to a phone app over **BLE**. Eventually, the JSON values will come from simulated CAN on a two‑node bench bus. The goal is to keep everything **simple, reproducible, and Pi‑first**.\n\n\u003e **Status / Scope**\n\u003e - Firmware lives in `firmware/` (PlatformIO project for **NUCLEO‑F446RE**).\n\u003e - VS Code tasks in `.vscode/tasks.json` give one‑click **Build**, **Upload**, **Monitor**, plus a **Serial logger** task.\n\u003e - A tiny bridge script logs the STM32 JSON to CSV on the Pi (`bridge/serial_logger.py`).\n\u003e - CI builds firmware on every push touching `firmware/**`.\n\u003e - Future: BLE bridge / mobile app, bench CAN feeding the same JSON fields.\n\n---\n\n## 0) Clone \u0026 Open\n\n```bash\ngit clone https://github.com/ka5j/obd2_development\ncd obd2_development\ncode obd2_development.code-workspace\n```\n\nIf you don’t use VS Code, you can still build from CLI (see below).\n\n---\n\n## 1) Repo layout\n\n```\nobd2_development/\n├─ README.md\n├─ LOG.md\n├─ obd2_development.code-workspace         # VS Code workspace (root + firmware/)\n├─ .vscode/\n│  └─ tasks.json                           # Root tasks (run PIO in firmware/)\n├─ firmware/                               # PlatformIO project (STM32F446RE)\n│  ├─ platformio.ini\n│  └─ src/\n│     ├─ main.c\n│     └─ retarget.c                        # printf() → USART2 (VCP)\n├─ bridge/                                 # Pi tooling\n│  ├─ serial_logger.py\n│  └─ requirements.txt\n├─ scripts/\n│  └─ bootstrap_pi.sh                      # One‑time setup on Raspberry Pi\n├─ .github/workflows/\n│  └─ firmware-ci.yml                      # CI: build firmware on push/PR\n└─ .editorconfig / .clang-format / .pre-commit-config.yaml\n```\n\n---\n\n## 2) Requirements\n\n**Hardware**\n\n- Raspberry Pi (3/4/5) with Internet access\n- STM32F446RE dev board (e.g., **NUCLEO‑F446RE**) with onboard ST‑LINK\n- USB‑A ↔ Micro‑B (or appropriate) cable\n\n**Software**\n\n- VS Code on the Pi (recommended)\n- VS Code extensions: **PlatformIO IDE**, **C/C++**\n- PlatformIO Core (installed by the extension automatically)\n- Python 3.x (for the bridge/venv)\n- Git\n\n---\n\n## 3) Hardware notes (VCP \u0026 pins)\n\n- **UART/VCP**: `USART2` on **PA2/PA3** is, by default, wired to the **ST‑LINK Virtual COM Port**. That’s how `printf()` reaches your `/dev/ttyACM*` on the Pi.\n- **Default solder bridges for VCP**: **SB13 = ON**, **SB14 = ON**, **SB62 = OFF**, **SB63 = OFF** (target USART2 ↔ ST‑LINK). If you want PA2/PA3 on the Arduino headers instead, flip those (SB62/SB63 ON, SB13/SB14 OFF).\n- **Baud**: 115200 8‑N‑1 (repo defaults).\n\n_Reference: ST UM1724 (STM32 Nucleo‑64, MB1136)._\n\n---\n\n## 4) One‑time bootstrap on the Pi (udev + venv)\n\nFrom repo root, run:\n\n```bash\n./scripts/bootstrap_pi.sh\n# Re‑plug the NUCLEO.\n# If you were added to the \"dialout\" group, log out/in or reboot.\n```\n\nQuick checks:\n\n```bash\npio device list\nls /dev/ttyACM*\n```\n\nThis script:\n- Creates a **virtualenv** at `.venv/` and installs `bridge/requirements.txt` (pyserial).\n- Installs **PlatformIO udev rules** and reloads udev.\n- Adds the current user to the **dialout** group for serial access.\n\n---\n\n## 5) Open the workspace \u0026 tasks (VS Code)\n\nOpen `obd2_development.code-workspace` (repo root). Install the recommended extensions when prompted.\n\nUse `Terminal → Run Task…` to run:\n\n- **PIO: Build (firmware)** — build in `firmware/`\n- **PIO: Upload (firmware)** — flash via ST‑LINK\n- **PIO: Monitor (firmware)** — open serial monitor at **115200 baud**\n- **Bridge: Serial logger** — run the Pi logger against `/dev/ttyACM*` and write CSV into `logs/`\n\nThe tasks always run inside `firmware/` so paths are consistent.\n\n---\n\n## 6) Build / Upload / Monitor (CLI)\n\n```bash\n# Build\ncd firmware\npio run\n\n# Upload (flash)\npio run -t upload\n\n# Monitor (115200 baud)\npio device monitor --baud 115200\n```\n\nArtifacts:\n- `firmware/.pio/build/nucleo_f446re/firmware.elf`\n\n---\n\n## 7) Firmware notes (printf, float, JSON)\n\n**Retarget `printf()` to USART2 (VCP)**\n\n`firmware/src/retarget.c`:\n\n```c\n#include \"stm32f4xx_hal.h\"\n#include \u003cstdint.h\u003e\n#include \u003csys/unistd.h\u003e // write\nextern UART_HandleTypeDef huart2;\nint _write(int file, char *ptr, int len) {\n  (void)file;\n  HAL_UART_Transmit(\u0026huart2, (uint8_t*)ptr, (uint16_t)len, HAL_MAX_DELAY);\n  return len;\n}\n```\n\n**Float formatting with newlib‑nano**\n\nTo ensure `printf(\"%.1f\", some_float)` actually prints, `platformio.ini` adds the linker symbol for float IO:\n\n```ini\nbuild_flags =\n  -Wl,--undefined,_printf_float\n  -Wl,--gc-sections\n```\n\n**Example JSON (10 Hz) in `main.c`**\n\n```c\nstatic uint32_t seq = 0;\nuint32_t t = HAL_GetTick();\nint rpm = 1650;\nfloat speed_kph = 42.1f;\nint coolant_c = 78;\nfloat batt_v = 12.1f;\n\nprintf(\"{\\\"seq\\\":%lu,\\\"tx_ms\\\":%lu,\\\"rpm\\\":%d,\\\"speed_kph\\\":%.1f,\\\"coolant_c\\\":%d,\\\"batt_v\\\":%.1f}\\r\\n\",\n       (unsigned long)seq++,\n       (unsigned long)t,\n       rpm, speed_kph, coolant_c, batt_v);\n\nHAL_Delay(100); // ~10 Hz\n```\n\n\u003e Tip: Make sure `USART2` is initialized in CubeMX (or your HAL init code) and the default SB settings for VCP are intact.\n\n**PlatformIO on ARM64 (Pi) — toolchain pin**\n\nIf needed on aarch64 Pis, `platformio.ini` pins a known‑good GCC toolchain:\n\n```ini\nplatform_packages = platformio/toolchain-gccarmnoneeabi@=1.100301.220327\n```\n\n---\n\n## 8) Bridge (Pi) — CSV logger\n\n**Run from VS Code tasks** (“Bridge: Serial logger”) or directly:**\n\n```bash\n# ensure venv is active if running manually\nsource .venv/bin/activate\npython bridge/serial_logger.py --baud 115200 --outdir logs\n# optional: --port /dev/ttyACM0\n```\n\nBehavior:\n- Auto‑detects `/dev/ttyACM*` / `/dev/ttyUSB*` (can override with `--port`).\n- Writes `logs/telemetry_YYYYmmdd_HHMMSS.csv` with a header derived from the first JSON object.\n- Skips malformed lines but prints them to stderr for debugging.\n\n---\n\n## 9) CI (GitHub Actions)\n\nEvery push/PR that touches `firmware/**` triggers a build in CI (`.github/workflows/firmware-ci.yml`). This protects against config drift and keeps team builds reproducible.\n\n---\n\n## 10) Roadmap (bench‑only MVP)\n\n1. UART JSON → Pi CSV logger (latency, packet loss)\n2. Pi BLE bridge (BlueZ GATT server; fixed service/characteristics; 5–10 Hz notify)\n3. Trip logic (start/stop thresholds) + CSV export parity\n4. Alerts (unplug/tow) — event JSON\n5. CAN bench (Pi + CANable ↔ SN65HVD230 ↔ STM32) — fill the same JSON fields\n\n**Targets** (later): median latency \u003c 200 ms; packet loss \u003c 1%; trip start/stop \u003e 95%; alerts \u003c 1 s.\n\n---\n\n## 11) Development standards\n\n- **C/C++ formatting**: `.clang-format` (LLVM‑style, width=100, 2‑space indents)\n- **Editor defaults**: `.editorconfig` (LF, UTF‑8, final newline)\n- **Python**: `pre-commit` runs **black**, **ruff**, and **isort**\n\nInstall hooks locally:\n\n```bash\npip install pre-commit\npre-commit install\n```\n\n---\n\n## 12) Troubleshooting (fast)\n\n- **No serial device / permissions**\n  - Re‑run `./scripts/bootstrap_pi.sh`, re‑plug the board, and confirm `dialout` group.\n  - `pio device list`, `ls /dev/ttyACM*`\n\n- **Serial shows nothing**\n  - Confirm **baud 115200**, VCP is enabled by default (see SBs), and your `main.c` prints **newline‑terminated** JSON.\n  - Check the right port: the NUCLEO usually appears as `/dev/ttyACM0`.\n\n- **Floats print `0.0` or garbage**\n  - Ensure `-Wl,--undefined,_printf_float` is present in `platformio.ini` (see §7).\n\n- **VS Code squiggles on HAL headers**\n  - Open the workspace file, then run “**PlatformIO: Rebuild IntelliSense Index**”.\n\n- **Upload errors (Linux)**\n  - Make sure **udev rules** are installed and current; re‑plug after installing.\n\n---\n\n## 13) Useful commands\n\n```bash\npio device list\npio device monitor --baud 115200\npio run                 # build\npio run -t upload       # flash\n```\n\n---\n\n## 14) Credits / Board\n\n- Target board: **NUCLEO‑F446RE** (STM32F446RET6, 180 MHz, 512 KB Flash, 128 KB RAM).\n- Tooling: **VS Code + PlatformIO** (PIO Core CLI under the hood).\n\n---\n\n## 15) License\n\nMIT — see `LICENSE`.\n\n---\n\n### References\n\n- ST UM1724 (STM32 Nucleo‑64, MB1136) — USART2 ↔ ST‑LINK VCP default SBs; VCP mapping.  \n  https://www.st.com/resource/en/user_manual/um1724-stm32-nucleo64-boards-mb1136-stmicroelectronics.pdf\n- PlatformIO udev rules (Linux).  \n  https://docs.platformio.org/en/stable/core/installation/udev-rules.html\n- newlib‑nano \u0026 float printf background.  \n  https://mcuoneclipse.com/2023/01/28/which-embedded-gcc-standard-library-newlib-newlib-nano/\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fka5j%2Fobd2_development","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fka5j%2Fobd2_development","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fka5j%2Fobd2_development/lists"}