Gesture Controlled Robot Using Arduino

Gesture Controlled Robot Using Arduino

Robots are used in many sectors like construction, military, manufacturing, assembling, etc. Robots can be autonomous or semi-autonomous. Autonomous robots do not require any human intervention and can act on their own according to the situation. Semi-autonomous robots work according to instructions given by humans. These semi-autonomous can be controlled by remote, phone, gestures, etc. We previously built few IoT based robots, which can be controlled from the webserver.

 

In today’s article, we are going to build a gesture-controlled robot using Arduino, MPU6050 Accelerometer, nRF24L01 Transceiver pair, and L293D motor driver module. We will design this robot into two parts. One is the Transmitter, and the other is the Receiver. Transmitter section consists of an Arduino Uno, MPU6050 Accelerometer and Gyroscope, and nRF24L01 while the Receiver section consists of an Arduino Uno, nRF24L01, two DC motors and L293D motor driver. The transmitter will act as remote to control the Robot where the robot will move according to the gestures.

 

Components Required

  • Arduino Uno (2)
  • NRF24L01 (2)
  • MPU6050
  • DC Motor (2)
  • L293D Motor Driver Module
  • Battery

 

MPU6050 Accelerometer and Gyroscope

MPU6050 Module

The MPU6050 sensor module is a complete 6-axis (3-axis Accelerometer and 3-axis Gyroscope) Micro-Electro-Mechanical System. MPU6050 sensor module also has an on-chip temperature sensor. It has an I2C bus and Auxiliary I2C bus interface to communicate with the microcontrollers and other sensor devices like 3-axis Magnetometer, Pressure sensor, etc.

The MPU6050 sensor module is used to measure acceleration, velocity, orientation, displacement, and some other motion-related parameters. This sensor module also has an inbuilt Digital Motion Processor that can perform complex calculations.

 

NRF24L01 Transceiver Module

Pinout of nRF24L01

nRF24L01 is a single-chip radio transceiver for the worldwide 2.4 - 2.5 GHz ISM band. The transceiver consists of a fully integrated frequency synthesizer, a power amplifier, a crystal oscillator, a demodulator, modulator, and Enhanced ShockBurs protocol engine. Output power, frequency channels, and protocol setup are easily programmable through an SPI interface.

The operating voltage range of this Transceiver module is 1.9V to 3.6V. It has Built-in Power Down and Standby modes that make it power-saving and easily realizable.

 

Working of Hand Gesture controlled Robot using Arduino

To understand the working of this Arduino gesture control car, let us divide this project into two parts. The first part is the transmitter part (remote) in which the MPU6050 Accelerometer sensor continuously sends signals to the receiver (Robot) through Arduino and nRF transmitter.

The second part is the Receiver part (Robot car) in which the nRF receiver receives the transmitted data and sends it to Arduino, which further processes them and move the robot accordingly.

Gesture Controlled Robot Using Arduino Working

The MPU6050 Accelerometer sensor reads the X Y Z coordinates and sends the coordinates to the Arduino. For this project, we need only X and Y coordinates. Arduino then checks the values of coordinates and sends the data to the nRF Transmitter. The transmitted data is received by the nRF Receiver. The receiver sends the data to the receiver side’s Arduino. Arduino passes the data to the Motor Driver IC and the motor driver turns the motors in the required direction.

 

DIY Gesture Controlled Robot using Arduino

 

Circuit Diagram

This Hand Gesture controlled Robot using Arduino hardware is divided into two sections

1.      Transmitter

2.      Receiver

 

Transmitter Circuit for Arduino Gesture Controlled Car

Gesture Controlled Robot Transmitter

The transmitter section of this project consists of MPU6050 Accelerometer and Gyroscope, nRF24L01Transceiver, and Arduino Uno. The Arduino continuously gets data from the MPU6050 and sends this data to the nRF Transmitter. RF transmitter transmits the data into the environment.

The circuit diagram for the Transmitter section is given below.

Arduino Gesture Controlled Robot Transmitter Circuit Diagram

nRF24L01

Arduino Uno

VCC

3.3V

GND

GND

CE

Pin 9

CSN

Pin10

SCK

Pin 13

MOSI

11

MISO

12

MPU6050

Arduino Uno

VCC

5V

GND

GND

SCL

Pin A5

SDA

Pin A4

INT

Pin 2

 

Receiver Circuit for Arduino Gesture Controlled Car

Arduino Gesture Controlled Robot Receiver

The receiver section of this gesture controlled robot consists of Arduino Uno, nRF24L01 Transceiver, 2 DC motors, and Motor driver module. NRF24L01 receiver receives the data from the transmitter and sends it to Arduino. Then according to received signals, Arduino moves the DC motors. The circuit diagram for the Receiver section is given below.

Arduino Gesture Controlled Robot Receiver Circuit Diagram

nRF24L01

Arduino Uno

VCC

3.3V

GND

GND

CE

