abdelkader_ch
Published

Hand Gesture Controlled robot

Make this robot moves by just moving your hand!

ExpertWork in progress15,105
Hand Gesture Controlled robot

Things used in this project

Hardware components

Arduino UNO
Arduino UNO
×1
Arduino Nano R3
Arduino Nano R3
×1
DC Motor, 12 V
DC Motor, 12 V
×1
Dual H-Bridge motor drivers L293D
Texas Instruments Dual H-Bridge motor drivers L293D
×1
HC-05 Bluetooth Module
HC-05 Bluetooth Module
×1
Ultrasonic Sensor - HC-SR04 (Generic)
Ultrasonic Sensor - HC-SR04 (Generic)
×1
9V battery (generic)
9V battery (generic)
×1
Rechargeable Battery, Lithium Ion
Rechargeable Battery, Lithium Ion
×1
Inertial Measurement Unit (IMU) (6 deg of freedom)
Inertial Measurement Unit (IMU) (6 deg of freedom)
×1
Switch Actuator, APEM A01 series Illuminated Push-Button Switches
Switch Actuator, APEM A01 series Illuminated Push-Button Switches
×1
Slide Switch
Slide Switch
×1
PCB's
×1
Robot wheels
×1
Robot chassis
×1

Software apps and online services

Arduino IDE
Arduino IDE

Hand tools and fabrication machines

Soldering Station, 110 V
Soldering Station, 110 V
Solder Wire, Lead Free
Solder Wire, Lead Free
Solder Flux, Soldering
Solder Flux, Soldering

Story

Read more

Schematics

Interfacing of L293D with Arduino

Code

Transmitter code

Arduino
Upload it to the transmission unit.
/*
   Arduino and MPU6050 Accelerometer and Gyroscope Sensor Tutorial
   by Dejan, https://howtomechatronics.com/tutorials/arduino/arduino-and-mpu6050-accelerometer-and-gyroscope-tutorial/
*/

#include <Wire.h>
#include <SoftwareSerial.h>
SoftwareSerial BTSerial(10, 11); // CONNECT BT RX PIN TO ARDUINO 11 PIN | CONNECT BT TX PIN TO ARDUINO 10 PIN


const int MPU_ADDRESS = 0x68; // MPU6050 I2C address

float AccX, AccY, AccZ;
float GyroX, GyroY, GyroZ;

float accAngleX, accAngleY, gyroAngleX, gyroAngleY, gyroAngleZ;
float roll, pitch, yaw;

float AccErrorX, AccErrorY, GyroErrorX, GyroErrorY, GyroErrorZ;

float elapsedTime, currentTime, previousTime;

int c = 0;


void setup()
{
  
  Serial.begin(9600);
  BTSerial.begin(9600);  // HC-05 default speed in AT command more

  Wire.begin();                      // Initialize comunication
  Wire.beginTransmission(MPU_ADDRESS);       // Start communication with MPU6050 // MPU=0x68
  Wire.write(0x6B);                  // Talk to the register 6B
  Wire.write(0x00);                  // Make reset - place a 0 into the 6B register
  Wire.endTransmission(true);        //end the transmission
  
  
  // Configure Accelerometer Sensitivity - Full Scale Range (default +/- 2g)
/*  Wire.beginTransmission(MPU);
  Wire.write(0x1C);                  //Talk to the ACCEL_CONFIG register (1C hex)
  Wire.write(0x10);                  //Set the register bits as 00010000 (+/- 8g full scale range)
  Wire.endTransmission(true);
  
  // Configure Gyro Sensitivity - Full Scale Range (default +/- 250deg/s)
  Wire.beginTransmission(MPU);
  Wire.write(0x1B);                   // Talk to the GYRO_CONFIG register (1B hex)
  Wire.write(0x10);                   // Set the register bits as 00010000 (1000deg/s full scale)
  Wire.endTransmission(true);
  delay(20);
  
  
  //Call this function if you need to get the IMU error values for your module*/
 //while(true) calculate_IMU_error();
  
 // delay(20);
  
}

void loop()
{
  
  MPU_read_accel_data();
  MPU_read_gyro_data();

 
  // calculate time elapsed since last time we were here 
  previousTime = currentTime;        // Previous time is stored before the actual time read
  currentTime = millis();            // Current time actual time read
  elapsedTime = (currentTime - previousTime) / 1000; // Divide by 1000 to get seconds


  // Complementary filter - combine acceleromter and gyro angle values
  roll  = 0.92 * (roll  + (GyroX * elapsedTime)) + 0.08 * accAngleX;
  pitch = 0.92 * (pitch + (GyroY * elapsedTime)) + 0.08 * accAngleY;
  //yaw   = gyroAngleZ;


  // Currently the raw values are in degrees per seconds, deg/s, so we need to multiply by sendonds (s) to get the angle in degrees
  gyroAngleX += GyroX * elapsedTime; // deg/s * s = deg
  gyroAngleY += GyroY * elapsedTime;
  gyroAngleZ += GyroZ * elapsedTime;
  
  /*by me */
  // Print the values on the serial monitor
    Serial.print("roll:");
    Serial.print(roll);
    Serial.print("    ");

    Serial.print("pitch:");
    Serial.println(pitch);
    
   /* Serial.print("    ");
    Serial.print("yaw:");
    Serial.println(yaw);*/
  
  


  /*Serial.print(" ");
/* made by me
  // Print the values on the serial monitor
  Serial.print(pitch);
  Serial.print(" ");
  Serial.print(accAngleY);
  Serial.print(" ");
  Serial.println(gyroAngleY);
*/
if(pitch<-17){
      BTSerial.write('F');
    }else if(pitch>20){
      BTSerial.write('B');
    }else if(roll>30){
      BTSerial.write('R');
    }else if(roll<-30){
      BTSerial.write('L');
    }else if(yaw>30){
      BTSerial.write('r');
    }else if(yaw<-30){
      BTSerial.write('l');
    }else 
      BTSerial.write('S');
}

