Introduction: Simple Arduino IR Remote Control Tank

The first consideration is Purpose – What is the objective of the robot or device. It is easy to get imaginative with what purposes a robot can serve but it just as important to realise that each and every motion & action has to be practically implementable. Some things may not be practical simply because the cost involved to obtain the precision required may outweigh the benefits of having the robot in the first place. Robotic arms are good example of components that can accomplish a wide variety of task yet have an extremely high entry-level cost to obtain a descent & capable robot arm or hand.

Hence the second consideration is Practical- Is every individual sub-task that forms part of the objective can be accomplished? Often you will find that there are alternative approaches available when you run into problems relating to practicality but there will always be a trade-off to compromise. When starting out designing robots, keep it small and simple. Finally, you have to consider what budget you have available and what your return will yield if the goal is accomplished. For amateur and educational purposes, the expected return may be non-existent other than gaining the experience required, in which case you may not need to work with the most expensive high-tech equipment but simply need to test the concept of working with the principles involved and can use a cheaper module instead. Consider the scenario of building your own CNC or 3D printer: The important part is to understand all the constraints involved and, this can be tested by building the smaller-scale prototype. Instead of building a room-sized 3D printer for your first project, rather build compact desktop-size version instead because you will gain most of the same experience & knowledge but if you do break a motor, gear, pulley or other component, it won’t make an impact on your budget. When scaling up a project physically, many new challenges will come into play that may not directly relate to your task at all. DIY Arduino Project: Wheeled Remote Control Robot Car Let us take on a simple project of building a RC car. The only reason this does not formally qualify as a ‘robot’ is because it not fully automated; the logic will be in the brain of the human and not the machine. Objective: We want our car to be able to drive on-demand, controlled by remote control.

A Chassis – The chassis needs to be rigid, strong and durable. The weight of all the components will be asserting a force on the chassis, high-speed collisions will occur that the chassis must be able to absorb without breaking and the chassis should as light-weight as possible to allow the robot drive faster or carry more sensors. For this project I will be using a robot tank chassis available at

Power Source – The robot needs to be powered somehow. Because this robot is a mobile robot, we cannot simply plug it into the wall to obtain electricity from the grid but rather we need to provide the robot with an on-board battery that is capable of providing enough power to motors that drive the robot. Secondary power sources can be added such as a solar (PV) panel to charge the battery. Lastly, the option of having some sort of docking station to recharge the robot is important if no secondary power sources are available in the field of operation. For this project I will be using a small rechargeable 12V Lead-Acid battery.

Motors – The robot needs to have an appropriate size motor, specifically one that is not to heavy, does not require more power than needed, is fast enough, has enough torque and has a shaft of the right size to either directly connect to the wheel or use a coupler. Robots generally use DC motors due to DC motors being able to obtain the highest speed compared to a stepper motor. If you need very precise motion at the expense of speed then you would use a stepper motor. With a stepper motor it is much easier to turn a specific number of degrees while a DC motor will attempt to spin as fast as possible depending on how much power it is given. My robot chassis being used for this project already contains 2 DC motors included that I will use but any DC motor can be used that fits the scope of the project.
Wheels – The robot’s wheels will determine many properties such a traction, speed and overall weight of the robot. Larger wheels require more force to turn while smaller wheels may slip more easily and not provide enough clearance from the ground to drive over rough terrain. In this project I am using tank tracks instead of traditional wheels but the control is the same ultimately.

Motor Drivers – The motors need to be controlled and the easiest way is to use a standard H-Bridge motor driver. This will allow you to easily control the speed of the motors and also the direction (forward or backward) of the motors. The H-Bridge needs to be able to handle and provide enough current to the motors. For this project I will be using the trusted L298N motor driver available at Leobot Electronics

Micro-controller – The micro-controller of personal choice would an Arduino Uno or Arduino Mega. For small robots, not requiring lots of code or physical IO pins an Arduino Uno would be perfect but if the intention is to have a multitude of sensors or many lines of code then an Arduino Mega would be the better option. Lastly, if physical size is a consideration then an Arduino Nano may be preferred. I will be using the Arduino Uno R3 available from Leobot Electronics

Sensors– Most robots will have a variety of sensor modules for specific tasks. In our case the only sensor we are interested in to start off with is a sensor to communicate with the robot in order to give it commands to drive. We can use an IR transmitter & receiver pair, we can use a RF transmitter & receiver pair or we can use a Wifi module to communicate with the computer to receive commands from a custom application. To keep it simple we will use an IR transmitter & receiver pair. The disadvantage of IR is that it is easy for obstructions to disrupt the signal. On the other hand, RF technology does not require a line of sight to communicate. For this project I will be using a universal IR receiver available at Leobot Electronics and any IR remote control.