Pin 9

CSN

Pin10

SCK

Pin 13

MOSI

11

MISO

12

Motor Driver

Arduino Uno

VCC

5V

GND

GND

INP A1

2

INP A2

3

INP B1

4

INP B2

5

 

Program Explanation

Complete code for this Gesture controlled robot using Arduino is given at the end of the document. Here we are explaining the program line by line.

 

Transmitter Side Program 

In this program, Arduino reads the data from MPU6050 and sends it to nRF 24L01 transmitter.

Begin the program by adding the required library files. You can download the library files from the given links.

SPI.h
nRF24L01.h
Wire.h
MPU6050.h

#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>
#include "Wire.h"      
#include "I2Cdev.h"    
#include "MPU6050.h"  

 

 

Then define the variables for MPU6050 Gyroscope and Accelerometer data. Here only Accelerometer data will be used.

MPU6050 mpu;
int16_t ax, ay, az;
int16_t gx, gy, gz;

 

Define the Radio pipe addresses for the communication and nRF transmitters CN and CSN pins.

const uint64_t pipeOut = 0xE8E8F0F0E1LL;
RF24 radio(9, 10);

 

Inside the void setup() function, begin the serial monitor. And also initialize the wire and radio communication. radio.setDataRate is used to set the data transmission rate.

void setup()
{
  Serial.begin(9600);
  Wire.begin();
  mpu.initialize();
 radio.begin();
  radio.setAutoAck(false);
  radio.setDataRate(RF24_250KBPS);
  radio.openWritingPipe(pipeOut);
}

 

Read the MPU6050 sensor data. Here we are only using X and Y direction accelerometer data.

mpu.getMotion6(&ax, &ay, &az, &gx, &gy, &gz);
data.X = map(ax, -17000, 17000, 0, 255 );
data.Y = map(ay, -17000, 17000, 0, 255); 

 

Finally, transmit the sensor data using radio.write function.

radio.write(&data, sizeof(MyData));

 

Receiver Side Program 

As usual, start the program by including the required library files.

#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>

 

Define the Radio pipe addresses for the communication and nRF transmitters CN and CSN pins.

const uint64_t pipeIn = 0xE8E8F0F0E1LL;
RF24 radio(9, 10);

 

Define the left and right DC motor pins.

const int IN1 = 2;   
const int IN2 = 3;   
const int IN3 = 4;    
const int IN4 = 5;

 

Now check if the radio is available or not. If it is, then read the data.

