A multi-node, RTOS-driven embedded system designed to mirror modern automotive Electronic Control Unit (ECU) architectures.
- System Architecture
- Fault Tolerance & Hardening
- Hardware Setup
- Repository Structure
- Getting Started
- Development Roadmap
The system is distributed across two microcontrollers, separating high-level system logic from low-level hardware actuation:
- Environment: FreeRTOS
- Responsibilities:
- Input Handling: Reads and software-debounces user push buttons.
- State Management: Drives a 4-state Finite State Machine (FSM):
Off→Low→High→Auto. - UI/Feedback: Updates status LEDs based on the current system state.
- Bus Communication: Frames and transmits control commands over the UART bus.
- Environment: Bare-metal C (RP2040 SDK)
- Responsibilities:
- Bus Listener: Parses incoming UART frames from the STM32.
- Actuation: Maps commanded percentage (0-100%) to a hardware PWM duty cycle to drive a DC motor.
- Hardware: UART
- Protocol: Custom framed packets consisting of
[Header | Payload | Checksum]. - Performance:
< 5msround-trip latency.
This project goes beyond simply spinning a motor by implementing production-grade edge case handling:
- Communication Timeouts: The STM32 actively monitors the bus. If the physical wire is unplugged, the system safely transitions to an error state.
- EMI / Noise Rejection: The bare-metal Pico parser validates a checksum on every incoming packet. If electrical noise from the DC motor corrupts a byte, the packet is safely discarded to prevent erratic motor behavior.
To establish the physical communication link between the two nodes, wire them as follows:
| STM32 (Node 1) | Raspberry Pi Pico (Node 2) | Purpose |
|---|---|---|
UART TX |
UART RX |
Transmit commands to Pico |
UART RX |
UART TX |
Receive acknowledgments (optional) |
GND |
GND |
Critical: Common ground reference |
smart-fan-controller/
├── shared/ # Shared protocol header (Single Source of Truth)
│ └── comms_protocol.h
├── node1_stm32_main/ # STM32CubeIDE Project (FreeRTOS)
└── node2_pico_motor/ # CMake Project (Bare-metal RP2040)- STM32CubeIDE (For Node 1)
- Raspberry Pi Pico SDK & CMake (For Node 2)
- ARM GNU Toolchain (
arm-none-eabi-gcc)
- Open STM32CubeIDE.
- Select
File→Open Projects from File System. - Point the directory to
/node1_stm32_main/. - Build the project and flash using an ST-Link.
Open your terminal and run the following commands:
cd node2_pico_motor
mkdir build && cd build
cmake ..
makeFlash the resulting .uf2 file to the Raspberry Pi Pico by holding the BOOTSEL button while plugging it in via USB, then drag and drop the file.