First before we start constructing the robot in earnest we first need to make sure we understand all the aspects that we intend to use. It is easier to test modules & sensors in a standalone environment that to test them when already integrated in the rest of the project. Thus, there are 2 aspects that we would want to gain clarity on before we construct the robot:

1) How does one control the motors to drive at a specific RPM and direction (either forward or backward) using the L298N H-Bridge Driver?

2) How does one handle the commands being sent by the IR transmitter with the universal IR receiver?

So first, lets see how can we control the speed and direction of a DC motor with an Arduino.

Step 1: DC Motors

DC Motors

- The direction of a DC motor is determined by the polarity of the power source attached. Switch the connections around and the polarity will change and thus the direction will change.

- The speed of a DC motor is determined by the voltage applied to the motor. The higher the voltage, the faster the motor will turn.

Consider trying to change the direction of a DC motor using only an Arduino: You would need to somehow change the polarity of the motor connections yet the Arduino can only provide an output voltage that is positive is polarity. Thus, an H-Bridge module comes into play. The H-Bridge will allow you to change the polarity of the connections to the motor by changing the state of the H-Bridge directly from an Arduino. This means, the Arduino will communicate with the H-Bridge, which in turn will actually drive the motor in the required direction. This solves the polarity issue.

Next, to correctly set the speed of a DC motor a trick is used, namely Pulse Width Modulation (PWM).

First lets consider how a DC motor rotates at a specific speed. The higher the voltage the faster the motor spins and the lower the applied voltage the slower it turns. It may seem simple enough but if you consider the fact that by providing a lower voltage, lesss current/ampere will flow through the motor and the total power/wattage, determined by Voltage*Ampere, would also decrease. Thus, the lower the applied voltage, the slower the motor but also the less power (torque) it has! Therefore, you do not simply want to change the voltage directly, and this is where Pulse Width Modulation does the trick. PWM means that instead of sending a constant voltage to the motor, we instead send pulses to the motor. The pulse peak will be the maximum voltage that we can provide, and the troth will be 0V.
Essentially, the motor will react to the average voltage being applied to it, while at every instant that voltage is applied it is applied at maximum power, thereby providing high-torque but at a reduced RPM speed. With PWM we can make the motor turn extremely slow but still have the same torque as would have been available at maximum speed. There is a good explanation on how to use the L298N with an Arduino to set the speed using PWM and change directions available here

Next is understanding the IR remote control interface.

Step 2: Universal Infrared Receiver

Our universal IR receiver has a filter to receive only Infrared light and can really be used with any IR transmitter as all IR light signals will be detected by the IR receiver. A basic IR remote will send 8 hexadecimal digits, encoded in binary as IR light. Our IR receiver simply needs to decode this message and react on it. To make life simple, there is a great IR library available that will take care of actually receiving & decoding messages so that you can simply read the result as a set of hexadecimal values. The IR library is available here

To know what messages are actually being sent by a specific IR remote control we simply load the basic IR sketch to dump any signals it receives to the serial port for us to visually inspect. By systematically pressing every key on the remote and saving the value that is received we can easily match signals received with physical buttons on the remote, and then react appropriately as required for that specific button.

Step 3: Arduino Robot Programming

Next up it is time to code the logic of the robot to act as traditional RC Car by responding to only 4 commands, namely Forward, Backward, Left and Right and, use this information to drive the 2 motors.

By pressing Up or Down we will move Forward and Backward respectively. Instead of making this complicated by adding variable acceleration to the robot we will simply crank up the power to both motors to the max. The downside of this is that there will be a big jump in current being drawn from the power source as the motors attempt to instantaneously reach the required speed. To avoid this surge in current usage a gradual climb to the required speed would be preferred. If your Arduino seems to reset at random times when just starting to move forward or backward then you are most likely drawing more current from your battery or power supply than it can provide and definitely need to use a gradual climb instead.

Because we do not want the robot to stutter around between waiting for signals from the remote control, we will give it a countdown time to keep on reacting to the last command given until the timer runs down to 0 or a new command is received.

Here is the full source code for a simple IR Remote Controlled Robot (RC Car). You may want to change the commands being responded to depending on your IR remote being used (as described above):

// Code By Leobot Electronics (

#include IRremote.h