void MPU_read_accel_data()
{
  // === Read acceleromter data === //
  Wire.beginTransmission(MPU_ADDRESS);
  Wire.write(0x3B); // Start with register 0x3B (ACCEL_XOUT_H)
  Wire.endTransmission(false);
  Wire.requestFrom(MPU_ADDRESS, 6, true); // Read 6 registers total, each axis value is stored in 2 registers
  
  //For a range of +-2g, we need to divide the raw values by 16384, according to the datasheet
  AccX = (Wire.read() << 8 | Wire.read()) / 16384.0; // X-axis value
  AccY = (Wire.read() << 8 | Wire.read()) / 16384.0; // Y-axis value
  AccZ = (Wire.read() << 8 | Wire.read()) / 16384.0; // Z-axis value
  
  // Calculating Roll and Pitch from the accelerometer data
  accAngleX = (atan(AccY / sqrt(pow(AccX, 2) + pow(AccZ, 2))) * 180 / PI)      - (-0.40);  // AccErrorX ~(0.58) See the calculate_IMU_error()custom function for more details
  accAngleY = (atan(-1 * AccX / sqrt(pow(AccY, 2) + pow(AccZ, 2))) * 180 / PI) - (-3.75); // AccErrorY ~(-1.58)
  
}


void MPU_read_gyro_data()
{
  // === Read gyroscope data === //
  Wire.beginTransmission(MPU_ADDRESS);
  Wire.write(0x43); // Gyro data first register address 0x43
  Wire.endTransmission(false);
  Wire.requestFrom(MPU_ADDRESS, 6, true); // Read 4 registers total, each axis value is stored in 2 registers

  // For a 250deg/s range we have to divide first the raw value by 131.0, according to the datasheet
  GyroX = (Wire.read() << 8 | Wire.read()) / 131.0;
  GyroY = (Wire.read() << 8 | Wire.read()) / 131.0;
  GyroZ = (Wire.read() << 8 | Wire.read()) / 131.0;
  
  // Correct the outputs with the calculated error values
  GyroX = GyroX - (-0.68); // GyroErrorX = ~ (-2.12) 
  GyroY = GyroY - (-2.48);  // GyroErrorY = ~ (4.12)
  GyroZ = GyroZ - (-0.12);  // GyroErrorZ = ~ (1.20)


}


void calculate_IMU_error()
{
  
  // We can call this funtion in the setup section to calculate the accelerometer and gyro data error. From here we will get the error values used in the above equations printed on the Serial Monitor.
  // Note that we should place the IMU flat in order to get the proper values, so that we then can the correct values
  // Read accelerometer values 200 times
  while (c < 200)
  {
    Wire.beginTransmission(MPU_ADDRESS);
    Wire.write(0x3B);
    Wire.endTransmission(false);
    Wire.requestFrom(MPU_ADDRESS, 6, true);
    AccX = (Wire.read() << 8 | Wire.read()) / 16384.0 ;
    AccY = (Wire.read() << 8 | Wire.read()) / 16384.0 ;
    AccZ = (Wire.read() << 8 | Wire.read()) / 16384.0 ;
    // Sum all readings
    AccErrorX = AccErrorX + ((atan((AccY) / sqrt(pow((AccX), 2) + pow((AccZ), 2))) * 180 / PI));
    AccErrorY = AccErrorY + ((atan(-1 * (AccX) / sqrt(pow((AccY), 2) + pow((AccZ), 2))) * 180 / PI));
    c++;
  }
  
  //Divide the sum by 200 to get the error value
  AccErrorX = AccErrorX / 200;
  AccErrorY = AccErrorY / 200;
  
  c = 0;
  
  // Read gyro values 200 times
  while (c < 200)
  {
    Wire.beginTransmission(MPU_ADDRESS);
    Wire.write(0x43);
    Wire.endTransmission(false);
    Wire.requestFrom(MPU_ADDRESS, 6, true);
    
    GyroX = Wire.read() << 8 | Wire.read();
    GyroY = Wire.read() << 8 | Wire.read();
    GyroZ = Wire.read() << 8 | Wire.read();
    
    // Sum all readings
    GyroErrorX = GyroErrorX + (GyroX / 131.0);
    GyroErrorY = GyroErrorY + (GyroY / 131.0);
    GyroErrorZ = GyroErrorZ + (GyroZ / 131.0);
    
    c++;
    
  }
  
  //Divide the sum by 200 to get the error value
  GyroErrorX = GyroErrorX / 200;
  GyroErrorY = GyroErrorY / 200;
  GyroErrorZ = GyroErrorZ / 200;
  
  // Print the error values on the Serial Monitor
  
  Serial.print("AccErrorX: ");
  Serial.print(AccErrorX);
  Serial.print(" | AccErrorY: ");
  Serial.print(AccErrorY);
  Serial.print(" | GyroErrorX: ");
  Serial.print(GyroErrorX);
  Serial.print(" | GyroErrorY: ");
  Serial.print(GyroErrorY);
  Serial.print(" | GyroErrorZ: ");
  Serial.println(GyroErrorZ);
  

  delay(1000);
}

