{"id":48444524,"url":"https://github.com/htl-stp-ecer/stm32-data-reader","last_synced_at":"2026-05-23T10:08:07.506Z","repository":{"id":349133602,"uuid":"1144883175","full_name":"htl-stp-ecer/stm32-data-reader","owner":"htl-stp-ecer","description":"Raspberry Pi ↔ STM32 SPI bridge — reads sensor data and publishes it via LCM for RaccoonOS","archived":false,"fork":false,"pushed_at":"2026-05-23T08:36:10.000Z","size":47197,"stargazers_count":1,"open_issues_count":3,"forks_count":0,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-05-23T09:33:44.855Z","etag":null,"topics":["botball","cpp","lcm","raccoon-os","raspberry-pi","robotics","spi","stm32"],"latest_commit_sha":null,"homepage":"https://raccoon-docs.pages.dev/","language":"C","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"gpl-3.0","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/htl-stp-ecer.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"COPYING","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":"2026-01-29T06:43:03.000Z","updated_at":"2026-05-23T08:33:56.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/htl-stp-ecer/stm32-data-reader","commit_stats":null,"previous_names":["htl-stp-ecer/stm32-data-reader"],"tags_count":35,"template":false,"template_full_name":null,"purl":"pkg:github/htl-stp-ecer/stm32-data-reader","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/htl-stp-ecer%2Fstm32-data-reader","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/htl-stp-ecer%2Fstm32-data-reader/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/htl-stp-ecer%2Fstm32-data-reader/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/htl-stp-ecer%2Fstm32-data-reader/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/htl-stp-ecer","download_url":"https://codeload.github.com/htl-stp-ecer/stm32-data-reader/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/htl-stp-ecer%2Fstm32-data-reader/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":33391002,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-23T04:15:53.637Z","status":"ssl_error","status_checked_at":"2026-05-23T04:15:53.242Z","response_time":53,"last_error":"SSL_read: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"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":["botball","cpp","lcm","raccoon-os","raspberry-pi","robotics","spi","stm32"],"created_at":"2026-04-06T17:04:05.118Z","updated_at":"2026-05-23T10:08:07.494Z","avatar_url":"https://github.com/htl-stp-ecer.png","language":"C","funding_links":[],"categories":[],"sub_categories":[],"readme":"\u003cdiv align=\"center\"\u003e\n\n\u003cimg src=\"https://raw.githubusercontent.com/htl-stp-ecer/.github/main/profile/raccoon-logo.svg\" alt=\"stm32-data-reader\" width=\"100\"/\u003e\n\n# stm32-data-reader\n\n**Raspberry Pi ↔ STM32 SPI bridge — reads sensor data and publishes it via LCM for RaccoonOS.**\n\n[![Build \u0026 Release](https://github.com/htl-stp-ecer/stm32-data-reader/actions/workflows/build-release.yml/badge.svg)](https://github.com/htl-stp-ecer/stm32-data-reader/actions/workflows/build-release.yml)\n[![Latest Release](https://img.shields.io/github/v/release/htl-stp-ecer/stm32-data-reader)](https://github.com/htl-stp-ecer/stm32-data-reader/releases/latest)\n[![License: GPL v3](https://img.shields.io/badge/License-GPLv3-blue.svg)](COPYING)\n![C++20](https://img.shields.io/badge/C%2B%2B20-00599C?logo=cplusplus\u0026logoColor=white)\n![Platform](https://img.shields.io/badge/Platform-Raspberry%20Pi%20ARM64-A22846?logo=raspberrypi\u0026logoColor=white)\n![STM32](https://img.shields.io/badge/STM32-03234B?logo=stmicroelectronics\u0026logoColor=white)\n\n\u003e 📖 **Full documentation at [raccoon-docs.pages.dev](https://raccoon-docs.pages.dev/)**\n\n\u003c/div\u003e\n\n---\n\nThis service runs on the Raspberry Pi inside the [KIPR Wombat](https://www.kipr.org/kipr/hardware-software) and acts as the hardware bridge between the STM32 microcontroller and the rest of RaccoonOS. It communicates with the STM32 over SPI, reads IMU, analog, and digital sensor data, and publishes everything onto the LCM multicast bus — where [RaccoonLib](https://github.com/htl-stp-ecer/raccoon-lib) and [botui](https://github.com/htl-stp-ecer/botui) can consume it. Motor and servo commands flow the other way: received from LCM and forwarded to the STM32.\n\n---\n\n## What it bridges\n\n**Publishes (STM32 → LCM):**\n- IMU — gyroscope, accelerometer, magnetometer, orientation quaternion, calibration accuracy\n- Analog inputs (6 ports), digital inputs (16-bit)\n- Motor back-EMF readings (4 ports)\n- System — battery voltage, IMU temperature, CPU temperature\n\n**Subscribes (LCM → STM32):**\n- Motor power and stop commands (4 ports)\n- Servo position commands (4 ports)\n- BEMF reset, scale, and offset commands\n\nFull channel reference: see [LCM Channels](#lcm-channels) below.\n\n---\n\n## Building\n\nThe recommended build targets ARM64 via Docker cross-compilation.\n\n```bash\n./build.sh                       # Release build (reader + firmware)\nSKIP_FIRMWARE=1 ./build.sh       # Reader only\nCMAKE_BUILD_TYPE=Debug ./build.sh\nFORCE_RECONFIGURE=1 ./build.sh   # Force CMake reconfiguration\nREBUILD_IMAGE=1 ./build.sh       # Rebuild Docker image\n```\n\nOutput: `build/stm32_data_reader`\n\n### Local build (mock SPI, no hardware needed)\n\n```bash\nmkdir -p cmake-build-debug \u0026\u0026 cd cmake-build-debug\ncmake .. -DUSE_SPI_MOCK=ON -DCMAKE_BUILD_TYPE=Debug\ncmake --build . -j$(nproc)\n```\n\n| CMake option | Default | Description |\n|:-------------|:--------|:------------|\n| `USE_SPI_MOCK` | `ON` | Mock SPI — build and test without hardware |\n| `CMAKE_BUILD_TYPE` | `Release` | `Release`, `Debug`, `RelWithDebInfo` |\n\n---\n\n## Deployment\n\n```bash\n./deploy.sh                              # Build both + deploy to Pi + flash firmware\nRPI_HOST=\u003cyour-pi-ip\u003e ./deploy.sh        # Override target\nRPI_USER=myuser ./deploy.sh\nRPI_DIR=/opt/stm32_data_reader ./deploy.sh\n```\n\nThe deploy script cross-compiles, stops any running service, copies the binary and systemd service files, and sets up the LCM multicast loopback service.\n\n### Running as a systemd service\n\n```bash\nsudo systemctl enable --now stm32_data_reader\njournalctl -u stm32_data_reader -f\n```\n\n---\n\n## Firmware\n\nThe STM32 firmware lives in `firmware/` and shares the SPI protocol header (`shared/spi/pi_buffer.h`) with the reader — single source of truth for both sides.\n\n```bash\n# Build firmware only\ncd firmware \u0026\u0026 bash build.sh\n\n# Build firmware natively (requires gcc-arm-none-eabi)\ncd firmware \u0026\u0026 mkdir -p build \u0026\u0026 cd build\ncmake -G \"Unix Makefiles\" -DCMAKE_TOOLCHAIN_FILE=../CMake/GNU-ARM-Toolchain.cmake ..\ncmake --build . -- -j$(nproc)\n```\n\n`./build.sh` from the repo root builds both reader and firmware together. `./deploy.sh` flashes the firmware to the STM32 after copying.\n\n---\n\n## Architecture\n\n\u003cdiv align=\"center\"\u003e\n  \u003cimg src=\"https://raw.githubusercontent.com/htl-stp-ecer/stm32-data-reader/main/docs/architecture.svg\" alt=\"stm32-data-reader architecture\" width=\"700\"/\u003e\n\u003c/div\u003e\n\n| Component | What it does |\n|:----------|:-------------|\n| `Application` | Main orchestrator — lifecycle, signal handling |\n| `DeviceController` | Owns SPI state: motors, servos, sensors |\n| `DataPublisher` | Publishes sensor data to LCM with change detection |\n| `CommandSubscriber` | Receives LCM commands and routes to DeviceController |\n| `LcmBroker` | Typed publish/subscribe wrapper (PIMPL pattern) |\n| `Spi` / `SpiMock` | Hardware abstraction toggled via `USE_SPI_MOCK` |\n\n---\n\n## LCM Channels\n\n### Published (sensor data)\n\n| Channel | Type | Description |\n|:--------|:-----|:------------|\n| `libstp/gyro/value` | `vector3f_t` | Gyroscope (rad/s) |\n| `libstp/accel/value` | `vector3f_t` | Accelerometer (m/s²) |\n| `libstp/mag/value` | `vector3f_t` | Magnetometer |\n| `libstp/imu/quaternion` | `quaternion_t` | Orientation quaternion |\n| `libstp/imu/temp/value` | `scalar_f_t` | IMU temperature (°C) |\n| `libstp/cpu/temp/value` | `scalar_f_t` | CPU temperature (°C) |\n| `libstp/battery/voltage` | `scalar_f_t` | Battery voltage |\n| `libstp/analog/{0-5}/value` | `scalar_i32_t` | Analog sensor readings |\n| `libstp/digital/{0-15}/value` | `scalar_i32_t` | Digital input states |\n| `libstp/bemf/{0-3}/value` | `scalar_i32_t` | Motor back-EMF |\n| `libstp/gyro/accuracy` | `scalar_i8_t` | Gyro calibration status (0–3) |\n| `libstp/accel/accuracy` | `scalar_i8_t` | Accelerometer calibration status |\n| `libstp/mag/accuracy` | `scalar_i8_t` | Magnetometer calibration status |\n| `libstp/imu/quaternion_accuracy` | `scalar_i8_t` | Quaternion accuracy |\n\n### Subscribed (commands)\n\n| Channel | Type | Description |\n|:--------|:-----|:------------|\n| `libstp/motor/{0-3}/power_cmd` | `scalar_i32_t` | Motor power (−100 to 100) |\n| `libstp/motor/{0-3}/stop_cmd` | `scalar_i32_t` | Stop motor |\n| `libstp/servo/{0-3}/position_cmd` | `scalar_i32_t` | Servo position |\n| `libstp/bemf/{0-3}/reset_cmd` | `scalar_i32_t` | Reset BEMF accumulator |\n| `libstp/bemf/{0-3}/scale_cmd` | `scalar_f_t` | BEMF scale factor |\n| `libstp/bemf/{0-3}/offset_cmd` | `scalar_f_t` | BEMF offset |\n| `libstp/bemf/nominal_voltage_cmd` | `scalar_i32_t` | Nominal battery voltage |\n| `libstp/system/dump_request` | `scalar_i32_t` | Request full data dump |\n\n---\n\n## Network setup for LCM\n\nLCM uses UDP multicast. Enable the loopback route for local-only operation:\n\n```bash\nsudo systemctl enable --now lcm-loopback-multicast\n# or manually:\nsudo ip route add 239.255.76.67/32 dev lo\n```\n\nFor network operation, ensure multicast is enabled and UDP port 7667 is open.\n\n---\n\n## Project structure\n\n```\nstm32-data-reader/\n├── src/wombat/\n│   ├── Application.cpp\n│   ├── services/            # DataPublisher, CommandSubscriber, DeviceController\n│   ├── hardware/            # Spi, SpiMock\n│   ├── messaging/           # LcmBroker\n│   └── core/                # Logger, Result\u003cT\u003e, utilities\n├── include/wombat/          # Headers matching src/\n├── shared/spi/pi_buffer.h   # SPI protocol (shared with STM32 firmware)\n├── firmware/                # STM32 firmware source\n├── lcm-messages/types/      # LCM message definitions (.lcm files)\n├── systemd/                 # Service files\n├── build.sh                 # Cross-compilation script\n├── deploy.sh                # Build + deploy + flash\n└── Dockerfile               # ARM64 build environment\n```\n\n---\n\n## Part of RaccoonOS\n\n| Repository | What it is |\n|:-----------|:-----------|\n| [raccoon-lib](https://github.com/htl-stp-ecer/raccoon-lib) | Core robotics library — consumes LCM data published here |\n| [raccoon-transport](https://github.com/htl-stp-ecer/raccoon-transport) | Shared LCM message types |\n| [botui](https://github.com/htl-stp-ecer/botui) | Flutter UI — visualises sensor data from this service |\n| [documentation](https://raccoon-docs.pages.dev/) | Full platform docs |\n\n---\n\n## License\n\nCopyright (C) 2026 Tobias Madlberger  \nLicensed under the GNU General Public License v3.0 — see [COPYING](COPYING) for details.\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhtl-stp-ecer%2Fstm32-data-reader","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fhtl-stp-ecer%2Fstm32-data-reader","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fhtl-stp-ecer%2Fstm32-data-reader/lists"}