Back to All Blog Posts
Tutorial •EltroNerd Engineering

Arduino Hand-Following Robot Using IR and Ultrasonic Sensors

This Arduino-based robot follows a human hand or object at a fixed distance using IR sensors and an ultrasonic distance sensor. It adjusts direction using two IR sensors (left and right) and maintains a safe distance using an HC-SR04 ultrasonic sensor.

Project Description

The motors are controlled via L298N motor driver logic, and speed is controlled using PWM pins. The logic supports:

  • Forward motion when both IR sensors detect no obstacle and an object is in front.

  • Turning left/right if one IR sensor detects an obstacle.

  • Reversing when both IR sensors detect a wall or object.

  • Stopping if the ultrasonic sensor detects the object is too close (<10cm).

    Hardware Used

  • Arduino Uno

  • HC-SR04 Ultrasonic Sensor

  • 2 x IR Obstacle Sensors

  • L298N Motor Driver Module

  • 2 x DC Motors

  • Battery Pack

Hand-Following Robot code using IR and ultrasonic sensors with DC motors:


🔧 1. Library and Pin Configuration

#include <NewPing.h>

  • Includes the NewPing library to handle ultrasonic sensor measurements with better timing and reliability.
#define IR_RIGHT A2
#define IR_LEFT A3
  • IR sensor pins: A2 for right and A3 for left. These detect black/white surfaces or obstacles.
#define TRIGGER_PIN A1
#define ECHO_PIN A0
#define MAX_DISTANCE 100
  • Defines HC-SR04 ultrasonic sensor pins and max distance in centimeters for sensing.
#define RIGHT_SPEED_PIN 10
#define LEFT_SPEED_PIN 11
  • PWM pins connected to motor driver for controlling motor speed.
#define RIGHT_MOTOR_A 4
#define RIGHT_MOTOR_B 5
#define LEFT_MOTOR_A 6
#define LEFT_MOTOR_B 7
  • Direction control pins for the motor driver. Two pins per motor (H-bridge logic).

2. Constants for Speeds and Distance Thresholds

#define DEFAULT_SPEED 191
#define TURN_SPEED 127
#define MIN_DISTANCE 10
#define MAX_FOLLOW_DISTANCE 30 
  • Speed values and distance thresholds to decide when to follow or stop.

3. Ultrasonic Object Initialization

NewPing sonar(TRIGGER_PIN, ECHO_PIN, MAX_DISTANCE);
  • Creates a sonar object to interact with the ultrasonic sensor.

4. Setup Function

void setup() {
Serial.begin(9600);
pinMode(IR_RIGHT, INPUT);
pinMode(IR_LEFT, INPUT);
pinMode(..., OUTPUT);
motor_stop();
} 
  • Starts serial communication (useful for debugging).
  • Sets IR pins as input and motor pins as output.
  • Calls motor_stop() to keep robot still at start.

5. Main Loop

void loop() {
delay(50);
unsigned int distance = sonar.ping_cm();
int rightIR = digitalRead(IR_RIGHT);
int leftIR = digitalRead(IR_LEFT); 
  • Gets the distance to object in front.
  • Reads IR sensor values (0 = obstacle, 1 = clear).

Then the control logic follows:

Move Forward

if (rightIR == 1 && leftIR == 1 && distance >= 10 && distance <= 30)
  • If no obstacle detected on either side and object is within followable range → move forward.

Turn Right

else if (rightIR == 0 && leftIR == 1) 
  • If obstacle on right → turn right.

Turn Left

else if (rightIR == 1 && leftIR == 0) 
  • If obstacle on left → turn left.

Reverse

else if (rightIR == 0 && leftIR == 0) 
  • If both sides are blocked → reverse to avoid collision.

Stop

else if (distance < 10 || (rightIR == 1 && leftIR == 1)) 
  • If the object is too close or there's nothing to follow → stop.

6. Movement Functions

Each motion control function does:

  • analogWrite() sets motor speed using PWM.
  • digitalWrite() sets motor direction using H-bridge logic.

For example:

void move_forward(int speed) {
analogWrite(...);
digitalWrite(...); // A = HIGH, B = LOW → forward direction
} 

Others like reverse(), turn_left(), and turn_right() follow similar structure but flip the direction control.


motor_stop() Function

void motor_stop() {
analogWrite(..., 0); // Cut off speed
digitalWrite(..., LOW); // Stop motor movement
} 

Summary of Behavior

Condition Action
IR clear, object in range Move forward
Obstacle right Turn right
Obstacle left Turn left
Obstacle both sides Reverse
Too close or idle Stop

Final Code

c
#include <NewPing.h>

// IR Sensor Pins
#define IR_RIGHT A2
#define IR_LEFT A3

// Ultrasonic Sensor Pins
#define TRIGGER_PIN A1
#define ECHO_PIN A0
#define MAX_DISTANCE 100

// Motor Control Pins
#define RIGHT_SPEED_PIN 10
#define LEFT_SPEED_PIN 11
#define RIGHT_MOTOR_A 4
#define RIGHT_MOTOR_B 5
#define LEFT_MOTOR_A 6
#define LEFT_MOTOR_B 7

// Default speeds
#define DEFAULT_SPEED 191
#define TURN_SPEED 127
#define MIN_DISTANCE 10
#define MAX_FOLLOW_DISTANCE 30

NewPing sonar(TRIGGER_PIN, ECHO_PIN, MAX_DISTANCE);

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

  pinMode(IR_RIGHT, INPUT);
  pinMode(IR_LEFT, INPUT);

  pinMode(RIGHT_MOTOR_A, OUTPUT);
  pinMode(RIGHT_MOTOR_B, OUTPUT);
  pinMode(LEFT_MOTOR_A, OUTPUT);
  pinMode(LEFT_MOTOR_B, OUTPUT);

  motor_stop();
}

