Skip to main content
Version: ACS CC

CargoBot

Remote-controlled cargo robot with Bluetooth telemetry

info

Author: Andrei Rusanescu
GitHub Project Link: link_to_github

Description

CargoBot is a remote-controlled four-wheeled robot that carries cargo and navigates surfaces with imperfections. It is controlled from a laptop keyboard via Bluetooth and uses an STM32 Nucleo-U545RE-Q microcontroller programmed in Rust with Embassy-rs. It sends real-time telemetry data to a PC dashboard via Bluetooth, while simultaneously displaying information on an onboard OLED.

The central idea of the project is measuring and visualizing the impact of cargo load on motor performance: when the robot carries something heavy, the PID controller automatically increases the PWM duty cycle to maintain a constant speed. This compensation is observable live on the robot's OLED, on the PC dashboard, and through 3 LEDs (green/yellow/red) that visually indicate the effort level.

Motivation

I am particularly interested in cars and networking. This project combines multiple peripherals studied in the lab (PWM, GPIO, I2C, UART, Bluetooth) into a functional system. It is a challenge that clearly demonstrates technical effort - the difference in motor effort with and without cargo, and how to compensate for the load.

Architecture

Architecture

The system is organized around five main subsystems:

1. MCU (STM32 Nucleo-U545RE-Q) The central unit running all Embassy-rs async tasks. Coordinates all subsystems and shared state protected by Mutex.

2. Motor Subsystem The L298N dual H-bridge receives PWM signals from the STM32 and drives 4 DC motors (2 per channel, left/right side in parallel - skid steering). The two IR LM393 optical sensors read encoder disc pulses on GPIO interrupts and compute RPM per side.

3. Sensing Subsystem

  • MPU-6500 (I2C, address 0x68): reads accelerometer + gyroscope data, combined via complementary filter to get a stable tilt angle
  • 2x HC-SR04 (GPIO trigger/echo): front and rear obstacle detection
  • 2x IR LM393 encoders: RPM feedback for PID

4. Communication Subsystem HC-06 Bluetooth module connected to STM32 via UART. Bidirectional: laptop sends movement commands (forward/backward/left/right + speed), robot sends back JSON telemetry at 5Hz.

5. Display & Indicators Subsystem

  • OLED SSD1306 128x64 (I2C, address 0x3C, shared bus with IMU): displays RPM, tilt angle, obstacle distance, state, load level
  • 3x LEDs (green/yellow/red) on GPIO: visual indicator of motor effort based on PWM duty cycle
  • Passive buzzer on PWM: horn and audio feedback

Embassy-rs Async Tasks:

TaskFrequencyResponsibility
sensor_task20 HzRead IMU (I2C) + ultrasonic sensors
motor_task50 HzApply PWM to L298N, read encoders
navigation_task10 HzState machine: FORWARD / COMPENSATE / AVOID / STOP
telemetry_task5 HzSerialize JSON and send over UART to HC-06
display_task4 HzUpdate OLED

Navigation State Machine:

StateEntry ConditionAction
FORWARDNo obstacleMove at target speed, PID active
COMPENSATEPitch > 5 deg (ramp)Increase PWM proportional to tilt angle
AVOIDObstacle < 30cmStop, rotate, resume forward
STOPManual command / errorMotors off, telemetry continues

Peripheral Usage:

PeripheralComponentUsage
PWMSTM32 -> L298NMotor speed control (0–100% duty cycle)
PWMSTM32 -> BuzzerHorn
GPIO OutputSTM32 -> HC-SR04 trigger10 micro-s pulse to trigger ultrasonic
GPIO Input InterruptHC-SR04 echo -> STM32Measure echo duration -> distance
GPIO Input InterruptLM393 encoders -> STM32Count pulses -> compute RPM
GPIO OutputSTM32 -> LEDs R/Y/GLoad indicator: green (<35%), yellow (35–65%), red (>65%)
GPIO OutputSTM32 -> L298N IN1-IN4Motor direction control
I2C (shared bus)STM32 -> MPU-6500 (0x68)Accelerometer + gyroscope for tilt angle
I2C (shared bus)STM32 -> SSD1306 (0x3C)OLED telemetry display
UARTSTM32 -> HC-06Bidirectional Bluetooth: commands in, telemetry out

