Skip to the content
4 layers100 × 100 mmSimple robot, the printed circuit board in 3D

A not-too-simple tracked robot with autonomous navigation and sensor-driven obstacle avoidance, written in Rust with Embassy. v2 reached the limits of its hardware platform; development continues in a new repository.

Size
100 × 100 mm
Copper layers
4
Thickness
1.6 mm
Parts
70
Nets
92
Pads
318
Tracks, vias
1,065, 173
Pours
11
Routed
Yes
KiCad
KiCad 10.0 (file 20260206)
Created
22 Sep 2024
Updated
13 Sep 2026

Overview

Simple robot is an open-source printed circuit board by 1-rafael-1, from the 1-rafael-1/simple-robot repository on GitHub. It is a 4-layer board of 100 × 100 mm with 70 parts on 92 nets, routed with 1,065 tracks and 173 vias.

It is built around the CD4049UBD and 10UF 10V. Its parts include 26 capacitors, 17 connectors, 11 resistors, 3 diodes and 2 ICs. It belongs with the robots and motor control and sensors and measurement boards and the RP2350 boards of this library.

Main components

2

README

README.md

simple-robot

A not-too-simple tracked robot with autonomous navigation and sensor-driven obstacle avoidance, written in Rust with Embassy. v2 reached the limits of its hardware platform; development continues in the follow-up explorer-robot repository.

Robot Side View Side view showing the robot's profile — the v2 iteration.

Project History

This started out as a hobby project for my 10-year-old son, who wanted me to build a robot for him. The thing started as a rather simple machine (v1) and then I got a little carried away. Check out the v1-robot navigating autonomously, download the demo video here: Autonomous Operation.

Note: The initial version of this robot is preserved in the v1 tag. That version represents a simple but functional obstacle-avoiding robot using basic components. The v2 iteration described here is tagged v2 and is now mothballed.

In v1, the robot could move autonomously by avoiding obstacles in a very simple way. That meant driving straight until an obstacle is detected, back up a little and then make a random turn. It was fun to watch and my son was happy with it.

v2 set out to be much more capable. The plan was to add spatial awareness through an IMU and a sweeping ultrasonic sensor, build more sophisticated autonomous navigation modes, and eventually integrate an AI camera module for follow-me and object-finding. Some of that worked out; some of it ran into hardware limits that couldn't be solved on this platform.

People have pointed out to me various things. The gist is that there are of course ready-made chassis solutions, ready-made RTOS for robotics and even probably complete systems available and that I am setting out to solve things that can be solved with much less effort by using existing things in code as well as hardware. This is all true and I do not dispute it. My motivation is different, though: I am not truly that much interested in having the actual robot, I have no use case at all for it, in fact. I just truly enjoy the process of building, figuring out how to do things, learning a ton of new stuff and it passes my rare spare time in a rewarding way.

What v2 Achieved

The v2 firmware is a fully integrated platform built on Embassy async with a task-oriented architecture. A central orchestrator runs an event loop, dispatching sensor events to behavior handlers and UI updates. The drive subsystem uses a single-producer command queue with intents for distance drives, in-place rotations, and brake/coast settling — all with IMU-corrected feedback and ramp-down near targets. Mode-agnostic obstacle detection triggers emergency braking across all modes.

The robot carries a custom 4-layer PCB designed in KiCad, hand-soldered, with an RP2350 at 150 MHz. It drives four TT motors through two TB6612FNG motor drivers, reads four hall-effect encoders, and runs an ICM-20948 9-axis IMU with on-chip DMP sensor fusion. An HC-SR04 ultrasonic sensor on a servo performs 0–160° sweeps with a 30° cone correction algorithm, feeding a shared sweep buffer used by both the OLED's radar visualization and the autonomous navigation modes. Two front-facing IR sensors provide close-range collision detection, and a PCA9555 I2C port expander handles motor direction/standby pins and additional inputs. An RGB LED indicates battery state and obstacle alerts.

The UI is driven by an EC11 rotary encoder with push button and an SSD1306 OLED display. A menu system exposes hardware tests (motors, encoders, IMU, ultrasonic sweep, drive accuracy), calibration routines (motor speed, IMU, distance factor), and autonomous mode selection. Calibration data persists to flash storage.