Receiver code

Arduino
Upload it code to the reception unit
#include <SoftwareSerial.h>

SoftwareSerial BTSerial(10, 11); // CONNECT BT RX PIN TO ARDUINO 12 PIN | CONNECT BT TX PIN TO ARDUINO 11 PIN
#include<SPI.h>

 
int trigPin = 12;    // Trig
int echoPin = 13;    // Echo
long duration, cm, inches;
int direct;
int l1=3;
int r1=5;
int l2=6;
int r2=9;

int forword_corr;


int a = 0 ;
int s = 3; 


int b = 0 ;
int c = 2; 





void setup() {
  Serial.begin(9600);      
  BTSerial.begin(9600);    
  
 
  pinMode(l1, OUTPUT);
  pinMode(r1, OUTPUT);
  pinMode(l2, OUTPUT);
  pinMode(r2, OUTPUT);
  
  digitalWrite(l1, LOW);
  digitalWrite(r1, LOW);
  digitalWrite(l2, LOW);
  digitalWrite(r2, LOW);
  
  pinMode(trigPin, OUTPUT);
  pinMode(echoPin, INPUT);
}

void loop() {
  
   digitalWrite(trigPin, LOW);
  delayMicroseconds(5);
  digitalWrite(trigPin, HIGH);
  delayMicroseconds(10);
  digitalWrite(trigPin, LOW);

  pinMode(echoPin, INPUT);
  duration = pulseIn(echoPin, HIGH);

  cm = (duration/2) / 29.1;     // Divide by 29.1 or multiply by 0.0343
  Serial.print(cm);
  Serial.print("cm");
  Serial.println();
  if(BTSerial.available()>0){ // Witing for data incoming from the other XBee module
   direct=BTSerial.read();
    
                if(direct == 'B'){
            Serial.println("Backward");
            backward();
          }else if (direct=='F'){
              Serial.println("Forward");
            forward();
          }else if(direct == 'R'){
            Serial.println("Right");
            left();
          }else if(direct == 'L'){
            Serial.println("left");
            right();

           }else if(direct == 'r'){
            Serial.println("rotright");
            rotr();
            
          }else if(direct == 'l'){
            Serial.println("rotleft");
            rotl();
            }else if  (direct == 'S'){
            Serial.println("Stop");
            stopCar();
          }
                
     
           
     
  }
}
    
  


 
void forward()
{
  if(cm<=15){
     digitalWrite(l1, LOW);
      digitalWrite(r2, LOW);

    }
    else{
    digitalWrite(l1, HIGH);
  digitalWrite(r1, LOW);
  digitalWrite(l2, LOW);
  
  
    digitalWrite(r2, LOW);
 delay(2);
    digitalWrite(r2, HIGH);
   delay(2);
}
}
void backward()
{
  digitalWrite(l1, LOW);
  digitalWrite(l2, HIGH);
  digitalWrite(r2, LOW);
  if(b%c == 0){
    digitalWrite(r1, HIGH);
  }else{
    digitalWrite(r1, LOW);
   }
   

    if(b > 1000 ) {
     b=0;
   }
}
void right()
{
  digitalWrite(l1, HIGH);
  digitalWrite(r1, LOW);
  digitalWrite(l2, LOW);
  analogWrite(r2, 100);
 
    

}
void left()
{
   analogWrite(l1, 100);
  digitalWrite(r1, LOW);
  digitalWrite(l2, LOW);
  digitalWrite(r2, HIGH);
}

void stopCar() {
    digitalWrite(l1, LOW);

  digitalWrite(r1, LOW);
  digitalWrite(l2, LOW);
  digitalWrite(r2, LOW);
}
void rotr() {

  digitalWrite(l1, HIGH);
  digitalWrite(r1, LOW);
  digitalWrite(l2, HIGH);
  digitalWrite(r2, LOW);
}
void rotl(){

  digitalWrite(l1, LOW);
  digitalWrite(r1, HIGH);
  digitalWrite(l2, LOW);
  digitalWrite(r2, HIGH);
}

Credits

abdelkader_ch

abdelkader_ch

0 projects • 1 follower

Comments