IR Remote Controlled Arduino Car

by Samyak Vyas in Circuits > Arduino

66 Views, 2 Favorites, 0 Comments

IR Remote Controlled Arduino Car

720602343_1980034625966878_7775912899151938837_n.jpg
719812998_1683530982886682_3580227057596999851_n.jpg

Ever wanted to make your own remote controlled car? In this Instructable, I will take you through the process of how I created an IR remote controlled car with an Arduino Uno. This was a school project which was a great learning experience in electronics, wiring and programming.

The car moves forward, backward, left or right with the control of a Samsung TV remote. It is equipped with two DC motors (L298N motor driver), and an IR receiver which receives the remote's signal. The Arduino receives those signals, and instructs the motors accordingly.

At the end of this guide you will have your own fully functional remote controlled car, built and programmed by you. You don't need to have ever programmed an Arduino before and this guide will take you through each and every step in detail.

Here are some things I learned on this project:


  1. Connecting Arduino to a Motor Driver
  2. How to use the IRremote library to receive signals
  3. How to troubleshoot motors that are reversing.
  4. How to adjust motor speeds to get the car to drive straight

Supplies

images.jpg
images.jpg
979988581.jpg
images.jpg
images.jpg
721247381_1313819717567171_4896941448266140105_n.jpg
Before you start building, you will need to gather all the parts. Here is a complete list of everything I used to build this car. Most of these parts can be found online or at an electronics store.
Electronics:
  1. 1x Arduino Uno
  2. 1x L298N Motor Driver Module
  3. 1x IR Receiver Module (VS1838B or similar)
  4. 1x Samsung TV Remote (or any remote you have the hex codes for)
Motors & Chassis:
  1. 2x DC Micro Servo motor (the kind that come with most car kits)
  2. 1x 2WD car chassis kit (includes wheels and mounting hardware)
Wiring:
  1. Jumper wires (male to male and male to female)
  2. 1x Battery pack (I used a 9V or AA battery pack)
Tools:
  1. Screwdriver
  2. Arduino IDE installed on your computer
  3. USB cable to connect Arduino to computer
Libraries needed:
  1. IRremote library (install via Arduino IDE Library Manager)

Wiring

images.jpg
images.jpg
724340177_1929533328061295_8589479092911285676_n.jpg
This is the most important step of the build. Take your time here and double check every connection before powering anything on. One wrong wire can cause a motor to spin the wrong way or damage your components. I will go through every single connection one by one.
IR Receiver Wiring:
The IR receiver has 3 pins — Signal, VCC, and GND.
  1. Signal pin → Arduino Pin 7
  2. VCC pin → Arduino 5V
  3. GND pin → Arduino GND
L298N Motor Driver Wiring:
The motor driver is the brain between the Arduino and the motors. It takes signals from the Arduino and powers the motors accordingly.
  1. IN1 → Arduino Pin 2
  2. IN2 → Arduino Pin 3
  3. IN3 → Arduino Pin 4
  4. IN4 → Arduino Pin 5
  5. ENA → Arduino Pin 9
  6. ENB → Arduino Pin 10
  7. GND → Arduino GND
  8. VCC → Battery Pack positive
Motor Wiring:
  1. Left motor → Output A terminals on the L298N
  2. Right motor → Output B terminals on the L298N
Battery:
  1. Positive → L298N VCC
  2. Negative → L298N GND and Arduino GND (shared ground)
Important tip: Make sure all GND connections are shared between the Arduino, motor driver, and battery pack. If they are not connected to the same ground, the car will not work properly.
Also keep in mind if that the kit you have has metal, to attach pegs on then hardware components to avoid any disruptions.

Code

