Gesture-Controlled Robot
Hi, my name is Ben, and I am a rising sophomore at Regis High School. For my intensive project, I constructed the gesture-controlled robot. Bend the flex sensors in unique combinations to elicit one of many preset movements from the servos or motors.
Engineer
Ben L
Area of Interest
Electrical Engineering
Computer Science
School
Regis High School
Grade
Incoming Sophomore
Reflection
Method
-
Controlled by flex sensors
Control the servos and motors with flex sensors on the same circuit.
-
Wireless connection
Communication with radio transmission via the NRF modules.
-
Car chassis and glove
Fit each device with all of the proper components.
Final Milestone
void E() {
//clawopen
while (data.text == 69 && pos <= 90) {
pos=pos+30;
myservo1.write(pos);
myRadio.read( &data, sizeof(data));
}
}
The way I controlled the servo was by incrementing its position by 30° each time the loop was run. I set a minimum position for the function that decreased the position and a maximum for the function that increased the position since that is the range the servo can move in to control the servo in the claw mechanism. Anything more extreme might break it.
Car Schematic
void E() {
//clawopen
while (data.text == 69 && pos <= 90) {
pos=pos+30;
myservo1.write(pos);
myRadio.read( &data, sizeof(data));
}
}
Figure 1: Diagram of car chassis. For reference, each square on the grid measures 1″.
#include <SPI.h>
#include “RF24.h”
boolean OnOff = false;
RF24 myRadio (7, 8);
byte addresses[][6] = {“0”};
struct package
{
int id = 1;
float temperature = 18.3;
char text;
};
typedef struct package Package;
Package data;
const int flexPin1 = A0;
const int flexPin2 = A1;
const int flexPin3 = A2;
const int flexPin4 = A3;
const int flexPin5 = A4;
int val1;
int val2;
int val3;
int val4;
int val5;
int n = 10;
float average1;
float average2;
float average3;
float average4;
float average5;
const byte ledPin = 10;
const byte interruptPin = 2;
boolean state = false;
void setup() {
Serial.begin(115200);
delay(1000);
myRadio.begin();
myRadio.setChannel(115);
myRadio.setPALevel(RF24_PA_MAX);
myRadio.setDataRate( RF24_250KBPS ) ;
myRadio.openWritingPipe( addresses[0]);
delay(1000);
pinMode(ledPin, OUTPUT);
pinMode(interruptPin, INPUT);
attachInterrupt(digitalPinToInterrupt(interruptPin), blink, RISING);
pinMode(flexPin1, INPUT);
pinMode(flexPin2, INPUT);
pinMode(flexPin3, INPUT);
pinMode(flexPin4, INPUT);
pinMode(flexPin5, INPUT);
Serial.println(“setup finished”);
}
void vals() {
val1 = analogRead(flexPin1);
average1 = 0;
for (int k = 1; k <= n; k++) {
average1 = average1 + analogRead(flexPin1);
}
average1 = average1 / n;
val2 = analogRead(flexPin2);
average2 = 0;
for (int k = 1; k <= n; k++) {
average2 = average2 + analogRead(flexPin2);
}
average2 = average2 / n;
val3 = analogRead(flexPin3);
average3 = 0;
for (int k = 1; k <= n; k++) {
average3 = average3 + analogRead(flexPin3);
}
average3 = average3 / n;
val4 = analogRead(flexPin4);
average4 = 0;
for (int k = 1; k <= n; k++) {
average4 = average4 + analogRead(flexPin4);
}
average4 = average4 / n;
val5 = analogRead(flexPin5);
average5 = 0;
for (int k = 1; k <= n; k++) {
average5 = average5 + analogRead(flexPin5);
}
average5 = average5 / n;
val1 = map(average1, 500, 810, 0, 100);
val2 = map(average2, 500, 810, 0, 100);
val3 = map(average3, 500, 810, 0, 100);
val4 = map(average4, 500, 810, 0, 100);
val5 = map(average5, 500, 810, 0, 100);
}
void carforward() {
data.text = 65;
//Serial.println(“expecting A”);
OnOff = true;
delay(500);
vals();
OnOff = false;
}
void carbackward() {
data.text = 66;
//Serial.println(“expecting B”);
OnOff = true;
delay(500);
vals();
OnOff = false;
}
void carleft() {
data.text = 67;
//Serial.println(“expecting C”);
OnOff = true;
delay(500);
vals();
OnOff = false;
}
void carright() {
data.text = 68;
//Serial.println(“expecting D”);
OnOff = true;
delay(500);
vals();
OnOff = false;
}
void clawopen () {
data.text = 69;
//Serial.println(“expecting E”);
OnOff = true;
delay(500);
vals();
OnOff = false;
}
void clawclose() {
data.text = 71;
//Serial.println(“expecting G”);
OnOff = true;
delay(500);
vals();
OnOff = false;
}
void noChar() {
data.text = “”;
OnOff = true;
delay(500);
vals();
OnOff = false;
}
void blink() {
state = !state;
digitalWrite(ledPin, state);
}
void loop() {
//Serial.println(“top of loop”);
myRadio.write(&data, sizeof(data));
//Serial.println(“myRadio”);
digitalWrite(ledPin, state);
//Serial.println(“digitalWrite”);
vals();
//Serial.println(“vals”);
/*
Serial.println(val1);
Serial.println(val2);
Serial.println(val3);
Serial.println(val4);
Serial.println(val5);
Serial.println();
*/
if (state == false) {
//Serial.println(“CAR”);
if (val1 < 75 && val2 >= 60 && val3 >= 60 && val4 < 60 && val5 < 60 && OnOff == false) {
carforward();
}
else if (val1 < 75 && val2 < 60 && val3 < 60 && val4 < 60 && val5 < 60 && OnOff == false) {
carbackward();
}
else if (val1 < 75 && val2 >= 60 && val3 >= 60 && val4 >= 60 && val5 < 60 && OnOff == false) {
carleft();
}
else if (val1 < 75 && val2 < 60 && val3 >= 60 && val4 >= 60 && val5 >= 60 && OnOff == false) {
carright();
}
else {
noChar();
}
}
else {
//Serial.println(“CLAW”);
if (val1 < 75 && val2 >= 60 && val3 >= 60 && val4 >= 60 && val5 >= 60 && OnOff == false) {
clawopen();
}
else if (val1 < 75 && val2 < 60 && val3 < 60 && val4 < 60 && val5 < 60 && OnOff == false) {
clawclose();
}
else {
noChar();
}
}
Serial.print(“\nPackage:”);
Serial.print(data.id);
Serial.print(“\n”);
Serial.println(data.temperature);
Serial.println(data.text);
data.id = data.id + 1;
data.temperature = data.temperature + 0.1;
delay(100);
}
#include <SPI.h>
#include “RF24.h”
#include <Servo.h>
Servo myservo1;
RF24 myRadio (7, 8);
struct package
{
int id = 0;
float temperature = 0.0;
char text = ‘e’;
};
byte addresses[][6] = {“0”};
typedef struct package Package;
Package data;
int pos = 180;
const int motor1_1Pin = 10;
const int motor1_2Pin = 2;
const int motor2_1Pin = A0;
const int motor2_2Pin = A1;
const int enablePin = 3;
void setup() {
myservo1.attach(9);
Serial.begin(115200);
pinMode(motor1_1Pin, OUTPUT);
pinMode(motor1_2Pin, OUTPUT);
pinMode(motor2_1Pin, OUTPUT);
pinMode(motor2_2Pin, OUTPUT);
pinMode(enablePin, OUTPUT);
digitalWrite(enablePin, HIGH);
delay(1000);
myRadio.begin();
myRadio.setChannel(115);
myRadio.setPALevel(RF24_PA_MAX);
myRadio.setDataRate(RF24_250KBPS);
myRadio.openReadingPipe(1, addresses[0]);
myRadio.startListening();
}
void A() {
//carforward
digitalWrite(motor1_1Pin, HIGH);
digitalWrite(motor1_2Pin, LOW);
analogWrite(motor2_1Pin, 0);
analogWrite(motor2_2Pin, 1023);
}
void B() {
//carbackward
digitalWrite(motor1_1Pin, LOW);
digitalWrite(motor1_2Pin, HIGH);
analogWrite(motor2_1Pin, 1023);
analogWrite(motor2_2Pin, 0);
}
void C() {
//carleft
digitalWrite(motor1_1Pin, LOW);
digitalWrite(motor1_2Pin, HIGH);
analogWrite(motor2_1Pin, 0);
analogWrite(motor2_2Pin, 1023);
}
void D() {
//carright
digitalWrite(motor1_1Pin, HIGH);
analogWrite(motor1_2Pin, LOW);
analogWrite(motor2_1Pin, 1023);
digitalWrite(motor2_2Pin, 0);
}
void E() {
//clawopen
while (data.text == 69 && pos <= 90) {
pos=pos+30;
myservo1.write(pos);
myRadio.read( &data, sizeof(data));
}
}
void G() {
//clawclose
while (data.text == 71 && pos > 0) {
pos=pos-30;
myservo1.write(pos);
myRadio.read(&data, sizeof(data));
}
}
void loop() {
if (myRadio.available()) {
while (myRadio.available()){
myRadio.read( &data, sizeof(data));
}
Serial.print(“\nPackage:”);
Serial.print(data.id);
Serial.print(“\n”);
Serial.println(data.temperature);
Serial.println(data.text);
if (data.text == 65) {
A();
}
else if (data.text == 66) {
B();
}
else if (data.text == 67) {
C();
}
else if (data.text == 68) {
D();
}
else if (data.text == 69) {
E();
}
else if (data.text == 70) {
G();
}
else {
digitalWrite(motor1_1Pin, 0);
digitalWrite(motor1_2Pin, 0);
digitalWrite(motor2_1Pin, 0);
digitalWrite(motor2_2Pin, 0);
}
}
}
Second Milestone
const byte interruptPin = 2;
void setup() {
pinMode(interruptPin, INPUT);
attachInterrupt(digitalPinToInterrupt(interruptPin), blink, RISING);
}
This change in input is the press of a button and change in state for the LED. I also wrote functions that interpreted different gestures, considering the mode, to send a unique character to the receiving NRF. This would allow the other Arduino to interpret the characters and cause certain movements from either the car or the claw.
One of my main issues for this milestone was inconsistency with the button. For my purposes, bouncing is the tendency of a button to generate multiple signals as it opens or closes a circuit. It is a mechanical part that bounces up and down. This leads to confusion when the Arduino has to determine if the button has been pushed. Debouncing is a method of ensuring that only a single signal will be sent at a time, with no fluctuation. To debounce my circuit, I used a .001 µF 50V capacitor, which functioned to store charge until it releases it all at once, effectively sending one signal at a time. See Figure 2 for the general debouncing circuit used here.
const byte interruptPin = 2;
void setup() {
pinMode(interruptPin, INPUT);
attachInterrupt(digitalPinToInterrupt(interruptPin), blink, RISING);
}
#include <SPI.h>
#include “RF24.h”
boolean OnOff = false;
RF24 myRadio (7, 8);
byte addresses[][6] = {“0”};
struct package
{
int id = 1;
float temperature = 18.3;
char text;
};
typedef struct package Package;
Package data;
const int flexPin1 = A0;
const int flexPin2 = A1;
const int flexPin3 = A2;
const int flexPin4 = A3;
const int flexPin5 = A4;
int val1;
int val2;
int val3;
int val4;
int val5;
int n = 10;
float average1;
float average2;
float average3;
float average4;
float average5;
const byte ledPin = 10;
const byte interruptPin = 2;
boolean state = false;
void setup()
{
Serial.begin(115200);
delay(1000);
myRadio.begin();
myRadio.setChannel(115);
myRadio.setPALevel(RF24_PA_MAX);
myRadio.setDataRate( RF24_250KBPS ) ;
myRadio.openWritingPipe( addresses[0]);
delay(1000);
pinMode(ledPin, OUTPUT);
pinMode(interruptPin, INPUT);
attachInterrupt(digitalPinToInterrupt(interruptPin), blink, RISING);
pinMode(flexPin1, INPUT);
pinMode(flexPin2, INPUT);
pinMode(flexPin3, INPUT);
pinMode(flexPin4, INPUT);
pinMode(flexPin5, INPUT);
Serial.println(“setup finished”);
}
void vals() {
val1 = analogRead(flexPin1);
average1 = 0;
for (int k = 1; k <= n; k++) {
average1 = average1 + analogRead(flexPin1);
}
average1 = average1 / n;
val2 = analogRead(flexPin2);
average2 = 0;
for (int k = 1; k <= n; k++) {
average2 = average2 + analogRead(flexPin2);
}
average2 = average2 / n;
val3 = analogRead(flexPin3);
average3 = 0;
for (int k = 1; k <= n; k++) {
average3 = average3 + analogRead(flexPin3);
}
average3 = average3 / n;
val4 = analogRead(flexPin4);
average4 = 0;
for (int k = 1; k <= n; k++) {
average4 = average4 + analogRead(flexPin4);
}
average4 = average4 / n;
val5 = analogRead(flexPin5);
average5 = 0;
for (int k = 1; k <= n; k++) {
average5 = average5 + analogRead(flexPin5);
}
average5 = average5 / n;
val1 = map(average1, 500, 810, 0, 100);
val2 = map(average2, 500, 810, 0, 100);
val3 = map(average3, 500, 810, 0, 100);
val4 = map(average4, 500, 810, 0, 100);
val5 = map(average5, 500, 810, 0, 100);
}
void carforward() {
data.text = 65;
//Serial.println(“expecting A”);
OnOff = true;
delay(500);
vals();
OnOff = false;
}
void carbackward() {
data.text = 66;
//Serial.println(“expecting B”);
OnOff = true;
delay(500);
vals();
OnOff = false;
}
void carleft() {
data.text = 67;
//Serial.println(“expecting C”);
OnOff = true;
delay(500);
vals();
OnOff = false;
}
void carright() {
data.text = 68;
//Serial.println(“expecting D”);
OnOff = true;
delay(500);
vals();
OnOff = false;
}
void clawopen () {
data.text = 69;
//Serial.println(“expecting E”);
OnOff = true;
delay(500);
vals();
OnOff = false;
}
void clawclose() {
data.text = 70;
//Serial.println(“expecting F”);
OnOff = true;
delay(500);
vals();
OnOff = false;
}
void clawleft() {
data.text = 71;
//Serial.println(“expecting G”);
OnOff = true;
delay(500);
vals();
OnOff = false;
}
void clawright() {
data.text = 72;
//Serial.println(“expecting H”);
OnOff = true;
delay(500);
vals();
OnOff = false;
}
void clawup() {
data.text = 73;
//Serial.println(“expecting I”);
OnOff = true;
delay(500);
vals();
OnOff = false;
}
void clawdown() {
data.text = 74;
//Serial.println(“expecting J”);
OnOff = true;
delay(500);
vals();
OnOff = false;
}
void noChar() {
data.text = “”;
OnOff = true;
delay(500);
vals();
OnOff = false;
}
void blink() {
state = !state;
digitalWrite(ledPin, state);
}
void loop() {
//Serial.println(“top of loop”);
myRadio.write(&data, sizeof(data));
//Serial.println(“myRadio”);
digitalWrite(ledPin, state);
//Serial.println(“digitalWrite”);
vals();
//Serial.println(“vals”);
/*
Serial.println(val1);
Serial.println(val2);
Serial.println(val3);
Serial.println(val4);
Serial.println(val5);
Serial.println();
*/
if (state == false) {
//Serial.println(“CAR”);
if (val1 < 75 && val2 >= 60 && val3 >= 60 && val4 < 60 && val5 < 60 && OnOff == false) {
carforward();
}
else if (val1 < 75 && val2 < 60 && val3 < 60 && val4 < 60 && val5 < 60 && OnOff == false) {
carbackward();
}
else if (val1 < 75 && val2 >= 60 && val3 >= 60 && val4 >= 60 && val5 < 60 && OnOff == false) {
carleft();
}
else if (val1 < 75 && val2 < 60 && val3 >= 60 && val4 >= 60 && val5 >= 60 && OnOff == false) {
carright();
}
else {
noChar();
}
}
else {
//Serial.println(“CLAW”);
if (val1 < 75 && val2 >= 60 && val3 >= 60 && val4 >= 60 && val5 >= 60 && OnOff == false) {
clawopen();
}
else if (val1 < 75 && val2 < 60 && val3 < 60 && val4 < 60 && val5 < 60 && OnOff == false) {
clawclose();
}
else if (val1 < 75 && val2 >= 60 && val3 >= 60 && val4 >= 60 && val5 < 60 && OnOff == false) {
clawleft();
}
else if (val1 < 75 && val2 < 60 && val3 >= 60 && val4 >= 60 && val5 >= 60 && OnOff == false) {
clawright();
}
else if (val1 >= 75 && val2 < 60 && val3 < 60 && val4 < 60 && val5 < 60 && OnOff == false) {
clawup();
}
else if (val1 >= 75 && val2 >= 60 && val3 < 60 && val4 < 60 && val5 < 60 && OnOff == false) {
clawdown();
}
else {
noChar();
}
}
Serial.print(“\nPackage:”);
Serial.print(data.id);
Serial.print(“\n”);
Serial.println(data.temperature);
Serial.println(data.text);
data.id = data.id + 1;
data.temperature = data.temperature + 0.1;
delay(100);
}
#include <SPI.h>
#include “RF24.h”
RF24 myRadio (7, 8);
struct package
{
int id=0;
float temperature = 0.0;
char text =”empty”;
};
byte addresses[][6] = {“0”};
typedef struct package Package;
Package data;
void setup()
{
Serial.begin(115200);
delay(1000);
myRadio.begin();
myRadio.setChannel(115);
myRadio.setPALevel(RF24_PA_MAX);
myRadio.setDataRate( RF24_250KBPS ) ;
myRadio.openReadingPipe(1, addresses[0]);
myRadio.startListening();
}
void loop()
{
if ( myRadio.available()) {
while (myRadio.available()){
myRadio.read( &data, sizeof(data));
}
Serial.print(“\nPackage:”);
Serial.print(data.id);
Serial.print(“\n”);
Serial.println(data.temperature);
Serial.println(data.text);
}
}
First Milestone
val = map(average, 130, 350, 0, 180);
The readings for the flex sensor were very sporadic, so I wrote a for loop that averaged every 50 values to get a more constant data set.
val = map(average, 130, 350, 0, 180);
int flexpin = A0;
int val;
float average;
void loop() {
val = analogRead(flexpin)-454;
average=0;
for(int k=1; k<=50; k++){
average=average+analogRead(flexpin);
}
average=average/50;
int flexpin = A0;
int val;
float average;
void loop() {
val = analogRead(flexpin)-454;
average=0;
for(int k=1; k<=50; k++){
average=average+analogRead(flexpin);
}
average=average/50;
#include <Servo.h>
Servo myservo;
int flexpin = A0;
int val;
float average;
void setup() {
myservo.attach(9);
Serial.begin(9600);
}
void loop() {
val = analogRead(flexpin)-454;
average=0;
for(int k=1; k<=50; k++){
average=average+analogRead(flexpin);
}
average=average/50;
Serial.println(average);
val = map(average, 130, 350, 0, 180);
myservo.write(val);
delay(150);
}
const int flexPin1 = A0; // flex sensor 1 input
const int flexPin2 = A1; // flex sensor 2 input
const int motor1Pin = 3; // H-bridge leg 1 (pin 2, 1A)
const int motor2Pin = 4; // H-bridge leg 2 (pin 7, 2A)
const int enablePin = 9; // H-bridge enable pin
int val1;
int val2;
void setup() {
Serial.begin(9600);
// set the flex sensor as an input:
pinMode(flexPin1, INPUT);
pinMode(flexPin2, INPUT);
// set all the other pins used as outputs:
pinMode(motor1Pin, OUTPUT);
pinMode(motor2Pin, OUTPUT);
pinMode(enablePin, OUTPUT);
// set enablePin high so that motor can turn on:
digitalWrite(enablePin, HIGH);
}
void loop() {
val1 = map(analogRead(flexPin1), 250, 520, 0, 100);
val2 = map(analogRead(flexPin2), 250, 520, 0, 100);
Serial.println(analogRead(flexPin1));
if (val1 >= 50 && val2 >= 50) {
digitalWrite(motor1Pin, 0);
digitalWrite(motor2Pin, 0);
}
// if the switch is low, motor will turn in the other direction:
if (val1 >= 50 && val2 < 50) {
digitalWrite(motor1Pin, 0);
digitalWrite(motor2Pin, 0);
}
if (val1 < 50 && val2 >= 50) {
digitalWrite(motor1Pin, HIGH); // set leg 1 of the H-bridge high
digitalWrite(motor2Pin, LOW); // set leg 2 of the H-bridge low
}
if (val1 < 50 && val2 < 50) {
digitalWrite(motor1Pin, LOW); // set leg 1 of the H-bridge low
digitalWrite(motor2Pin, HIGH); // set leg 2 of the H-bridge high
}
}