if ( radio.available() ) {
    radio.read(&data, sizeof(MyData));

 

Now compare the received data and drive the motors according to the conditions.

if (data.Y < 80) { //Reverse
      digitalWrite(IN1, HIGH);
      digitalWrite(IN2, LOW);
      digitalWrite(IN3, LOW);
      digitalWrite(IN4, HIGH);
    }
……………
……………
……………

 

Testing the Hand Gesture controlled Robot using Arduino

Once the hardware is ready, connect both the transmitter and receiver side Arduinos to your laptop and upload the code. Then move the MPU6050 accelerometer to control the robot Car.

Hand Gesture Controlled Robot using Arduino - Project Setup

The complete working of the Gesture controlled robot can be found in the video given below.

Code

Transmitter Side Program

#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>
#include "Wire.h"       
#include "I2Cdev.h"     
#include "MPU6050.h"    

//Define variables for Gyroscope and Accelerometer data

MPU6050 mpu;
int16_t ax, ay, az;
int16_t gx, gy, gz;

const uint64_t pipeOut = 0xE8E8F0F0E1LL; 

RF24 radio(9, 10); //  CN and CSN  pins of nrf

struct MyData {
  byte X;
  byte Y;
};

MyData data;

void setup()
{
  Serial.begin(9600);
  Wire.begin();
  mpu.initialize();

  radio.begin();
  radio.setAutoAck(false);
  radio.setDataRate(RF24_250KBPS);
  radio.openWritingPipe(pipeOut);
}

void loop()
{
  mpu.getMotion6(&ax, &ay, &az, &gx, &gy, &gz);

  data.X = map(ax, -17000, 17000, 0, 255 ); //Send X axis data
  data.Y = map(ay, -17000, 17000, 0, 255);  //Send Y axis data

  delay(50);
  radio.write(&data, sizeof(MyData));

  Serial.print("Axis X = ");
  Serial.print(data.X);
  Serial.print("  ");
  Serial.print("Axis X = ");
  Serial.println(data.X);
}

 

Receiver Side Program

#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>
const uint64_t pipeIn = 0xE8E8F0F0E1LL; 

RF24 radio(9, 10);

// Left & Right motor pins
const int IN1 = 2;    
const int IN2 = 3;    
const int IN3 = 4;     
const int IN4 = 5;    

struct MyData {
  byte X; 
  byte Y;
};

MyData data;

void setup()
{
  Serial.begin(9600); 
  radio.begin();
  radio.setAutoAck(false);
  radio.setDataRate(RF24_250KBPS);
  radio.openReadingPipe(1, pipeIn);
  radio.startListening();

}

void recvData()
{
  if ( radio.available() ) {
    radio.read(&data, sizeof(MyData));


    if (data.Y < 80) { //Reverse
      digitalWrite(IN1, HIGH);
      digitalWrite(IN2, LOW);
      digitalWrite(IN3, LOW);
      digitalWrite(IN4, HIGH);

    }

    if (data.Y > 145) {//forward
      digitalWrite(IN1, LOW);
      digitalWrite(IN2, HIGH);
      digitalWrite(IN3, HIGH);
      digitalWrite(IN4, LOW);
    }

    if (data.X > 155) {//right turn
      digitalWrite(IN1, LOW);
      digitalWrite(IN2, HIGH);
      digitalWrite(IN3, LOW);
      digitalWrite(IN4, HIGH);
    }

    if (data.X < 80) {//left turn
      digitalWrite(IN1, HIGH);
      digitalWrite(IN2, LOW);
      digitalWrite(IN3, HIGH);
      digitalWrite(IN4, LOW);
    }

    if (data.X > 100 && data.X < 170 && data.Y > 80 && data.Y < 130) { //stop car
      digitalWrite(IN1, LOW);
      digitalWrite(IN2, LOW);
      digitalWrite(IN3, LOW);
      digitalWrite(IN4, LOW);
    }
  }
}

void loop()
{
  recvData();
  Serial.print("X: ");
  Serial.print(data.X);
  Serial.print("    ");
  Serial.print("Y: ");
  Serial.print(data.Y);
  Serial.print("\n");
}
 

Video

5 Comments

My receiver is not giving output of mpu X and Y values. Please help in correcting the codes.

Transmitter code:
#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>
#include "Wire.h"
#include "I2Cdev.h"
#include "MPU6050.h"

MPU6050 mpu;
int16_t ax, ay, az;
int16_t gx, gy, gz;

struct MyData {
byte X;
byte Y;
};

MyData data;

RF24 radio(7, 8); // CE, CSN
const byte address[6] = "00001";

void setup() {
Serial.begin(9600);
Wire.begin();
mpu.initialize();
radio.begin();
radio.openWritingPipe(address);
radio.setPALevel(RF24_PA_MIN);
radio.stopListening();
}
void loop() {
const char text[] = "Hello World";
radio.write(&text, sizeof(text));
mpu.getMotion6(&ax, &ay, &az, &gx, &gy, &gz);
data.X = map(ax, -17000, 17000, 0, 255 ); //Send X axis data
data.Y = map(ay, -17000, 17000, 0, 255); //Send Y axis data
radio.write(&data, sizeof(MyData));

delay(1000);
Serial.println(text);
Serial.print("Axis X = ");
Serial.print(data.X);
Serial.print(" ");
Serial.print("Axis Y = ");
Serial.println(data.Y);
}
Transmitter Output:
Hello World
Axis X = 17 Axis Y = 84
Hello World
Axis X = 17 Axis Y = 83
Hello World
Axis X = 17 Axis Y = 83
Hello World
Axis X = 16 Axis Y = 83
Hello World
Axis X = 17 Axis Y = 83
Hello World
Axis X = 17 Axis Y = 83
Hello World
Axis X = 18 Axis Y = 83
Hello World
Axis X = 16 Axis Y = 84
Hello World
Axis X = 17 Axis Y = 83
Hello World
Axis X = 17 Axis Y = 82

Receiver Code:
#include <SPI.h>
#include <nRF24L01.h>
#include <RF24.h>

struct MyData {
byte X;
byte Y;
};

MyData data;

RF24 radio(7, 8); // CE, CSN
const byte address[6] = "00001";

void setup() {
Serial.begin(9600);
radio.begin();
radio.openReadingPipe(0, address);
radio.setPALevel(RF24_PA_MIN);
radio.startListening();
}

void loop() {
if (radio.available()) {
char text[32] = "";
radio.read(&text, sizeof(text));
Serial.println(text);
radio.read(&data, sizeof(MyData));
Serial.print("Axis X = ");
Serial.print(data.X);
Serial.print(" ");
Serial.print("Axis Y = ");
Serial.println(data.Y);

}
}

Receiver output:
Hello World
Axis X = 0 Axis Y = 0
S
Axis X = 0 Axis Y = 0
Hello World
Axis X = 0 Axis Y = 0
T
Axis X = 0 Axis Y = 0
Hello World
Axis X = 0 Axis Y = 0
S
Axis X = 0 Axis Y = 0
Hello World
Axis X = 0 Axis Y = 0
T
Axis X = 0 Axis Y = 0
Hello World
Axis X = 0 Axis Y = 0
S
Axis X = 0 Axis Y = 0
Hello World
Axis X = 0 Axis Y = 0
S
Axis X = 0 Axis Y = 0