- Wii Remote + Arduino + LEGO RC Car (Part 1): Parts Selection
- Wii Remote + Arduino + LEGO RC Car (Part 2): Driving DC Motors
- Wii Remote + Arduino + LEGO RC Car (Part 3): Bluetooth Dongle via USB Host Shield
- [Finished!] Wii Remote + Arduino + LEGO RC Car (Part 4): Controlling DC Motors with the Wii Remote
We've made it to the final part of the RC car build. Probably.
Here's the completed circuit:

It looks complicated, but it's just everything from previous parts combined.
Let's walk through it piece by piece.
Motor Driver TA7291P
Check on Amazon
We need to control the left and right motors independently,
so we place two motor drivers in a mirror-symmetric layout.
Unlike before, this time we're connecting three pins per driver to the Arduino — no fixed resistor.
This wasn't a random change. There's a real reason for it.
(…which I realised only after assembling everything.)
USB Host Shield and Pin Constraints
The reason for dropping the fixed resistor comes down to the combined constraints of the USB Host Shield, Arduino UNO, and TA7291P.
Arduino controls output voltage through PWM, but not every pin supports PWM.
Only pins marked with
~ on the board support it: specifically D3, D5, D6, D9, D10, D11.When the USB Host Shield is stacked on the Arduino UNO, it occupies D7–D13,
leaving those pins unavailable for motor control.
Of the remaining D0–D6, only D3, D5, and D6 support PWM — just three pins.
With a fixed resistor, controlling the TA7291P requires one PWM pin per direction (forward on pin 5, reverse on pin 6), so two PWM pins per driver.
Two drivers means four PWM pins — but we only have three. Not enough.
Instead, we use three pins per driver (pins 4, 5, 6) with no fixed resistor.
In this configuration, pin 4 handles speed via PWM, while pins 5 and 6 just set direction (HIGH/LOW).
Two drivers now need only two PWM pins and four digital pins — exactly what we have available.
With the USB Host Shield mounted, we have D3, D5, D6 for PWM and D0, D1, D2, D4 for digital — just barely enough.
Note: if you only need forward/back/spin-in-place without variable speed, you don't need PWM at all and can skip this whole constraint puzzle.
Motor Direction and Track Movements
Tracks (as opposed to wheels) have a special move: spin in place.
Here's how motor directions map to vehicle movement:
- Forward
Left motor: forward Right motor: forward - Reverse
Left motor: reverse Right motor: reverse - Turn left
Left motor: forward (reduced speed) Right motor: forward - Turn right
Left motor: forward Right motor: forward (reduced speed) - Reverse left
Left motor: reverse (reduced speed) Right motor: reverse - Reverse right
Left motor: reverse Right motor: reverse (reduced speed) - Spin left (in place)
Left motor: reverse Right motor: forward - Spin right (in place)
Left motor: forward Right motor: reverse
Program
The D-pad on the Wii Remote controls the track direction.
Tilting the remote left or right (held horizontally) adjusts the turning angle.
Here's the sketch to upload to the Arduino UNO:
Fair warning: I accidentally lost the original sketch from the video.
The code below was written fresh for this post and hasn't been tested on the actual hardware.
Let me know if you spot any bugs.
#include <Wii.h>
#include <usbhub.h>
#define R_INR 3
#define R_IN1 1
#define R_IN2 2
#define L_INR 6
#define L_IN1 4
#define L_IN2 5
USB Usb;
USBHub Hub1(&Usb);
BTD Btd(&Usb);
WII Wii(&Btd,PAIR);
void setup() {
Serial.begin(115200);
// Wait for Wii Remote connection
if (Usb.Init() == -1) {
Serial.print(F("\r\nOSC did not start"));
while(1); //halt
}
Serial.print(F("\r\nWiimote Bluetooth Library Started"));
// Set Arduino UNO output pins
pinMode(R_INR, OUTPUT);
pinMode(R_IN1, OUTPUT);
pinMode(R_IN2, OUTPUT);
pinMode(L_INR, OUTPUT);
pinMode(L_IN1, OUTPUT);
pinMode(L_IN2, OUTPUT);
}
void loop() {
Usb.Task();
// Stop if Wii Remote disconnects
if(!Wii.wiimoteConnected) { return; }
if(Wii.getButtonClick(HOME)) {
Serial.println("CLOSE");
Wii.disconnect();
return;
}
// Get tilt angle of horizontally-held remote (0-360)
int pitch = Wii.getPitch();
int right = 0;
int left = 0;
if( 0 <= pitch && pitch <= 90 ){
right = constrain( map(pitch, 0, 45, 0, 255), 0, 255 );
}else if( -90 <= pitch && pitch <= 0 ){
left = constrain( map(pitch, 0,-45, 0, 255), 0, 255 );
}else if( 270 <= pitch ){
left = constrain( map(pitch, 360, 315, 0, 255), 0, 255 );
}
if(Wii.getButtonPress(UP)){
// UP button: both motors forward
digitalWrite(R_IN1, HIGH);
digitalWrite(R_IN2, LOW);
digitalWrite(L_IN1, HIGH);
digitalWrite(L_IN2, LOW);
// Tilt right: slow down right; tilt left: slow down left
analogWrite(R_INR,255 - right);
analogWrite(L_INR,255 - left);
}else if(Wii.getButtonPress(DOWN)){
// DOWN button: both motors reverse
digitalWrite(R_IN1, LOW);
digitalWrite(R_IN2, HIGH);
digitalWrite(L_IN1, LOW);
digitalWrite(L_IN2, HIGH);
// Tilt right: slow down right; tilt left: slow down left
analogWrite(R_INR,255 - right);
analogWrite(L_INR,255 - left);
}else if(Wii.getButtonPress(RIGHT)){
// RIGHT button: spin right (reverse right motor only)
digitalWrite(R_IN1, LOW);
digitalWrite(R_IN2, HIGH);
digitalWrite(L_IN1, HIGH);
digitalWrite(L_IN2, LOW);
analogWrite(R_INR,255);
analogWrite(L_INR,255);
}else if(Wii.getButtonPress(LEFT)){
// LEFT button: spin left (reverse left motor only)
digitalWrite(R_IN1, HIGH);
digitalWrite(R_IN2, LOW);
digitalWrite(L_IN1, LOW);
digitalWrite(L_IN2, HIGH);
analogWrite(R_INR, 255);
analogWrite(L_INR, 255);
} else {
// No button: stop
digitalWrite(R_IN1, LOW);
digitalWrite(R_IN2, LOW);
digitalWrite(L_IN1, LOW);
digitalWrite(L_IN2, LOW);
analogWrite(R_INR, 0);
analogWrite(L_INR, 0);
}
}
LEGO Assembly
Check on Amazon
Build the LEGO however you like.
The one issue: the shaft coming out of the gearbox doesn't match the axle hole size on the LEGO track gear.
The easiest fixes are to fill the hole with hot glue, or to shave down a pinion gear from a Tamiya Mini 4WD kit.
The one issue: the shaft coming out of the gearbox doesn't match the axle hole size on the LEGO track gear.
The easiest fixes are to fill the hole with hot glue, or to shave down a pinion gear from a Tamiya Mini 4WD kit.
And that's the RC car finished.
Hopefully this showed just how much you can build with ~100 lines of Arduino code — a fully wireless remote-controlled vehicle.
Mounting a phone on top for a camera car is also a lot of fun.
I built this to play with my kids.
They completely ignored it. Please do not ask about this.
I later 3D-printed an adapter to connect the gearbox shaft to the LEGO gear.
Source code is available on GitHub.
No comments:
Post a Comment