// THESE ARE THE MOTOR PINS // Motor One int enA = 10; int in1 = 9; int in2 = 8; // Motor Two int enB = 5; int in3 = 7; int in4 = 6; // Remote Control IR Receiver Pin int RECV_PIN = 11; int count=0; bool state= 1; IRrecv irrecv(RECV_PIN); decode_results results; void setup() { Serial.begin(9600); // In case the interrupt driver crashes on setup, give a clue // to the user what's going on. //Serial.println("Enabling IRin"); irrecv.enableIRIn(); // Start the receiver // Serial.println("Enabled IRin"); pinMode(enA, OUTPUT); pinMode(enB, OUTPUT); pinMode(in1, OUTPUT); pinMode(in2, OUTPUT); pinMode(in3, OUTPUT); pinMode(in4, OUTPUT); pinMode(loutpin, OUTPUT); } enum EnumDirection { Stop, Up, Down, Left, Right }; EnumDirection currentDirection; int timeDown=0; int timerMax=100; void loop() { bool HasNewVal=false; EnumDirection nextDirection= currentDirection; count++; if(count>=1) { count=0; } if (irrecv.decode(&results)) { //Serial.println(results.value, HEX); irrecv.resume(); // Receive the next value if(results.value==0xFF18E7) { HasNewVal=true; nextDirection= EnumDirection::Up; // Serial.println("up"); } if(results.value==0xFF4AB5) { HasNewVal=true; nextDirection= EnumDirection::Down; // Serial.println("down"); } if(results.value==0xFF10EF) { HasNewVal=true; nextDirection= EnumDirection::Left; // Serial.println("left"); } if(results.value==0xFF5AA5) { HasNewVal=true; nextDirection= EnumDirection::Right; // Serial.println("right"); } if(results.value==0xFFFFFFFF) { HasNewVal=true; // Serial.println("redo last"); } if(results.value==0xFF38C7) { HasNewVal=true; nextDirection= EnumDirection::Stop; // Serial.println("stop"); } } if(HasNewVal) { currentDirection=nextDirection; timeDown=timerMax; } if(timeDown>0) { timeDown--; } if(timeDown>0) { //drive if(nextDirection== EnumDirection::Stop) { StopAll(); } if(nextDirection== EnumDirection::Up) { DriveForward(); } if(nextDirection== EnumDirection::Down) { DriveBackward(); } if(nextDirection== EnumDirection::Left) { DriveLeft(); } if(nextDirection== EnumDirection::Right) { DriveRight(); } } if(timeDown==0) { //turn off StopAll(); } delay(100); } byte speedx=200; void DriveForward() { // turn on motor A digitalWrite(in1, LOW); digitalWrite(in2, HIGH); // set speed to x out of possible range 0~255 analogWrite(enA, speedx); // turn on motor B digitalWrite(in3, LOW); digitalWrite(in4, HIGH); // set speed to x out of possible range 0~255 analogWrite(enB, speedx); } void DriveRight() { // turn on motor A digitalWrite(in1, LOW); digitalWrite(in2, HIGH); // set speed to x out of possible range 0~255 analogWrite(enA, speedx); // turn on motor B digitalWrite(in3, LOW); digitalWrite(in4, HIGH); // set speed to x out of possible range 0~25 5 analogWrite(enB, (byte)speedx/10); } void DriveLeft() { // turn on motor A digitalWrite(in1, LOW); digitalWrite(in2, HIGH); // set speed to x out of possible range 0~255 analogWrite(enA, (byte)speedx/10); // turn on motor B digitalWrite(in3, LOW); digitalWrite(in4, HIGH); // set speed to x out of possible range 0~25 5 analogWrite(enB, speedx); } void DriveBackward() { // turn on motor A digitalWrite(in1, HIGH); digitalWrite(in2, LOW); // set speed to 200 out of possible range 0~255 analogWrite(enA, speedx); // turn on motor B digitalWrite(in3, HIGH); digitalWrite(in4, LOW); // set speed to 200 out of possible range 0~25 5 analogWrite(enB, speedx); } void StopAll() { digitalWrite(in1, LOW); digitalWrite(in2, LOW); digitalWrite(in3, LOW); digitalWrite(in4, LOW); }

Step 4: Final Result: IR RC Tank

This generic template can be used with any 2 wheel drive system, including cars and tanks. It is really simply and you only need the motors, the motor driver and the Arduino to start building a robot using any recycled scraps as a base to cover the rest such as the chassis.

For more information feel free to contact me via