Two autonomous modes are implemented:

  • Coast-and-avoid — drives forward until an obstacle is detected, backs up, and turns a random angle. Simple but reliable.
  • Attempt straight line — the user sets a target distance (100–1000 cm); the robot sweeps the ultrasonic sensor, performs gap analysis with drift correction, and navigates leg-by-leg toward the goal while avoiding obstacles.

Three side-quest crates were published along the way: hcsr04_async (async HC-SR04 driver), moving_median (moving median filter), and icm20948-rs (ICM-20948 driver with DMP support).

Why v2 Ends Here

The robot works, but it cannot reach the spatial awareness and navigation precision the original vision demanded. Several hard limits converge:

Spatial awareness is the primary bottleneck. The HC-SR04 ultrasonic sensor, even with servo sweeping and cone correction, is fundamentally imprecise. Its 30° detection cone could have been overcome algorithmically, but it produces false readings far too easily — a carpet, a floor tile seam, or a slightly textured surface registers as an obstacle. That makes reliable navigation impossible. The front-facing IR sensors work but have very short range and would require redesigning the sensor array holder to be truly useful. There is no downward-facing sensor to detect stairs or ledges.

The board is out of pins. The RP2350 on a Pico 2, even with a PCA9555 port expander, has every pin in use. There is no room to add a downward edge sensor, a better spatial sensor, or anything else. Some of those pins are spent on RC receiver inputs and a UART for an AI board that were never fully utilized, and on four motor encoders and two motor driver modules — overhead that a two-motor design would eliminate.

Four TT motors reach a precision ceiling. Two motors per track were necessary to move the Proto-Tank chassis, but that doubled the encoder and PWM pin count. The cheap hall-effect encoders and the inherent variability of TT motors mean no amount of calibration will deliver the positional accuracy needed for reliable dead-reckoning navigation.

The I2C bus is shared between the IMU, the OLED display, and the port expander. Motor direction changes go through the expander on that same bus. This never caused a hard failure in testing, but it is a fragile design with no headroom.

None of these are software problems. They are hardware constraints of a design that started from a simple tank chassis and grew organically. v2 went as far as it could on this platform.

What's Next

Development continues in the follow-up explorer-robot repository. I am not yet sure where this will go, but the plan is to build a more capable robot with better spatial awareness and navigation precision.

Licensing Overview

This project uses multiple licenses depending on the component:

  • Firmware code (src/, build.rs, Cargo.toml, etc.): Licensed under MIT License (see LICENSE-MIT.md)
  • 3D-printed chassis designs (misc/chassis/): Based on the Proto-Tank Chassis by fustyles, licensed under CC BY-SA 4.0 (see attribution below)
  • Schematic and hardware design (misc/media/schematic_picture.png): Licensed under CC BY-SA 4.0 (see LICENSE-CC-BY-SA-4.0.md)
  • Documentation (docs/, README.md): Licensed under CC BY-SA 4.0

Please review the individual license files and attribution sections for detailed information.

Schematic

You can find the KiCad project here: misc/KiCad/simple-robot. Some of the boards I used had no symbols & footprints and so I created them as I went. You can find them here: misc/KiCad/symbols. The Pi Pico symbol I found online here: ncarandini/KiCad-RP-Pico.

robot-schematic The v2 schematic (current design)

robot-pcb The v2 PCB layout (current design)

3D Printing

The robot chassis and various mounting components are designed to be 3D printed. I printed all parts in PLA and they worked quite okay so far. The 3D models are stored in the misc/chassis directory with both FreeCAD source files (.FCStd) and print-ready formats (.3mf, .stl).

For convenient printing with a Bambu Lab 3D printer, two Bambu Studio print projects are included:

  • print project.3mf - Complete robot chassis assembly including the base frame, servo mount, HC-SR04 ultrasonic sensor mount, and IR sensor mounts
  • track pin print project.3mf - Track pin components for securing and tensioning the robot's tracks (recently added)

The individual component files are also available if you prefer to customize your print settings:

  • BaseFrame - edit.3mf/stl (main chassis frame)
  • 9g servo mount.3mf (servo mounting bracket)
  • hc-sr04 mount.3mf (ultrasonic sensor mount)
  • IR Sensor mount.3mf (infrared sensor mounting)
  • PCB mounting base.3mf (circuit board support)
  • track pin.3mf (individual track pin component)

For more details on the chassis components, file formats, and assembly, see misc/chassis/README.md.

Side quests that became necessary

Building the thing I found no async driver for the HC-SR04, so I had to make one myself:

