1. Range-finder detects if someone has come within 30 cm of the robot and if so, the robot abruptly wakes up, moving its head up and eyes lighting up. The robot's neck pulls up using a servo motor and its eyes have LED's which light up to show it's awake and ready to play.
2. Force Sensitive Resistors in the ears detect the slightest rub and if someone scratches one of its ears, the robot giggles (bobs its head and blinks eyes).
3. Capacitive Sensor in the nose detects if anyone touches the nose. If so, the robot pulls its head back down.
4. Wheels activate if a person messes with the robot's nose too much. The robot moves it's head down and then suddenly rolls away to a side (moves to left or right alternately).
The final breadboard looked somewhat like this: (there are still a few connections missing - which I can't take a picture of since the breadboard is inserted into the robot-body to connect to those).
==========================================
Arduino Code:
#include [servo.h]
#define EYES_OPEN 255
#define EYES_SHUT 0
#define EYES_DIM 30
#define HEAD_HI 10
#define HEAD_LO 100
#define RANGE_NEAR 35
#define RANGE_NEARER 20
#define RANGE_FAR 100
#define R_SAMPLES 20
#define INTERVAL 10000
#define WHEEL_INTERVAL 1000
#define TOUCH_HI 60
#define FSR_HI 30
int HEAD = HEAD_LO;
int EYES = EYES_SHUT;
unsigned long currMillis;
long prevMillis = 0;
long prevWheelMillis = 0;
boolean dir = true;
boolean running = false;
// ##################
// ## Analog Pins: ##
// ##################
// RANGEFINDER VARs
int rangeSum=0; //Create sum variable
int rangeCount = 0;
int rangePrev = RANGE_NEAR;
int rangeCurr = RANGE_FAR;
// FSR VARs
int FSRval1;
int FSRval2;
// ###################
// ## Digital Pins: ##
// ###################
// CAPACITATIVE SENSOR VARs
unsigned int touchX, touchY;
float touchSum, touchOut, touchVal = .07; // these are variables for a simple low-pass (smoothing) filter - touchVal of 1 = no filter - .001 = max filter
// SERVO VARs
Servo myservo; // create servo object to control a servo
int pinTest = 3;
int pinFSR1 = 0;
int pinFSR2 = 1;
int pinRange = 2; // select the input pin for the ultrasonic sensor
const int pinTouchOut = 2;
const int pinTouchIn = 3;
const int pinTouchGrd = 4;
const int pinServo = 5;
const int pinEyes = 6;
const int motor1Pin = 9; // H-bridge leg 1 (pin 2, 1A)
const int motor2Pin = 8; // H-bridge leg 2 (pin 7, 2A)
const int motor3Pin = 11; // H-bridge leg 1 (pin 2, 1A)
const int motor4Pin = 12; // H-bridge leg 2 (pin 7, 2A)
const int enablePin = 10; // H-bridge enable
int runRangeFinder();
int runTouchSensor();
int runFSR();
int noseCount = 0;
void setup()
{
Serial.begin(9600);
pinMode(pinTest, OUTPUT); // TEST LED
pinMode(pinRange, INPUT); // RANGEFINDER
pinMode(pinFSR1, INPUT); // FSR
pinMode(pinFSR2, INPUT); // FSR
pinMode(pinEyes, OUTPUT); // EYES' LEDs
pinMode(pinTouchOut, OUTPUT); // output pin
pinMode(pinTouchIn, INPUT); // input pin
pinMode(pinTouchGrd, OUTPUT); // guard pin
digitalWrite(pinTouchGrd, LOW); // could also be HIGH - don't use this pin for changing output though
myservo.attach(pinServo); // SERVO:
// set all the other pins you're using as outputs:
pinMode(motor1Pin, OUTPUT);
pinMode(motor2Pin, OUTPUT);
pinMode(motor3Pin, OUTPUT);
pinMode(motor4Pin, OUTPUT);
pinMode(enablePin, OUTPUT);
}
void loop()
{
currMillis = millis();
randomSeed(analogRead(pinTouchGrd)); // setting the seed to data from unconnected pin
runRangeFinder();
runTouchSensor();
runFSR();
runWheels();
// when normal --> return to Normal Position
myservo.write(HEAD);
analogWrite (pinEyes, EYES);
/*
Serial.print("\t Touch: ");
Serial.print( (long)touchOut, DEC); // Smoothed Low to High
Serial.print("\t FSR: ");
Serial.print( FSRval);
Serial.println();
*/
delay(10);
}
//==================
// RANGE FINDER
//==================
int runRangeFinder()
{
unsigned long currRangeMillis = millis();
// sampleCount starts life at 0, then loops through sampleSize
rangeSum += analogRead(pinRange);
rangeCount++;
if (rangeCount == R_SAMPLES)
{
rangeCurr= rangeSum/R_SAMPLES;
Serial.print("Range: ");
Serial.print(rangeCurr);
Serial.println();
rangeCount = 0; rangeSum = 0;
if (rangeCurr <= RANGE_NEAR)
rangePrev = RANGE_NEAR;
if (currRangeMillis - prevMillis > INTERVAL )
{
prevMillis = currRangeMillis;
if (rangeCurr >= RANGE_FAR)
rangePrev = rangeCurr;
Serial.print(" Interval - Curr: ");
Serial.print(rangeCurr);
Serial.print(" Prev: ");
Serial.print(rangePrev);
Serial.println();
}
}
if (rangeCurr < RANGE_NEAR)
{
Serial.println("Hi there!");
// talk();
HEAD = ( HEAD > HEAD_HI ? HEAD-=10 : HEAD_HI);
EYES = ( EYES < EYES_OPEN ? EYES+=10 : EYES_OPEN);
}
else if(rangePrev >= RANGE_FAR && rangeCurr >= RANGE_FAR)
{
HEAD = HEAD_LO;
EYES = EYES_SHUT;
}
return 0;
}
//==================
// TOUCH SENSOR:
//==================
int runTouchSensor()
{
touchX = 0; // clear out variables
touchY = 0;
for (int i=0; i < 4 ; i++ )
{ // do it four times to build up an average - not really neccessary but takes out some jitter
digitalWrite(pinTouchOut, HIGH); // LOW-to-HIGH transition
while (digitalRead(pinTouchIn) != 1) touchX++;// while the sense pin is not high
delay(1);
digitalWrite(pinTouchOut, LOW); // HIGH-to-LOW transition
while(digitalRead(pinTouchIn) != 0 ) touchY++;
delay(1);
}
touchOut = (touchVal * (float)touchX) + ((1-touchVal) * touchSum); // Easy smoothing filter "touchVal" determines amount of new data in touchOut
touchSum = touchOut;
// Serial.print(touchOut);
// Serial.println(touchOut);
// when nose touched --> hide
if (touchOut >= TOUCH_HI)
{
Serial.println ("You touched my Nose! :(");
// EYES = EYES_DIM;
// HEAD = HEAD_LO;
myservo.write(HEAD_LO);
analogWrite (pinEyes, EYES_DIM);
noseCount += 1;
Serial.print(" NoseCount: ");
Serial.println(noseCount);
delay (1000);
}
return 0;
}
//==================
// FORCE SENSOR:
//==================
int runFSR()
{
FSRval1 = analogRead(pinFSR1);
FSRval2 = analogRead(pinFSR2);
// when ear rubbed --> laugh
if (FSRval1 >= FSR_HI || FSRval2 >= FSR_HI)
{
Serial.println("Hehehe :D");
for (int i = 0; i < random(2,5); i++)
{
myservo.write(HEAD_HI);
analogWrite (pinEyes, EYES_OPEN);
delay(100);
myservo.write(HEAD_LO);
analogWrite (pinEyes, EYES_DIM);
delay(130);
}
}
// Serial.print(", FSR1: ");
// Serial.print( FSRval1);
// Serial.print(", FSR2: ");
// Serial.println( FSRval2);
// delay (500);
return 0;
}
int runWheels()
{
if (noseCount == 3 || running)
{
if (currMillis - prevWheelMillis > WHEEL_INTERVAL )
{
prevWheelMillis = millis();
if (!running)
{
digitalWrite(enablePin, HIGH);
Serial.println("go!");
running = !running;
}
else
{
Serial.println("stop!");
digitalWrite(enablePin, LOW);
noseCount = 0;
running = !running;
return 1;
}
if (dir)
{
Serial.println("dir1!");
digitalWrite(motor1Pin, LOW); // set leg 1 of the H-bridge low
digitalWrite(motor2Pin, HIGH); // set leg 2 of the H-bridge high
digitalWrite(motor3Pin, LOW); // set leg 1 of the H-bridge low
digitalWrite(motor4Pin, HIGH); // set leg 2 of the H-bridge high
dir = !dir;
}
else
{
Serial.println("dir2!");
digitalWrite(motor1Pin, HIGH); // set leg 1 of the H-bridge low
digitalWrite(motor2Pin, LOW); // set leg 2 of the H-bridge high
digitalWrite(motor3Pin, HIGH); // set leg 1 of the H-bridge low
digitalWrite(motor4Pin, LOW); // set leg 2 of the H-bridge high
dir = !dir;
}
}
}
return 0;
}
#define EYES_OPEN 255
#define EYES_SHUT 0
#define EYES_DIM 30
#define HEAD_HI 10
#define HEAD_LO 100
#define RANGE_NEAR 35
#define RANGE_NEARER 20
#define RANGE_FAR 100
#define R_SAMPLES 20
#define INTERVAL 10000
#define WHEEL_INTERVAL 1000
#define TOUCH_HI 60
#define FSR_HI 30
int HEAD = HEAD_LO;
int EYES = EYES_SHUT;
unsigned long currMillis;
long prevMillis = 0;
long prevWheelMillis = 0;
boolean dir = true;
boolean running = false;
// ##################
// ## Analog Pins: ##
// ##################
// RANGEFINDER VARs
int rangeSum=0; //Create sum variable
int rangeCount = 0;
int rangePrev = RANGE_NEAR;
int rangeCurr = RANGE_FAR;
// FSR VARs
int FSRval1;
int FSRval2;
// ###################
// ## Digital Pins: ##
// ###################
// CAPACITATIVE SENSOR VARs
unsigned int touchX, touchY;
float touchSum, touchOut, touchVal = .07; // these are variables for a simple low-pass (smoothing) filter - touchVal of 1 = no filter - .001 = max filter
// SERVO VARs
Servo myservo; // create servo object to control a servo
int pinTest = 3;
int pinFSR1 = 0;
int pinFSR2 = 1;
int pinRange = 2; // select the input pin for the ultrasonic sensor
const int pinTouchOut = 2;
const int pinTouchIn = 3;
const int pinTouchGrd = 4;
const int pinServo = 5;
const int pinEyes = 6;
const int motor1Pin = 9; // H-bridge leg 1 (pin 2, 1A)
const int motor2Pin = 8; // H-bridge leg 2 (pin 7, 2A)
const int motor3Pin = 11; // H-bridge leg 1 (pin 2, 1A)
const int motor4Pin = 12; // H-bridge leg 2 (pin 7, 2A)
const int enablePin = 10; // H-bridge enable
int runRangeFinder();
int runTouchSensor();
int runFSR();
int noseCount = 0;
void setup()
{
Serial.begin(9600);
pinMode(pinTest, OUTPUT); // TEST LED
pinMode(pinRange, INPUT); // RANGEFINDER
pinMode(pinFSR1, INPUT); // FSR
pinMode(pinFSR2, INPUT); // FSR
pinMode(pinEyes, OUTPUT); // EYES' LEDs
pinMode(pinTouchOut, OUTPUT); // output pin
pinMode(pinTouchIn, INPUT); // input pin
pinMode(pinTouchGrd, OUTPUT); // guard pin
digitalWrite(pinTouchGrd, LOW); // could also be HIGH - don't use this pin for changing output though
myservo.attach(pinServo); // SERVO:
// set all the other pins you're using as outputs:
pinMode(motor1Pin, OUTPUT);
pinMode(motor2Pin, OUTPUT);
pinMode(motor3Pin, OUTPUT);
pinMode(motor4Pin, OUTPUT);
pinMode(enablePin, OUTPUT);
}
void loop()
{
currMillis = millis();
randomSeed(analogRead(pinTouchGrd)); // setting the seed to data from unconnected pin
runRangeFinder();
runTouchSensor();
runFSR();
runWheels();
// when normal --> return to Normal Position
myservo.write(HEAD);
analogWrite (pinEyes, EYES);
/*
Serial.print("\t Touch: ");
Serial.print( (long)touchOut, DEC); // Smoothed Low to High
Serial.print("\t FSR: ");
Serial.print( FSRval);
Serial.println();
*/
delay(10);
}
//==================
// RANGE FINDER
//==================
int runRangeFinder()
{
unsigned long currRangeMillis = millis();
// sampleCount starts life at 0, then loops through sampleSize
rangeSum += analogRead(pinRange);
rangeCount++;
if (rangeCount == R_SAMPLES)
{
rangeCurr= rangeSum/R_SAMPLES;
Serial.print("Range: ");
Serial.print(rangeCurr);
Serial.println();
rangeCount = 0; rangeSum = 0;
if (rangeCurr <= RANGE_NEAR)
rangePrev = RANGE_NEAR;
if (currRangeMillis - prevMillis > INTERVAL )
{
prevMillis = currRangeMillis;
if (rangeCurr >= RANGE_FAR)
rangePrev = rangeCurr;
Serial.print(" Interval - Curr: ");
Serial.print(rangeCurr);
Serial.print(" Prev: ");
Serial.print(rangePrev);
Serial.println();
}
}
if (rangeCurr < RANGE_NEAR)
{
Serial.println("Hi there!");
// talk();
HEAD = ( HEAD > HEAD_HI ? HEAD-=10 : HEAD_HI);
EYES = ( EYES < EYES_OPEN ? EYES+=10 : EYES_OPEN);
}
else if(rangePrev >= RANGE_FAR && rangeCurr >= RANGE_FAR)
{
HEAD = HEAD_LO;
EYES = EYES_SHUT;
}
return 0;
}
//==================
// TOUCH SENSOR:
//==================
int runTouchSensor()
{
touchX = 0; // clear out variables
touchY = 0;
for (int i=0; i < 4 ; i++ )
{ // do it four times to build up an average - not really neccessary but takes out some jitter
digitalWrite(pinTouchOut, HIGH); // LOW-to-HIGH transition
while (digitalRead(pinTouchIn) != 1) touchX++;// while the sense pin is not high
delay(1);
digitalWrite(pinTouchOut, LOW); // HIGH-to-LOW transition
while(digitalRead(pinTouchIn) != 0 ) touchY++;
delay(1);
}
touchOut = (touchVal * (float)touchX) + ((1-touchVal) * touchSum); // Easy smoothing filter "touchVal" determines amount of new data in touchOut
touchSum = touchOut;
// Serial.print(touchOut);
// Serial.println(touchOut);
// when nose touched --> hide
if (touchOut >= TOUCH_HI)
{
Serial.println ("You touched my Nose! :(");
// EYES = EYES_DIM;
// HEAD = HEAD_LO;
myservo.write(HEAD_LO);
analogWrite (pinEyes, EYES_DIM);
noseCount += 1;
Serial.print(" NoseCount: ");
Serial.println(noseCount);
delay (1000);
}
return 0;
}
//==================
// FORCE SENSOR:
//==================
int runFSR()
{
FSRval1 = analogRead(pinFSR1);
FSRval2 = analogRead(pinFSR2);
// when ear rubbed --> laugh
if (FSRval1 >= FSR_HI || FSRval2 >= FSR_HI)
{
Serial.println("Hehehe :D");
for (int i = 0; i < random(2,5); i++)
{
myservo.write(HEAD_HI);
analogWrite (pinEyes, EYES_OPEN);
delay(100);
myservo.write(HEAD_LO);
analogWrite (pinEyes, EYES_DIM);
delay(130);
}
}
// Serial.print(", FSR1: ");
// Serial.print( FSRval1);
// Serial.print(", FSR2: ");
// Serial.println( FSRval2);
// delay (500);
return 0;
}
int runWheels()
{
if (noseCount == 3 || running)
{
if (currMillis - prevWheelMillis > WHEEL_INTERVAL )
{
prevWheelMillis = millis();
if (!running)
{
digitalWrite(enablePin, HIGH);
Serial.println("go!");
running = !running;
}
else
{
Serial.println("stop!");
digitalWrite(enablePin, LOW);
noseCount = 0;
running = !running;
return 1;
}
if (dir)
{
Serial.println("dir1!");
digitalWrite(motor1Pin, LOW); // set leg 1 of the H-bridge low
digitalWrite(motor2Pin, HIGH); // set leg 2 of the H-bridge high
digitalWrite(motor3Pin, LOW); // set leg 1 of the H-bridge low
digitalWrite(motor4Pin, HIGH); // set leg 2 of the H-bridge high
dir = !dir;
}
else
{
Serial.println("dir2!");
digitalWrite(motor1Pin, HIGH); // set leg 1 of the H-bridge low
digitalWrite(motor2Pin, LOW); // set leg 2 of the H-bridge high
digitalWrite(motor3Pin, HIGH); // set leg 1 of the H-bridge low
digitalWrite(motor4Pin, LOW); // set leg 2 of the H-bridge high
dir = !dir;
}
}
}
return 0;
}