RP2040 boards
TX controller + RX car
2.4 GHz
nRF24L01+ link
Channel 108 · 250 kbps
50 ms
Control loop
20 Hz command cycle
C++17
Bare-metal firmware
Pico SDK · no RTOS

Overview

An RC car built from the ground up — printed, wired and programmed end to end. A handheld controller reads an analog joystick and streams steering and throttle commands over a 2.4 GHz radio link to the vehicle, which drives its motors and steering servo in real time. The whole thing runs on two Raspberry Pi Pico boards and a few hundred lines of modern C++.

Real-time wireless control

Joystick axes are mapped to a −1000…+1000 range and packed into a compact RC_Command struct sent every 50 ms — low enough latency to feel direct.

Reliable radio link

Dynamic payloads, auto-retries (5×, 15 cycles) and a noise-filtered power rail keep the nRF24L01+ link stable even near the motors.

Closed-loop ready

A wheel encoder feeds back speed, opening the door to cruise control and traction tuning on the car firmware.

Fully 3D-printed

Chassis, steering linkage and electronics mounts are all custom-printed and iterated alongside the firmware.

One repo, two targets

A single CMake + Ninja build produces both controller.uf2 and car.uf2, sharing the RF24 driver between them.

TX
Controller
Raspberry Pi Pico
Analog joystick
nRF24L01+
→→→
2.4 GHz · channel 108
RC_Command · 50 ms
RX
RC Car
Raspberry Pi Pico
Motors · Servo · Encoder

Wiring Diagram

RC Buggy wiring diagram

Hardware

Car

ComponentQtyNotes
Raspberry Pi Pico 1 Main receiver / controller (RP2040)
DC Motor 2 Wheel drive via PWM
MG series servo 1 Steering — 50 Hz, 1000–2000 µs range
nRF24L01+ module 1 2.4 GHz wireless, channel 108
DC-DC converter (battery) 1 Battery regulation for motor supply
DC-DC converter (logic) 1 Stable 3.3 V for Pico and sensors
Capacitors several Noise filtering on nRF24L01+ power rail
Encoder 1 Wheel speed measurement

Controller

ComponentQtyNotes
Raspberry Pi Pico 1 Transmitter / handheld controller (RP2040)
nRF24L01+ module 1 Wireless communication
KY-023 analog joystick 1 VRX = ADC1, VRY = ADC0, SW = GPIO 22

Pinout

Car

RF24

MISO GPIO 12
MOSI GPIO 11
SCK GPIO 14
CSN GPIO 15
CE GPIO 13

Motors

MOTOR1_INA GPIO 2
MOTOR1_INB GPIO 3
MOTOR2_INA GPIO 4
MOTOR2_INB GPIO 5

Servo

SERVO_PIN GPIO 8

Encoder

ENCODER1_A GPIO 10
ENCODER1_B GPIO 6

Controller

RF24

MISO GPIO 4
MOSI GPIO 3
SCK GPIO 2
CSN GPIO 5
CE GPIO 17

Joystick

VRX GPIO 27 / ADC1
VRY GPIO 26 / ADC0
SW GPIO 22

Communication Protocol

RC_Command struct

Packet sent every 50 ms from the controller to the car.

struct RC_Command {
    int16_t steering;  // X axis  -1000 ... +1000
    int16_t throttle;  // Y axis  -1000 ... +1000
    uint8_t buttons;   // button bitmask
};

RF24 configuration

Channel 108
Data rate RF24_250KBPS
PA level RF24_PA_LOW
Dynamic payloads enabled
Retries setRetries(5, 15)
TX cycle 50 ms

Requirements

ToolVersion
Raspberry Pi Pico SDK 2.2.0
ARM GNU toolchain arm-none-eabi-gcc
CMake 3.13+
Ninja latest
Picotool optional — recommended for terminal flashing
Git submodule support required

Build & Flash

Clone

Clone the repo with all submodules.

$ git clone --recurse-submodules https://github.com/truposky/remote_car.git
$ cd remote_car

Already cloned without submodules?

$ git submodule update --init --recursive

Configure & build

If CMake can't find the SDK, export PICO_SDK_PATH first.

$ export PICO_SDK_PATH="$HOME/.pico-sdk/sdk/2.2.0"
$ cmake -B build -G Ninja
$ ninja -C build

Individual targets:

$ ninja -C build controller
$ ninja -C build car

Flash

Connect the Pico in BOOTSEL mode, then copy the .uf2 file to the mounted drive — or use picotool:

$ picotool load build/controller/controller.uf2 -fx
$ picotool load build/car/car.uf2 -fx

Output files:

build/controller/controller.uf2
build/car/car.uf2

CMake targets

Libraries linked per target.

TargetLinked libraries
controller RF24, pico_stdlib, hardware_spi, hardware_gpio, hardware_adc
car RF24, pico_stdlib, hardware_spi, hardware_gpio, hardware_pwm

Comments

0 comments

No comments yet — be the first to leave one.

Comments are reviewed before they appear.
← Back