This was fun :-)

Testing the ultrasonic sensor I found it gets even more unreliable when moving. So I searched for some moving median filtering solution, found none and made one myself:

A little less fun.

I replaced the initial MPU9250/MPU6050 I never truly got to work with the ICM20948, a more modern 9-axis IMU from the same manufacturer (TDK InvenSense). The ICM20948 offers better performance and I created a driver for it:

The driver supports async I2C operations and includes examples for RP2350. This was to a degree vibe-coded because that is truly out of my league, but it seems to work okay so far. I am sure there are many things that could be done better, but it is a start and I can now get good orientation data from the IMU, which is a big step forward for the project.

The code

The code is written in Rust and makes heavy use of the Embassy framework. The architecture is task‑oriented, with a central orchestration loop handling events and routing them to behavior modules. Tasks stay resident and idle when not needed, which keeps the control flow predictable and makes it easy to evolve the system.

The drive subsystem is explicitly single‑producer/single‑executor: higher‑level modes build queues of drive steps, submit them to the drive queue executor, and await a single queue completion. Per‑step completion is internal to the executor, and interrupts remain available for preemption.

There are two modules, system and task. The system module contains rather general things like the event system and state. The task module contains the tasks that are run by the system.

State Modules and Lock Order

The global state is split into domain-specific modules under system/state/* to reduce contention and keep hot paths lock-free where possible:

  • system/state/power.rs
  • system/state/motion.rs
  • system/state/perception.rs
  • system/state/calibration.rs

UI mode state lives in task/ui/state.rs (via UI_STATE) and is kept separate from the system state lock order.

When multiple state mutexes must be held at the same time, a uniform lock order is required to avoid deadlocks:

  1. POWER_STATE
  2. CALIBRATION_STATE
  3. PERCEPTION_STATE
  4. MOTION_STATE

The main.rs file is the entry point of the program but does nothing besides initializing some resources and then spawning all the tasks.

The firmware uses both cores of the RP2350 at the nominal 150 MHz clock speed: core0 runs the orchestrator, drive subsystem, sensors, and UI; core1 owns the I2C bus and runs the display, IMU, and port expander tasks. It uses a few percent of the flash space and about 20% of the RAM. The single I2C bus is shared between the IMU, the OLED display, and the port expander — this never caused issues in testing, but it is a tight design with no room for additional devices.

Acknowledgments & Attribution

Proto-Tank Chassis Design

The robot's tracked chassis is based on the Proto-Tank project, which is licensed under Creative Commons Attribution 4.0 International.

The Proto-Tank design has been modified and adapted for the simple-robot project to integrate custom motor mounts, PCB solutions, and sensor integration.

See misc/chassis/ATTRIBUTION.md for full attribution details and license information.

Disclaimer

I am a hobbyist, I have no formal electronics education and am still relatively new to the hobby (2.5 years now). I am also still as new to Rust and Embedded. By now I have a basic understanding of how things work and of what are higher level things in embedded. Enough for maker-level, far off from actual professional level. So expect imperfections.

I use AI when coding, which has proven to be an excellent teaching tool for learning a new language. It allows me to explore more advanced concepts than I could on my own, making self-teaching much easier than it was just a year or two ago. That being said: The code is my take on how to do this, actual professionals will find a thousand things one could do better. In case you find a thing that could be better: Happy to hear about it, get in touch! :-)

Component Summary

The following is a summary of the components used in the v2 schematic (see KiCad project).

Microcontroller

RefComponentNotes
U1Raspberry Pi Pico 2 (RP2350)Main controller

Sensors

RefComponentNotes
I1ICM-20948 module9-axis IMU (accelerometer, gyroscope, magnetometer), I2C
J11HC-SR04 ultrasonic sensorConnected via JST 4-pin, with servo sweeper
J12, J13IR obstacle detection sensors (×2)Right-front and left-front
J14Grove Vision AI v2Camera/AI module, JST 4-pin

Motor Control

RefComponentNotes
MD1, MD2TB6612FNG motor driver carriers (×2)Left track & right track
J6–J9Motor encoders (×4)LF, LR, RF, RR via JST 3-pin
J1, J2, J4, J5DC motor connectors (×4)JST 2-pin

Communication & IO Expansion

RefComponentNotes
P1PCA9555 I2C port expander16-bit GPIO expander
LS_1, LS_2, LS_3Bi-directional level shifters (×3)3.3V ↔ 5V
U2CD4049UBHex inverting buffer (DIP-16)

User Interface

RefComponentNotes
OLED1SSD1306 OLED display moduleI2C
SW1Rotary encoder with push switchUser input
LED15mm RGB LED (common cathode)Status indicator
—RF receiverRemote control, via JST 3-pin

Power

RefComponentNotes
B1LM2596 DC-DC buck converter moduleSteps battery voltage down
J10Screw terminal (2-pin)Battery input
D1, D31N5819 Schottky diodes (×2)Power path protection

Passive Components

RefComponentNotes
C2–C16, C19–C24, C26100nF ceramic capacitors (×20)Decoupling
C184700µF 16V electrolyticBulk decoupling (motors)
C1, C7220µF polarized (×2)
C17220µF 10V
C2510µF 16V
R2, R347Ω (×2)
R5, R61kΩ (×2)
R810kΩ
R4, R720kΩ (×2)
R10, R11220Ω (×2)LED current limiting
R9330ΩLED current limiting

Parts

70
QtyValueFootprintReferences
21100nF_CeramicCapacitor_THT:C_Disc_D5.0mm_W2.5mm_P2.50mmC2, C3, C10, C11, C12, C13, C14, C15, C16, C19, C20, C21, C22, C23, C24, C26 +5
3Level Shiftercommon-hobby-things:Level shifter 4 bi-dirLS_1, LS_2, LS_3
21N5819PCM_Diode_THT_AKL:D_DO-41_SOD81_P7.62mm_HorizontalD1, D3
21kResistor_THT:R_Axial_DIN0207_L6.3mm_D2.5mm_P10.16mm_HorizontalR5, R6
220kResistor_THT:R_Axial_DIN0207_L6.3mm_D2.5mm_P10.16mm_HorizontalR4, R7
2220ohmResistor_THT:R_Axial_DIN0207_L6.3mm_D2.5mm_P10.16mm_HorizontalR10, R11
2220uFCapacitor_THT:CP_Radial_D6.3mm_P2.50mmC1, C7
247ohmResistor_THT:R_Axial_DIN0207_L6.3mm_D2.5mm_P10.16mm_HorizontalR2, R3
2MountingHole_PadMountingHole:MountingHole_3.7mm_Pad_ViaH1, H2
110kResistor_THT:R_Axial_DIN0207_L6.3mm_D2.5mm_P10.16mm_HorizontalR8
110uF_10VCapacitor_THT:CP_Radial_D6.3mm_P2.50mmC17
110uF_16VCapacitor_THT:CP_Radial_D5.0mm_P2.00mmC25
1330ohmResistor_THT:R_Axial_DIN0207_L6.3mm_D2.5mm_P10.16mm_HorizontalR9
13K3Resistor_THT:R_Axial_DIN0207_L6.3mm_D2.5mm_P10.16mm_HorizontalR1
14700uF_16VCapacitor_THT:CP_Radial_D16.0mm_P7.50mmC18
1CD4049UBPackage_DIP:DIP-16_W7.62mm_LongPadsU2
1ENC_LFConnector_JST:JST_PH_B3B-PH-K_1x03_P2.00mm_VerticalJ6
1ENC_LRConnector_JST:JST_PH_B3B-PH-K_1x03_P2.00mm_VerticalJ7
1ENC_RFConnector_JST:JST_PH_B3B-PH-K_1x03_P2.00mm_VerticalJ8
1ENC_RRConnector_JST:JST_PH_B3B-PH-K_1x03_P2.00mm_VerticalJ9
1IR_LFConnector_JST:JST_PH_B3B-PH-K_1x03_P2.00mm_VerticalJ13
1IR_RFConnector_JST:JST_PH_B3B-PH-K_1x03_P2.00mm_VerticalJ12
1JST RF_LogicConnector_JST:JST_EH_B4B-EH-A_1x04_P2.50mm_VerticalJ15
1JST RF_PWConnector_JST:JST_EH_B2B-EH-A_1x02_P2.50mm_VerticalJ16
1JST03 ServoConnector_JST:JST_EH_B3B-EH-A_1x03_P2.50mm_VerticalJ3
1JSTHCSR04Connector_JST:JST_EH_B4B-EH-A_1x04_P2.50mm_VerticalJ11
1JST_GVConnector_JST:JST_EH_B4B-EH-A_1x04_P2.50mm_VerticalJ14
1LED_5mm_RGB_Kcom_RKGBPCM_LED_THT_AKL:LED_D5.0mm-4_RGB_Wide_PinsLED1
1LM2596 Modulecommon-hobby-things:LM2596_ModuleB1
1LeftTrackcommon-hobby-things:TB6612FNG motor driver carrierMD1
1MotLAConnector_JST:JST_PH_B2B-PH-K_1x02_P2.00mm_VerticalJ1
1MotLBConnector_JST:JST_PH_B2B-PH-K_1x02_P2.00mm_VerticalJ2
1MotRAConnector_JST:JST_PH_B2B-PH-K_1x02_P2.00mm_VerticalJ4
1MotRBConnector_JST:JST_PH_B2B-PH-K_1x02_P2.00mm_VerticalJ5
1Pico2PCM_SL_Development_Boards:raspberry_pi_pico_THTU1
1Port Expandercommon-hobby-things:PCA9555 Port ExpanderP1
1RightTrackcommon-hobby-things:TB6612FNG motor driver carrierMD2
1RotaryEncoder_SwitchRotary_Encoder:RotaryEncoder_Alps_EC11E-Switch_Vertical_H20mmSW1
1Screw_Terminal_2_P5.00mmTerminalBlock_Phoenix:TerminalBlock_Phoenix_PT-1,5-2-5.0-H_1x02_P5.00mm_HorizontalJ10
1~common-hobby-things:SSD1306OLED1
1~common-hobby-things:ICM-20948-moduleI1

Similar boards

  • 2 layers59.1 × 46.9 mmFatdrive, the printed circuit board in 3D

    Fatdrive

    bubbajfett/kicad-guitar-pedals

    collection of guitar pedal PCB layouts in kicad

    46 parts17CC0-1.0
  • 2 layersMorpheus kicad, the printed circuit board in 3D

    Morpheus kicad

    pscrespo/Morpheus-STM32

    A small 3D printer controller board for use with a "blue pill" STM32F1 generic board. Inspired on http://reprap.org/wiki/SinapTec

    66 parts80GPL-3.0
  • 2 layers54 × 48 mmPS4-USB HEN ESP32, the printed circuit board in 3D

    PS4-USB HEN ESP32

    TomasFilipCZ/PS4-USB-HEN-ESP32

    ESP32-S2 as USB Flash disk emulation for loading GoldHEN for 9.00

    41 parts10BSD-3-Clause
  • 2 layers25 × 25 mmKiwiEFI Hall 0.1, the printed circuit board in 3D

    KiwiEFI Hall 0.1

    Neil427/Speeduino-Hall-Trigger-Conditioner

    Speeduino Hall sensor conditioner board with buffering

    38 parts4GPL-3.0
  • 4 layers71.9 × 91 mmKlipper, the printed circuit board in 3D

    Klipper

    tobetter/3DPrinterShield

    "3D Printer Shield" is a board to run 3D printer using ODROID single board computer, technically this board is designed to control the motor driver modules with TMC2209 (UART) or TMC2130 (SPI) through the on-board GPIO…

    111 parts4GPL-3.0
  • 2 layers75 × 75 mmAD POWER DEVICE, the printed circuit board in 3D

    AD POWER DEVICE

    R-Mutura/AD_POWER_DEVICE

    Highly integrated Single board Computer with RK3566

    593 parts3
  • 4 layers160 × 210 mmCarrier, the printed circuit board in 3D

    Carrier

    ddanila/Pico1715

    Pico-based SD, RAM and controller replacement for Robotron PC 1715

    80 partsMIT

Questions

How big is the Simple robot PCB?

It measures 100 × 100 mm and has 4 copper layers, 1.6 mm thick.

What parts does the Simple robot use?

70 parts, built around the CD4049UBD and 10UF 10V. The full list of its parts is on this page, with links to each part's symbol and footprint where PCBKit's library has them.

Where can I download the Simple robot KiCad files?

From the 1-rafael-1/simple-robot repository on GitHub, at the commit this page was made from: the board is misc/KiCad/simple-robot/simple-robot.kicad_pcb and its schematic misc/KiCad/simple-robot/simple-robot.kicad_sch. PCBKit opens the board in the browser, with nothing to install.

Can I use the Simple robot design in my own project?

Its repository states no licence, so its author keeps all rights: ask 1-rafael-1 before reusing the design.