Log

Week 6 - 12 Apr

Ordered most of the components needed.

Week 13 - 19 Apr

Assembled the mechanical parts (wheels, motors, car platform).

Week 20 - 26 Apr

Working on the Schematic in KiCad. Tested individual components: bluetooth module, display, motors, distance sensors, LM393 speed sensors.

Week 27 Apr - 3 May

Ordered Li-Ion Samsung 18650 3.6V 3450mAh 8A batteries, a charger for the batteries, more male-female and female-female jumpers and a smaller breadboard (400 points).

Week 4 - 10 May

Soldered IMU and OLED display in the lab. Assembled final product. Started to write the software for the cargobot and tested it carrying another car. The HC-SR04 sensors are not so precise as the car sometimes crashes into walls if driven into.

Week 11 - 17 May

Hardware

The robot is built on a 4WD chassis with 4 DC motors (3–6V) driven through an L298N dual H-bridge using skid steering (left/right side in parallel). Speed and direction are controlled via PWM from the STM32. Two IR optical sensors read encoder discs on the motors to compute RPM. An MPU-6500 IMU over I2C measures tilt angle using a complementary filter. Two HC-SR04 ultrasonic sensors handle obstacle detection front and rear. An SSD1306 OLED displays live telemetry. An HC-06 Bluetooth module provides bidirectional communication with the laptop.

Car from above Car from a side

Schematics

KiCad Schematic: KiCad Schematic

Bill of Materials

DeviceUsagePrice
STM32 Nucleo-U545RE-QMain microcontroller (Cortex-M33), runs all Embassy-rs tasks0 RON (provided by university)
4x DC motors (3-6V), encoder discs, wheelsWheels and motors for the CargoBot40 RON
2x IR Speed Sensor LM393 x2Optical encoder reading, counts pulses from encoder discs to compute RPM16.22 RON
L298N Dual H-BridgeMotor driver, controls speed (PWM) and direction of both motor sides8.96 RON
MPU-6500 Accelerometer & Gyroscope6-axis IMU, measures tilt angle via complementary filter (I2C, 0x68)9.92 RON
HC-06 Bluetooth ModuleBidirectional wireless UART, receives keyboard commands, sends telemetry JSON25.13 RON
OLED SSD1306 0.96" I2COn-board display, shows RPM, tilt, obstacle distance, state, load level (I2C, 0x3C)14.01 RON
2x HC-SR04 Ultrasonic Sensor x2Obstacle detection, front and rear, GPIO trigger/echo18.80 RON
18650 Battery Holder 2SHolds 2x 18650 cells in series, 7.4V output for L298N and STM325.74 RON
2x Li-Ion Samsung 18650 3.6V 3450mAh 8ABatteries to provide voltage for the motors and for the board63 RON
Battery chargerCharges the Li-ion batteries35 RON
3x LED (red/yellow/green) + resistorsVisual motor effort indicator0 RON (owned)
Female-Female jumper wiresWires for connections7.73 RON
Male-Female jumper wiresWires for connections7.73 RON
Male-Male jumper wiresWires for connections0 RON (owned)

Software

LibraryDescriptionUsage
embassy-stm32Async HAL for STM32U5PWM, I2C, UART, GPIO, Timer drivers
embassy-executorAsync task executorSpawning and running concurrent tasks
embassy-timeAsync timers and delaysTask scheduling at fixed frequencies
embassy-syncSynchronization primitivesMutex and Channel for inter-task shared state
ssd1306OLED SSD1306 driverI2C display rendering
embedded-graphics2D graphics libraryDrawing text and shapes on OLED
heaplessNo-alloc data structuresString/Vec without heap allocation
defmt + defmt-rttLogging frameworkDebug output via probe
libmMath functions (no_std)atan2, sqrt for complementary filter
Python pyserialSerial communicationPC-side script to receive telemetry and send commands over Bluetooth
Python matplotlib / FlaskData visualizationLive dashboard with RPM, PWM, tilt, distance graphs
  1. Embassy-rs documentation
  2. STM32 Nucleo-U545RE-Q user manual
  3. MPU-6500 datasheet
  4. SSD1306 OLED driver crate
  5. L298N datasheet
  6. HC-SR04 ultrasonic sensor guide