How I Made a Radio Controlled Roomba Using Arduino
One day, I was browsing the cursed website that is Twitter when I stumbled upon a video from a man named Michael Reeves. Michael had modified a Roomba to scream in pain when it runs into things. I thought this idea was pretty cool, and I wanted to mod my own RC Roomba (with less screaming).
As luck would have it, I was browsing eBay the next day and I found a cheap, broken Roomba for sale.
This was my destiny.
I had so many great ideas of what I could make with this Roomba.
I decided to create a base that could be used for future projects. I wanted a device like a Raspberry Pi to be able to interact with an Arduino over USB serial and control the Roomba. For example, this would allow the Arduino to be controlled by a Raspberry PI using Machine Learning to drive the Roomba to a specific location or object.
I also wanted to change out the motors on the Roomba with better ones to make it run faster. Finally, just for fun, I wanted to be able to control the Roomba with an RC controller.
This post is a log of the steps I took to build the prototype. Please know that this is not the only way to mod your Roomba nor is it even the best way. This is just how I went about modding my Roomba. If you would like to recreate this project for yourself, I would highly recommend branching off and improving from what I did.
Materials Used
1x Roomba: You can buy cheap broken Roombas on eBay, or use your own! I used a broken Roomba 650 I found on eBay. If you do buy a used Roomba, be sure to clean it out thoroughly.
1x Arduino: This is the brains for our robot. I used an Uno, but you could also use a Nano or a Mega if that’s what you have on hand.
2x 12V DC Motors: I used these motors on amazon, but you can use cheaper ones too. I recommend checking your local hobby store.
1x DC Motor driver: You can find these on Amazon or at most hobby stores. I used these drivers, but you can find them for much less at Micro Center.
1x RC Transmitter & Reciever: This is used to control the Roomba. I have a Fly Sky i6 transmitter, and I’m also using the Fly Sky-iA6 Receiver that came with it.
1x 13V Power supply or 1x 13V battery: We need 13 Volts to power our DC motor driver, our DC motors, and our Arduino. I had an extra power supply on hand, so I just used the Roomba plugged into an extension cord. You could also add a battery to make the Roomba wireless. The battery that came with my original Roomba was dead, so I couldn’t repurpose it.
WaGo Lever nuts or a soldering iron: I use WaGo lever nuts to connect wires in small projects like this. A soldering iron or wire nuts will work just as well. I just used these because I had them on hand.
Punch and mallet or hammer
A heat gun or hairdryer
Dremel or hand saw
Hot glue gun
Screw Driver
Sandpaper and/or a File
Zip ties
Duct tape
Jumper cables and/or a crimp set
Wire
Safety glasses
Clamps (optional)
Velcro tape (optional)
Masking tape (optional)
Step One: Disasemballing the Roomba
Unfortunately, I cannot be much help here as I lost the images of my Roomba disassembly. However, I can direct you to this great guide that could be some help.
Essentially the main goal is to remove the vacuum assembly. This will give us enough room to put our electronics in. Then be sure to clean out your Roomba, especially if you bought a broken one on eBay like I did.
Step Two: Removing the Tires
Our next step will be to remove the tires from the wheel assembly. I want to try to use as much of the Roomba as possible so that I’m not wasting parts. If you want to make your own tires you may skip this step, though I would advise against it
First, remove the tire assembly from the Roomba by unscrewing the three Phillips head screws holding it to the body.
Next, remove the suspension spring from the wheel assembly. This will make it a lot easier later on. I just used a pair of pliers to unhook the spring from the plastic shell.
Next, we need to remove the pin holding the wheel and the gear assembly housing to the blue plastic. To do this, I found the most effective method was to use a punch and mallet. Remember to use safety glasses while using the punch.
After you removed the pin, you should be left with just the gear assembly housing.
Next, we need to access the gears. Unscrew the six Phillips head screws and remove the cover.
After we gain access to the internals of the gear assembly, we need to remove the gears. I pried the top three gears off with a flat head screwdriver.
Next, we need to remove the big gear adhered to the wheel axel. To do this we can use a hairdryer or heat gun to soften the adhesive.
Try to aim the heat gun close to where the gear meets the axel. Once the adhesive has softened, use a flathead screwdriver to pry the gear and wheel off of the axel.
Then, slide the wheel and axel away from the plastic housing. Once the wheel has been removed, we need to cut the axel to fit inside of the wheel profile. This will allow us to use a 3D-Printed adapter to connect the wheel axel to the motor. To cut the axel, I just used a saw. A Dremel should also work just fine.
Step Three: Printing and Installing the Wheel Adapter
The next step is to print two of the wheel adapters mentioned earlier.
I designed the wheel adapters with a very low tolerance so I could press fit them into the wheel with minimal glue. Here is the link to the Fusion 360 file if you need to make any modifications to the design
Next, I put a little bit of hot glue inside the wheel. I then used two clamps to press-fit the adapter into the wheel. Then slide the motor into the other end of the Roomba.
Step Three: Printing the Motor Mounts and Installing the Motor
Now, let’s turn our attention back to the Roomba. We need to print the mounts that will allow us to attach the motors to the Roomba base. Here is the link to the Fusion 360 file for the mount.
Place the motor inside of the mount. Then, use a zip tie to secure the motor to the mount. I also wrapped the motor with duct tape for extra friction. Later in the build, I added another motor mount on the back half of the motor. This will not be pictured below, but it will add a lot more stability.
Step Four: Attaching the Motors to The Roomba
Next, we need to cut two small holes across from each other. This is so the wheel can sit in the former location of the wheel assembly while the motor sits where the vacuum was. First, I lined up where I would make the two cuts with masking tape.
Next, I used a saw to cut out around a 15 mm x 12 mm hole in the plastic, or just enough so that the axel can pass through the plastic while allowing the motor mount so sit flush with the base.
Then, be sure to sand down and/or file your cuts until they are smooth. This is to prevent injury and damage to the electronics.
After our holes are cut, it’s time to install the motor mounts to the Roomba. First, I scuffed up the Roomba plastic, and the motor mount, with some sandpaper in the areas I wanted to glue. This was to ensure that the glue would stick.
Next, I used hot glue to secure the motor mount to the Roomba.
Repeat these steps with the other motor.
After gluing the mount, I realized the Roomba was quite unstable with only one motor mount, so I added another one to both sides.
Step Five: Installing the Electronics
As I mentioned before, this project runs off of an Arduino and is controlled by a FlySky RC transmitter/receiver combo. You may also choose to control the Roomba by another means via serial. If you do, just ignore the mentions of the RC receiver.
The first step is to mount the electronics to the Roomba. For this, I used velcro tape for easy removal. You may also choose to glue your components.
Here is how I configured my components.
Next, wire up the components according to this diagram.
For my Roomba, I wired my electronics to an external power source rather than a battery. This was only because I did not have a battery on hand. However, you can wire your Roomba to a battery if you wish.
Step Six: Programing (RC)
If you would like your Roomba to run off an RC controller, the next step is to upload the code for it.
First, we need to calibrate the controller. Open this code in the Arduino IDE.
//Define pins
#define pin 12void setup() {
//Pour a bowl of serial (Yum!)
Serial.begin(9600);
//Set pin to input mode
pinMode(pin, INPUT);
}void loop() {
//Print pulse in
Serial.println(map(pulseIn(pin, HIGH), 1100, 1900, 0, 255));
delay(20);
}
We are using two separate inputs from the RC receiver, our X-axis pin, and our Y-axis pin. Each pin on the receiver corresponds with one transmitter input. You can play around with the receiver and determine which controller configuration works best for you.
First, find the pin on the receiver you want to calibrate. Then, change the “pin” variable in the code to the pin number of the corresponding pin on the Arduino. Connect a wire from that pin on the Arduino to the RC Reciever pin that you want to calibrate. Finally, upload the code to your Roomba and open the serial monitor.
Once the code has been flashed, move the stick you’re calibrating to the maximum position. Then log the corresponding value shown in the serial monitor. Repeat these steps to find the neutral position of the stick. Then, do the same for the other inputs you wish to use.
Once you finish getting the calibration values, we can plug them into the main script below. This will be the script to actually control the Roomba.
/*
RC Roomba Arduino code :)
Made with <3 by Charlie Graymedium.com/@charliegray.dev
*///Define Y axis
#define ch1 13
#define maxValy 279
#define midy 124//Define X axis
#define ch3 12
#define maxValx 282
#define midx 123// Motor A connections
int enA = 2;
int in1 = 7;
int in2 = 6;
// Motor B connections
int enB = 3;
int in3 = 4;
int in4 = 5;//Power going to motors (-255 to 255)
int leftPower;
int rightPower;void setup() {
// Set all the motor control pins to outputs
pinMode(enA, OUTPUT);
pinMode(enB, OUTPUT);
pinMode(in1, OUTPUT);
pinMode(in2, OUTPUT);
pinMode(in3, OUTPUT);
pinMode(in4, OUTPUT); //Set Radio pin to in
pinMode(ch1, INPUT);
pinMode(ch3, INPUT);
// Turn off motors - Initial state
digitalWrite(in1, LOW);
digitalWrite(in2, LOW);
digitalWrite(in3, LOW);
digitalWrite(in4, LOW); // Set speed to 0
analogWrite(enA, 0);
analogWrite(enB, 0);}void loop() { //Get RC
leftPower = clampInt(getRCValue() - getTurnMod()*2,-255,255);
rightPower = clampInt(getRCValue() + getTurnMod()*2,-255,255);
//Left motor //Set L Direction
if (leftPower > 0){
digitalWrite(in1, HIGH);
digitalWrite(in2, LOW);
}
else{
digitalWrite(in1, LOW);
digitalWrite(in2, HIGH);
} //Right motor
//Set R Direction
if (rightPower > 0){
digitalWrite(in3, LOW);
digitalWrite(in4, HIGH);
}
else{
digitalWrite(in3, HIGH);
digitalWrite(in4, LOW);
} //Set R Power
analogWrite(enB, abs(leftPower));
//Set L Speed
analogWrite(enA, abs(rightPower));
}//Get speed from RC Reciever
int getRCValue(){
int zero = map(pulseIn(ch1, HIGH), 1100, 1900, 0, 255)-midy;
float current = (float)zero/(maxValy-midy);if(current > 0.7){
return 255;
}
if(current < -0.7){
return -255;
}
return (0);
}//Get turn multiplier
int getTurnMod(){
int zero = map(pulseIn(ch3, HIGH), 1100, 1900, 0, 255)-midx;
float current = (float)zero/(maxValx-midx);
return (current*255);
}//Clamp intint clampInt(int value, int minClamp, int maxClamp){
if(value>maxClamp){
return maxClamp;
}
if(value<minClamp){
return minClamp;
}
return value;
}
Before we flash the code to the Arduino, we need to change the maximum and neutral calibration for both inputs. You can change those variables at the top of the script. Finally, flash the code to your Roomba, and you’re done! :)
Step 6.5: Programing (Serial)
For me, the main purpose of building this Roomba was to be able to use it as a base for future projects, so I added a script for optional control over USB Serial. This will make it much more scalable if I decide to make future projects involving the Roomba. It will also allow me to interact with the Roomba using a more powerful microcontroller like a Raspberry Pi or a Jetson Nano. Here is the code to control the Roomba with serial.
/*
Serial Controlled Roomba arduino code :)
Made with <3 by Charlie Graymedium.com/@charliegray.dev
*/// Motor A connections
int enA = 2;
int in1 = 8;
int in2 = 7;
// Motor B connections
int enB = 3;
int in3 = 5;
int in4 = 4;//Serial stuff owo
String serialData;//Power going to motors (-255-255)
int leftPower;
int rightPower;void setup() {
// Set all the motor control pins to outputs
pinMode(enA, OUTPUT);
pinMode(enB, OUTPUT);
pinMode(in1, OUTPUT);
pinMode(in2, OUTPUT);
pinMode(in3, OUTPUT);
pinMode(in4, OUTPUT);
// Turn off motors - Initial state
digitalWrite(in1, LOW);
digitalWrite(in2, LOW);
digitalWrite(in3, LOW);
digitalWrite(in4, LOW);// Set speed to 0
analogWrite(enA, 0);
analogWrite(enB, 0);//Open serial stuff
Serial.begin(9600);
Serial.setTimeout(10);
}void loop() {
// put your main code here, to run repeatedly:
}//on serial event
void serialEvent(){//Get Serial string
serialData = Serial.readString();if (serialData.charAt(0) == '!'){
return;
}
// Parse Speeds
leftPower = parseSerialL(serialData);
rightPower = parseSerialR(serialData);Serial.print("!" + String(leftPower));
Serial.print("!" + String(rightPower));
//Left motor//Set L Speed
analogWrite(enA, abs(leftPower));//Set L Direction
if (leftPower > 0){
digitalWrite(in1, HIGH);
digitalWrite(in2, LOW);
}
else{
digitalWrite(in1, LOW);
digitalWrite(in2, HIGH);
}//Right motor//Set R Power
analogWrite(enB, abs(rightPower));
//Set R Direction
if (rightPower > 0){
digitalWrite(in3, HIGH);
digitalWrite(in4, HIGH);
}
else{
digitalWrite(in3, HIGH);
digitalWrite(in4, LOW);
}
}//Gets L value in string
int parseSerialL(String serialData){
serialData.remove(serialData.indexOf(",")); return serialData.toInt();
}//Gets R value in string
int parseSerialR(String serialData){
serialData.remove(0,serialData.indexOf(",")+1);
return serialData.toInt();
}
To use the script, send the Arduino two integers separated by a comma. The first value will be the power sent to the left motor while the second value will be the power sent to the right motor. Make sure that the values are between -255 and 255.
And you’re done!
Thank you so much for reading about my project. I look forward to seeing your own creations and feedback in the comments below \ (•◡•) /