Make a Gesture Control Robot at Low Cost
358 Views, 4 Favorites, 0 Comments
Make a Gesture Control Robot at Low Cost
.png)
This tutorial will help you build a car with gesture control by yourself. This is an easy application using MPU-6050's three-axis Gyroscope and Accelerometer. You can perform a myriad of things. By understanding how to use it and how to interface it with Arduino, and how to transfer data using Bluetooth modules. In this article, I will concentrate upon Bluetooth connecting to Bluetooth communication in the case of two HC-05 Bluetooth modules.
Supplies






Connection Diagram


A Diagram of the connection between robot and transmitter unit is provided below. You can refer to them.
one is for the car unit and another one is for the hand unit.
Assambling


.png)
.png)
.png)
.png)
.png)
Assemble both units according to the circuit diagram.
assemble according to the photos and diagram.
Hardware Configuration
.png)
.png)
.png)
.png)
.png)

.png)
We will now discuss Bluetooth modules configuration. In essence, the HC-05 Bluetooth module has an option to set the slave module's factory settings. this means that we can transmit data to the module as soon as we connecting it. there is no need to change any other settings to transfer messages from devices on mobile to HC05 module. Simply enter its default password (1234/0000)to connect to it. But what happens if we want to transfer data via this module to another similar module, or even to a mobile device.
In this project, we're using the same method this project, sending data through this Bluetooth module. Data is collected by the MPU-6050 gyro sensor to other Bluetooth modules.
So, to accomplish this, we have to set up the two Bluetooth modules. So that they will automatically be paired with one another when they are powered on. The first module acts as a slave unit, which receives messages from remote units and is mounted on the vehicle. Also, configure the second as a master device that can act as transmitter units and transmit information directly to the slave devices.
First, you must configure the initial Bluetooth module to be a slave device. To do this, connect it to Arduino according to the wiring diagram.
And upload the code by name configure.
#include <SoftwareSerial.h> SoftwareSerial BTSerial(10, 11); // RX | TX void setup() { Serial.begin(9600); Serial.println("Enter AT commands:"); BTSerial.begin(38400); // HC-05 default speed in AT command more } void loop() { // Keep reading from HC-05 and send to Arduino Serial Monitor if (BTSerial.available()) Serial.write(BTSerial.read()); // Keep reading from Arduino Serial Monitor and send to HC-05 if (Serial.available()) BTSerial.write(Serial.read()); }
Remove the module. Hold and press the Ky on the module until you reconnect it. You'll notice that the led on the module blinked at a slower rate. Each time it happens, it takes 2 seconds. This means that HC-05 has entered its AT commands mode. When you open the serial monitor, adjust the baud speed to 9600 and the output type to the combination of NL & CR. Then type AT in the your send box and then transmit it. If it responds with OK this means that everything is well. If it doesn't, and responds with an error, send AT again. until it replies with OK or chek connections. Then send AT once more .
After you have received a good response from module, enter the following commands, one by one.
AT+ORGL and then send the command. This command will put the module to the factory setting.
AT+RMAAD command will free the the module from any previous pairing
AT+UART? examine the current baud speed of the module
AT+UART=38400, 0, 0. set the baudrate to 38400.
AT+ROLE? Find out if the role is master or slave. It will reply with either the number 1 or 0. If the module is a slave device, it will reply with to 0 and if it's a master device, it will reply with 1.
assign role as slave device. Enter AT+ROLE=0
AT+ADDR? look up the address of the module.
Note this address down. The module responded. Once the module has received this address, the configuration of the slave module is completed.
Now it's time to set your second Bluetooth module to act as the master device. Connect it to an Arduino board and then switch it into AT mode. Similar to what we did with our previous one.
Input these AT commands with the given sequence.
AT+ORGL
AT+RMAAD
AT+UART?
AT+UART=38400, 0, 0
AT+ROLE?
assign the function of this module to be the device that is master. AT+ROLE=1
AT+CMODE=0 means that the module connects to a single device. the default setting is 0
Now you can connect this module to the slave device. To do this, and then press enter.
AT+BIND =" The address for the module slave" and that's it!
Now, you can install the MPU-6050 library sensor. It also supports I2C communication. Because MPU-6050's gyro sensor is equipped with an I2C interface. download libraries and Source code from here: http://www.mediafire.com/file/l8mru5emulb8x93/gesture_control_robot.rar/file
If you've installed these libraries, you can skip this.
The car unit should be connected to the PC via an USB cable. Choose the right connection port and type of board. And upload theprogram by name "Gesture_controled_Robot__car_unit_". Be sure that the battery as well as Bluetooth module are not connected to the vehicle while you upload the application.
//program by Shubham Shinganapure on 3-10-2019 // //for Gesture controled Robotic Car int lm1=8; //left motor output 1 int lm2=9; //left motor output 2 int rm1=10; //right motor output 1 int rm2=11; //right motor output 2 char d=0; void setup() { pinMode(lm1,OUTPUT); pinMode(lm2,OUTPUT); pinMode(rm1,OUTPUT); pinMode(rm2,OUTPUT); Serial.begin(38400); sTOP(); } void loop() { if(Serial.available()>0) { d=Serial.read(); if(d=='F') { ForWard(); } if(d=='B') { BackWard(); } if(d=='L') { Left(); } if(d=='R') { Right(); } if(d=='S') { sTOP(); } } } void ForWard() { digitalWrite(lm1,HIGH); digitalWrite(lm2,LOW); digitalWrite(rm1,HIGH); digitalWrite(rm2,LOW); } void BackWard() { digitalWrite(lm1,LOW); digitalWrite(lm2,HIGH); digitalWrite(rm1,LOW); digitalWrite(rm2,HIGH); } void Left() { digitalWrite(lm1,LOW); digitalWrite(lm2,HIGH); digitalWrite(rm1,HIGH); digitalWrite(rm2,LOW); } void Right() { digitalWrite(lm1,HIGH); digitalWrite(lm2,LOW); digitalWrite(rm1,LOW); digitalWrite(rm2,HIGH); } void sTOP() { digitalWrite(lm1,LOW); digitalWrite(lm2,LOW); digitalWrite(rm1,LOW); digitalWrite(rm2,LOW); }
Similar to your remote device. Start the program with the name remote. Upload this program to your remote unit.
//program modified on 3/10/19 by // by Shubham Shinganapure. // //for Gesture controled Robotic Car (remote ) #include "I2Cdev.h" #include "MPU6050_6Axis_MotionApps20.h" //#include "MPU6050.h" // not necessary if using MotionApps include file // Arduino Wire library is required if I2Cdev I2CDEV_ARDUINO_WIRE implementation // is used in I2Cdev.h #if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE #include "Wire.h" #endif // class default I2C address is 0x68 // specific I2C addresses may be passed as a parameter here // AD0 low = 0x68 (default for SparkFun breakout and InvenSense evaluation board) // AD0 high = 0x69 MPU6050 mpu; #define OUTPUT_READABLE_YAWPITCHROLL // MPU control/status vars bool dmpReady = false; // set true if DMP init was successful uint8_t mpuIntStatus; // holds actual interrupt status byte from MPU uint8_t devStatus; // return status after each device operation (0 = success, !0 = error) uint16_t packetSize; // expected DMP packet size (default is 42 bytes) uint16_t fifoCount; // count of all bytes currently in FIFO uint8_t fifoBuffer[64]; // FIFO storage buffer VectorFloat gravity; Quaternion q; float ypr[3]; // [yaw, pitch, roll] yaw/pitch/roll container and gravity vector uint8_t teapotPacket[14] = { '$', 0x02, 0,0, 0,0, 0,0, 0,0, 0x00, 0x00, '\r', '\n' }; volatile bool mpuInterrupt = false; // indicates whether MPU interrupt pin has gone high void dmpDataReady() { mpuInterrupt = true; } #include <SoftwareSerial.h> SoftwareSerial BTSerial(10, 11); // RX | TX int bt=8; int x =1; void setup() { #if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE Wire.begin(); TWBR = 24; // 400kHz I2C clock (200kHz if CPU is 8MHz) #elif I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE Fastwire::setup(400, true); #endif // initialize serial communication // (115200 chosen because it is required for Teapot Demo output, but it's // really up to you depending on your project) Serial.begin(115200); BTSerial.begin(38400); // while (!Serial); // wait for Leonardo enumeration, others continue immediately Serial.println(F("Initializing I2C devices...")); mpu.initialize(); // verify connection Serial.println(F("Testing device connections...")); Serial.println(mpu.testConnection() ? F("MPU6050 connection successful") : F("MPU6050 connection failed")); // wait for ready // load and configure the DMP Serial.println(F("Initializing DMP...")); devStatus = mpu.dmpInitialize(); // supply your own gyro offsets here, scaled for min sensitivity mpu.setXGyroOffset(220); mpu.setYGyroOffset(76); mpu.setZGyroOffset(-85); mpu.setZAccelOffset(1788); // make sure it worked (returns 0 if so) if (devStatus == 0) { // turn on the DMP, now that it's ready Serial.println(F("Enabling DMP...")); mpu.setDMPEnabled(true); // enable Arduino interrupt detection Serial.println(F("Enabling interrupt detection (Arduino external interrupt 0)...")); attachInterrupt(0, dmpDataReady, RISING); mpuIntStatus = mpu.getIntStatus(); // set our DMP Ready flag so the main loop() function knows it's okay to use it Serial.println(F("DMP ready! Waiting for first interrupt...")); dmpReady = true; // get expected DMP packet size for later comparison packetSize = mpu.dmpGetFIFOPacketSize(); } else { // ERROR! // 1 = initial memory load failed // 2 = DMP configuration updates failed // (if it's going to break, usually the code will be 1) Serial.print(F("DMP Initialization failed (code ")); Serial.print(devStatus); Serial.println(F(")")); } // configure LED for output pinMode(bt,INPUT); } // ================================================================ // === MAIN PROGRAM LOOP === // ================================================================ void loop() { if(digitalRead(bt)==HIGH) { x++; delay(150); } if((x%2)==0){ // if programming failed, don't try to do anything if (!dmpReady) return; // wait for MPU interrupt or extra packet(s) available while (!mpuInterrupt && fifoCount < packetSize) { // other program behavior stuff here // . // . // . // if you are really paranoid you can frequently test in between other // stuff to see if mpuInterrupt is true, and if so, "break;" from the // while() loop to immediately process the MPU data // . // . // . } // reset interrupt flag and get INT_STATUS byte mpuInterrupt = false; mpuIntStatus = mpu.getIntStatus(); // get current FIFO count fifoCount = mpu.getFIFOCount(); // check for overflow (this should never happen unless our code is too inefficient) if ((mpuIntStatus & 0x10) || fifoCount == 1024) { // reset so we can continue cleanly mpu.resetFIFO(); Serial.println(F("FIFO overflow!")); // otherwise, check for DMP data ready interrupt (this should happen frequently) } else if (mpuIntStatus & 0x02) { // wait for correct available data length, should be a VERY short wait while (fifoCount < packetSize) fifoCount = mpu.getFIFOCount(); // read a packet from FIFO mpu.getFIFOBytes(fifoBuffer, packetSize); // track FIFO count here in case there is > 1 packet available // (this lets us immediately read more without waiting for an interrupt) fifoCount -= packetSize; #ifdef OUTPUT_READABLE_YAWPITCHROLL // display Euler angles in degrees mpu.dmpGetQuaternion(&q, fifoBuffer); mpu.dmpGetGravity(&gravity, &q); mpu.dmpGetYawPitchRoll(ypr, &q, &gravity); Serial.print("ypr\t"); Serial.print(ypr[0] * 180/M_PI); Serial.print("\t"); Serial.print(ypr[1] * 180/M_PI); Serial.print("\t"); Serial.println(ypr[2] * 180/M_PI); if((ypr[1] * 180/M_PI)<= -25) {BTSerial.write('F'); } else if((ypr[1] * 180/M_PI)>= 25) {BTSerial.write('B'); } else if((ypr[2] * 180/M_PI)<= -25) {BTSerial.write('L'); } else if((ypr[2] * 180/M_PI)>= 20) {BTSerial.write('R'); } else{ BTSerial.write('S'); } #endif } } else{ BTSerial.write('S'); } }
Install master Bluetooth module in the car unit. Then, connect control the Bluetooth module in the unit remote. Then you're done.
We'll turn it on and then it's all set to go .......
Arduino Code
Here is the Arduino control gesture control robot code. made by the Shubham Shinganapure.
https://www.youtube.com/watch?v=ifcIrTVrGHw
//program modified on 3/10/19 by // by Shubham Shinganapure. // //for Gesture controled Robotic Car (remote ) #include "I2Cdev.h" #include "MPU6050_6Axis_MotionApps20.h" //#include "MPU6050.h" // not necessary if using MotionApps include file // Arduino Wire library is required if I2Cdev I2CDEV_ARDUINO_WIRE implementation // is used in I2Cdev.h #if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE #include "Wire.h" #endif // class default I2C address is 0x68 // specific I2C addresses may be passed as a parameter here // AD0 low = 0x68 (default for SparkFun breakout and InvenSense evaluation board) // AD0 high = 0x69 MPU6050 mpu; #define OUTPUT_READABLE_YAWPITCHROLL // MPU control/status vars bool dmpReady = false; // set true if DMP init was successful uint8_t mpuIntStatus; // holds actual interrupt status byte from MPU uint8_t devStatus; // return status after each device operation (0 = success, !0 = error) uint16_t packetSize; // expected DMP packet size (default is 42 bytes) uint16_t fifoCount; // count of all bytes currently in FIFO uint8_t fifoBuffer[64]; // FIFO storage buffer VectorFloat gravity; Quaternion q; float ypr[3]; // [yaw, pitch, roll] yaw/pitch/roll container and gravity vector uint8_t teapotPacket[14] = { '$', 0x02, 0,0, 0,0, 0,0, 0,0, 0x00, 0x00, '\r', '\n' }; volatile bool mpuInterrupt = false; // indicates whether MPU interrupt pin has gone high void dmpDataReady() { mpuInterrupt = true; } #include <SoftwareSerial.h> SoftwareSerial BTSerial(10, 11); // RX | TX int bt=8; int x =1; void setup() { #if I2CDEV_IMPLEMENTATION == I2CDEV_ARDUINO_WIRE Wire.begin(); TWBR = 24; // 400kHz I2C clock (200kHz if CPU is 8MHz) #elif I2CDEV_IMPLEMENTATION == I2CDEV_BUILTIN_FASTWIRE Fastwire::setup(400, true); #endif // initialize serial communication // (115200 chosen because it is required for Teapot Demo output, but it's // really up to you depending on your project) Serial.begin(115200); BTSerial.begin(38400); // while (!Serial); // wait for Leonardo enumeration, others continue immediately Serial.println(F("Initializing I2C devices...")); mpu.initialize(); // verify connection Serial.println(F("Testing device connections...")); Serial.println(mpu.testConnection() ? F("MPU6050 connection successful") : F("MPU6050 connection failed")); // wait for ready // load and configure the DMP Serial.println(F("Initializing DMP...")); devStatus = mpu.dmpInitialize(); // supply your own gyro offsets here, scaled for min sensitivity mpu.setXGyroOffset(220); mpu.setYGyroOffset(76); mpu.setZGyroOffset(-85); mpu.setZAccelOffset(1788); // make sure it worked (returns 0 if so) if (devStatus == 0) { // turn on the DMP, now that it's ready Serial.println(F("Enabling DMP...")); mpu.setDMPEnabled(true); // enable Arduino interrupt detection Serial.println(F("Enabling interrupt detection (Arduino external interrupt 0)...")); attachInterrupt(0, dmpDataReady, RISING); mpuIntStatus = mpu.getIntStatus(); // set our DMP Ready flag so the main loop() function knows it's okay to use it Serial.println(F("DMP ready! Waiting for first interrupt...")); dmpReady = true; // get expected DMP packet size for later comparison packetSize = mpu.dmpGetFIFOPacketSize(); } else { // ERROR! // 1 = initial memory load failed // 2 = DMP configuration updates failed // (if it's going to break, usually the code will be 1) Serial.print(F("DMP Initialization failed (code ")); Serial.print(devStatus); Serial.println(F(")")); } // configure LED for output pinMode(bt,INPUT); } // ================================================================ // === MAIN PROGRAM LOOP === // ================================================================ void loop() { if(digitalRead(bt)==HIGH) { x++; delay(150); } if((x%2)==0){ // if programming failed, don't try to do anything if (!dmpReady) return; // wait for MPU interrupt or extra packet(s) available while (!mpuInterrupt && fifoCount < packetSize) { // other program behavior stuff here // . // . // . // if you are really paranoid you can frequently test in between other // stuff to see if mpuInterrupt is true, and if so, "break;" from the // while() loop to immediately process the MPU data // . // . // . } // reset interrupt flag and get INT_STATUS byte mpuInterrupt = false; mpuIntStatus = mpu.getIntStatus(); // get current FIFO count fifoCount = mpu.getFIFOCount(); // check for overflow (this should never happen unless our code is too inefficient) if ((mpuIntStatus & 0x10) || fifoCount == 1024) { // reset so we can continue cleanly mpu.resetFIFO(); Serial.println(F("FIFO overflow!")); // otherwise, check for DMP data ready interrupt (this should happen frequently) } else if (mpuIntStatus & 0x02) { // wait for correct available data length, should be a VERY short wait while (fifoCount < packetSize) fifoCount = mpu.getFIFOCount(); // read a packet from FIFO mpu.getFIFOBytes(fifoBuffer, packetSize); // track FIFO count here in case there is > 1 packet available // (this lets us immediately read more without waiting for an interrupt) fifoCount -= packetSize; #ifdef OUTPUT_READABLE_YAWPITCHROLL // display Euler angles in degrees mpu.dmpGetQuaternion(&q, fifoBuffer); mpu.dmpGetGravity(&gravity, &q); mpu.dmpGetYawPitchRoll(ypr, &q, &gravity); Serial.print("ypr\t"); Serial.print(ypr[0] * 180/M_PI); Serial.print("\t"); Serial.print(ypr[1] * 180/M_PI); Serial.print("\t"); Serial.println(ypr[2] * 180/M_PI); if((ypr[1] * 180/M_PI)<= -25) {BTSerial.write('F'); } else if((ypr[1] * 180/M_PI)>= 25) {BTSerial.write('B'); } else if((ypr[2] * 180/M_PI)<= -25) {BTSerial.write('L'); } else if((ypr[2] * 180/M_PI)>= 20) {BTSerial.write('R'); } else{ BTSerial.write('S'); } #endif } } else{ BTSerial.write('S'); } }
Ending
I hope You will like this tutorial after making it.
If you like this helpful please follow me and if you have any doubt please feel free to comment.