Now that everything is wired up, it's time to upload the code. Open the Arduino IDE and make sure you have the IRremote library installed (Sketch → Include Library → Manage Libraries → search "IRremote" → Install).
This project uses the IRremote library, originally developed by Ken Shirriff, to decode signals from the IR remote. My code structure was inspired by tutorials like "How to Build an IR Remote-Controlled Car with Arduino & L298N" on YouTube: https://www.youtube.com/watch?v=wxaWpEyYgPI
Below is the full code I used for my car. I'll explain each section so you understand exactly what it does.
Pin Definitions:
At the top of the code, I define all the pins being used — the IR receiver pin, the motor driver pins (IN1-IN4), and the speed control pins (ENA, ENB). This makes it easy to change pins later without searching through the whole code.
Speed and Trim Settings:
I created variables for drive speed and turn speed so I could easily adjust how fast the car moves. I also added "trim" values for each side, since my motors weren't perfectly matched — one side was naturally a bit weaker than the other, causing the car to drift. The trim values let me boost the weaker motor until the car drives straight.
IR Remote Codes:
Each button on my Samsung remote sends a unique hex code. I found these codes by running a simple test sketch that printed the code to the Serial Monitor every time I pressed a button. I then saved each one (UP, DOWN, LEFT, RIGHT, OK) so my code could recognize which button was pressed.
Motor Control Functions:
I wrote separate functions for forward, backward, turnLeft, turnRight, and stopAll. Each function sets the direction pins (HIGH or LOW) and speed for both motors. Getting the directions right took some trial and error — I had to test each motor individually and flip the HIGH/LOW values until both motors spun the correct way for each movement.
Running Commands:
The runCommand function takes the received IR code and decides which movement function to call. It also handles the "repeat" signal, which is sent when you hold a button down on the remote, so the car keeps moving smoothly instead of stopping and starting.
Setup and Loop:
In setup(), I initialize all the pins and start the IR receiver. In loop(), the code continuously checks if a new IR signal has been received, and if so, runs the matching command.

Here is my complete code(scroll to see entire code):

cpp

#include <IRremote.h>
// ── Pin definitions
#define IR_PIN 7
#define IN1 2
#define IN2 3
#define IN3 4
#define IN4 5
#define ENA 9
#define ENB 10

// ── Speed settings (0–255)
#define DRIVE_SPEED 120
#define TURN_SPEED 80

// increase the SLOWER wheel's side
#define LEFT_TRIM 30
#define RIGHT_TRIM 30

// ── IR remote hex codes (Samsung remote)
#define BTN_UP 0xE0E006F9
#define BTN_DOWN 0xE0E08679
#define BTN_LEFT 0xE0E0A659
#define BTN_RIGHT 0xE0E046B9
#define BTN_OK 0xE0E016E9
#define BTN_REPEAT 0xFFFFFFFF

IRrecv irrecv(IR_PIN);
decode_results results;

uint32_t lastCommand = 0;

// -Motor helper

void setMotors(int leftDir1, int leftDir2,
int rightDir1, int rightDir2,
int leftSpeed, int rightSpeed) {
int l = constrain(leftSpeed + LEFT_TRIM, 0, 255);
int r = constrain(rightSpeed + RIGHT_TRIM, 0, 255);
analogWrite(ENA, l);
analogWrite(ENB, r);
digitalWrite(IN1, leftDir1);
digitalWrite(IN2, leftDir2);
digitalWrite(IN3, rightDir1);
digitalWrite(IN4, rightDir2);
}

void forward() { setMotors(LOW, HIGH, LOW, HIGH, DRIVE_SPEED, DRIVE_SPEED); }
void backward() { setMotors (HIGH, LOW, HIGH, LOW, DRIVE_SPEED, DRIVE_SPEED); }
void turnLeft() { setMotors(LOW, HIGH, HIGH, LOW, TURN_SPEED, TURN_SPEED); }
void turnRight() { setMotors(HIGH, LOW, LOW, HIGH, TURN_SPEED, TURN_SPEED); }
void stopAll() { setMotors(LOW, LOW, LOW, LOW, 0, 0); }

// ── Execute a command

void runCommand(uint32_t cmd) {
switch (cmd) {
case BTN_UP: forward(); Serial.println(">> FORWARD"); break;
case BTN_DOWN: backward(); Serial.println(">> BACKWARD"); break;
case BTN_LEFT: turnLeft(); Serial.println(">> LEFT"); break;
case BTN_RIGHT: turnRight(); Serial.println(">> RIGHT"); break;
case BTN_OK:
stopAll();
lastCommand = 0;
Serial.println(">> STOP");
break;
default:
Serial.print("Unknown code: 0x");
Serial.println(cmd, HEX);
break;
}
}

void setup() {
Serial.begin(9600);

pinMode(LED_BUILTIN, OUTPUT);

// blink 3x on boot so you know Arduino powered up
for (int i = 0; i < 3; i++) {
digitalWrite(LED_BUILTIN, HIGH); delay(200);
digitalWrite(LED_BUILTIN, LOW); delay(200);
}

pinMode(IN1, OUTPUT);
pinMode(IN2, OUTPUT);
pinMode(IN3, OUTPUT);
pinMode(IN4, OUTPUT);
pinMode(ENA, OUTPUT);
pinMode(ENB, OUTPUT);

stopAll();
irrecv.enableIRIn();
Serial.println("IR Car ready.");
}
unsigned long lastSignalTime = 0;
#define SIGNAL_TIMEOUT 300 // stop after 300ms of no signal