void loop() {
  delay(50);
  unsigned int distance = sonar.ping_cm();
  int rightIR = digitalRead(IR_RIGHT);
  int leftIR = digitalRead(IR_LEFT);

  if (distance > 1 && distance < MIN_DISTANCE) {
    motor_stop(); // Too close to object
  }
  else if (rightIR == 1 && leftIR == 1 && distance >= MIN_DISTANCE && distance <= MAX_FOLLOW_DISTANCE) {
    move_forward(DEFAULT_SPEED);
  }
  else if (rightIR == 0 && leftIR == 1) {
    turn_right(TURN_SPEED);
  }
  else if (rightIR == 1 && leftIR == 0) {
    turn_left(TURN_SPEED);
  }
  else if (rightIR == 0 && leftIR == 0) {
    move_reverse(TURN_SPEED);
  }
  else {
    motor_stop(); // Default stop
  }
}

// Motion Control Functions
void move_forward(int speed) {
  analogWrite(RIGHT_SPEED_PIN, speed);
  analogWrite(LEFT_SPEED_PIN, speed);

  digitalWrite(RIGHT_MOTOR_A, HIGH);
  digitalWrite(RIGHT_MOTOR_B, LOW);
  digitalWrite(LEFT_MOTOR_A, HIGH);
  digitalWrite(LEFT_MOTOR_B, LOW);
}

void move_reverse(int speed) {
  analogWrite(RIGHT_SPEED_PIN, speed);
  analogWrite(LEFT_SPEED_PIN, speed);

  digitalWrite(RIGHT_MOTOR_A, LOW);
  digitalWrite(RIGHT_MOTOR_B, HIGH);
  digitalWrite(LEFT_MOTOR_A, LOW);
  digitalWrite(LEFT_MOTOR_B, HIGH);
}

void turn_right(int speed) {
  analogWrite(RIGHT_SPEED_PIN, 63);
  analogWrite(LEFT_SPEED_PIN, speed);

  digitalWrite(RIGHT_MOTOR_A, LOW);
  digitalWrite(RIGHT_MOTOR_B, HIGH);
  digitalWrite(LEFT_MOTOR_A, HIGH);
  digitalWrite(LEFT_MOTOR_B, LOW);
}

void turn_left(int speed) {
  analogWrite(RIGHT_SPEED_PIN, speed);
  analogWrite(LEFT_SPEED_PIN, 63);

  digitalWrite(RIGHT_MOTOR_A, HIGH);
  digitalWrite(RIGHT_MOTOR_B, LOW);
  digitalWrite(LEFT_MOTOR_A, LOW);
  digitalWrite(LEFT_MOTOR_B, HIGH);
}

void motor_stop() {
  analogWrite(RIGHT_SPEED_PIN, 0);
  analogWrite(LEFT_SPEED_PIN, 0);

  digitalWrite(RIGHT_MOTOR_A, LOW);
  digitalWrite(RIGHT_MOTOR_B, LOW);
  digitalWrite(LEFT_MOTOR_A, LOW);
  digitalWrite(LEFT_MOTOR_B, LOW);
}

Try this project in your browser

Compile code and simulate hardware output with EltroNerd Cloud IDE.

Launch Cloud IDE