void loop() {
if (irrecv.decode(&results)) {
digitalWrite(LED_BUILTIN, HIGH);
uint32_t code = results.value;


if (code == BTN_REPEAT) {
if (lastCommand != 0) {
lastSignalTime = millis();
runCommand(lastCommand);
}
} else {
lastCommand = code;
lastSignalTime = millis();
runCommand(code);
}
irrecv.resume();
digitalWrite(LED_BUILTIN, LOW);
}


// stop if no signal received for SIGNAL_TIMEOUT ms
if (millis() - lastSignalTime > SIGNAL_TIMEOUT) {
stopAll();
lastCommand = 0;
}
}

Final Results

Once you have uploaded the code and double checked all the wiring, it's time to test the car! Park the car, start it up and aim the remote at the IR receiver.

Click the UP button, the car should move forward. Press DOWN to move backwards, press LEFT and RIGHT to turn and press OK to stop. Don't be concerned if your car does not move the way you think, that's normal! This is how I did it to make my own work flawlessly:

I first drove my car, and the motors didn't move the car the way I wanted. The one motor was spinning in the opposite direction, my turns were also in the wrong direction. To correct this, I went through each motor in turn and modified the HIGH/LOW settings in the four functions (forward, backward, turnLeft, turnRight) until the car ran in all directions properly.

Also, I had observed that my car had a tendency to turn to one side when driving straight, as the motor was a little weaker than the other. I solved this by using the value of the weaker motor's trim, LEFT_TRIM and RIGHT_TRIM in my code, the trim value was raised in both directions till the car was driving in a straight line both forward and backward.

After tuning, the car ran superbly! It reacted rapidly to the remote and worked well on all controls.

When building this, if you do, I would strongly recommend running one motor at a time and checking the results before testing the entire car with all of them. It is extremely easy to have trouble getting directions.

Conclusion / Add-ons

0351b8df-e162-4b49-b551-8c796f1ff67e.jpg
download.png
download.jpg

Thanks for following along with my IR remote controlled car project! This was a great way to learn about Arduino, motor control, and IR communication. If you want to take this project further, here are a few add-ons you could try.

1. Headlights that turn on automatically in the dark (using a photoresistor/LDR)

Wiring:

  1. LDR one leg → Arduino 5V
  2. LDR other leg → Arduino A0 AND one leg of a 10kΩ resistor
  3. Other leg of resistor → Arduino GND
  4. LED positive (long leg) → Arduino Pin 8
  5. LED negative (short leg) → 220Ω resistor → Arduino GND



cpp

#define LDR_PIN A0
#define LED_PIN 8
#define DARK_THRESHOLD 400 // adjust based on testing

// add this in setup()
pinMode(LDR_PIN, INPUT);
pinMode(LED_PIN, OUTPUT);

// add this in loop(), before the IR check
int lightLevel = analogRead(LDR_PIN);
if (lightLevel < DARK_THRESHOLD) {
digitalWrite(LED_PIN, HIGH); // dark, turn on LED
} else {
digitalWrite(LED_PIN, LOW); // bright, turn off LED
}

2. A horn that beeps when a specific remote button is pressed (using an active buzzer)

Wiring:

  1. Buzzer positive → Arduino Pin 6
  2. Buzzer negative → Arduino GND



cpp

#define BUZZER_PIN 6
#define BTN_HORN 0xYOURCODEHERE // replace with your button's hex code

// add this in setup()
pinMode(BUZZER_PIN, OUTPUT);

// add this case inside runCommand()
case BTN_HORN:
digitalWrite(BUZZER_PIN, HIGH);
delay(200);
digitalWrite(BUZZER_PIN, LOW);
Serial.println(">> BEEP");
break;

3. An ultrasonic sensor to stop the car automatically before hitting a wall

Wiring:

  1. VCC → Arduino 5V
  2. GND → Arduino GND
  3. Trig → Arduino Pin 11
  4. Echo → Arduino Pin 12



cpp

#include <NewPing.h>
#define TRIG_PIN 11
#define ECHO_PIN 12
#define MAX_DISTANCE 200

NewPing sonar(TRIG_PIN, ECHO_PIN, MAX_DISTANCE);

// add this in loop(), before running forward command
int distance = sonar.ping_cm();
if (distance > 0 && distance < 15) {
stopAll();
Serial.println(">> OBSTACLE DETECTED, STOPPING");
}