// Includes
#include <SoftwareSerial.h>
#include <Servo.h>
#include <EEPROM.h>
#include <Wire.h>
// I2C slaves addresses
#define MotorController 60
#define Thermo 208>>1
#define Compass 42>>1
// I2C commands
#define Forward 1
#define Reverse 2
#define Left 3
#define Right 4
#define Stop 5
// LCD pins
#define txPin 2 // digital pin 2
#define rxPin 13 // digital pin 13, not used for the LCD
// Servo pins
#define TiltPin 3 // digital pin 3, PWM pin (6V power)
#define RshoulderPin 5 // digital pin 5, PWM pin (6V power)
#define LshoulderPin 6 // digital pin 6, PWM pin (6V power)
#define ScanPin 7 // digital pin 7 (regulated 5V power)
#define PanPin 8 // digital pin 8 (regulated 5V power)
#define RarmPin 9 // digital pin 9, PWM pin (6V power)
#define LarmPin 10 // digital pin 10, PWM pin (6V power)
#define WaistPin 11 // digital pin 11, PWM pin (6V power)
// Media pins
#define speakerOut 12 // digital pin 12
#define ledPin 13 // digital pin 13
// Sensor pins
#define PingPin 4 // digital pin 4
#define BattSensor 0 // analog pin 0
#define TouchPin 1 // analog pin 1
#define IR_Pin 16 // digital pin 16 (analog pin 2)
#define SharpPin 3 // analog pin 3
// Moves
byte Stand_By = 0;
byte Rarm_Wave = 1;
byte Pick_Up_Object = 2;
byte Release = 3;
// Servos
Servo Scan;
Servo Waist;
Servo Lshoulder;
Servo Rshoulder;
Servo Larm;
Servo Rarm;
Servo Pan;
Servo Tilt;
// Software serial
SoftwareSerial LcdSerial = SoftwareSerial(rxPin, txPin);
// Sensor Variables
unsigned int PingDistance = 0;
byte IrDistance = 0;
byte TouchVal = 0;
int temperature[] = {0,0,0,0,0,0,0,0,0}; // Array to hold temperature data
// servo variables
#define center 80
byte direction = 1;
byte object = 0;
//servos: stepDeleay, Waist, Lshould, Rshould, Larm, Rarm, Tilt, Pan
byte oldPos[8] = {0, 70, 180, 180, 80, 90, 80, 80};
byte Speed = 0;
byte Distance = 0;
byte Degrees = 0;
byte Object_here = 3; // object is closer than 3
byte moveNumber = 0;
byte sv = 1;
boolean teachMode = 0;
byte pos = 80;
byte index = 1;
byte pos_delay = 0;
boolean move = 0;
boolean stored = 0;
boolean state = 0;
// Play Melody variables
byte names[] = {'c', 'd', 'e', 'f', 'g', 'a', 'b', 'C'};
int tones[] = {1915, 1700, 1519, 1432, 1275, 1136, 1014, 956};
byte melody[] = "2d2a1f2c2d2a2d2c2f2d2a2c2d2a1f2c2d2a2a2g2p8p8p8p";
// count length: 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0
// 10 20 30
int count = 0;
int count2 = 0;
int count3 = 0;
int MAX_COUNT = 24;
void setup() {
Wire.begin(); // join i2c bus (address optional for master)
//hardware serial
Serial.begin(9600);
//software serial for LCD
pinMode(rxPin, INPUT);
pinMode(txPin, OUTPUT);
LcdSerial.begin(9600);
LCDposition(1, 1);
LcdSerial.print("Mini Eric");
LCDposition(2, 5);
LcdSerial.print("robot");
delay(1000); //wait a second
LCDclear();
//media
pinMode(ledPin, OUTPUT);
pinMode(speakerOut, OUTPUT);
//sensors
pinMode(PingPin, OUTPUT);
digitalWrite(PingPin, LOW);
//servos
Scan.attach(ScanPin);
Pan.attach(PanPin);
Tilt.attach(TiltPin);
Waist.attach(WaistPin);
Lshoulder.attach(LshoulderPin);
Rshoulder.attach(RshoulderPin);
Larm.attach(LarmPin);
Rarm.attach(RarmPin);
Pan.write(center); // 0 - 80 - 170
Tilt.write(center); // 0 - 80 - 180
Scan.write(center); // 40 - 85 - 130 ; 40 = left, 130 = right
Larm.write(center); // 0 - 80 - 180
Rarm.write(center+10); // 0 - 80 - 180; 0 =
Lshoulder.write(center+100); // 0 - 80 - 180
Rshoulder.write(center+100); // 0 - 80 - 180 ; 0 = Up, 180 = Down
Waist.write(center-10); // 70 = Up, 150 = Down
}
// Main Loop
void loop(){
state = !state;
digitalWrite(ledPin, state);
Trigger_Wave_Hand();
//Trigger_Music();
Trigger_Pick_Object();
//Trigger_Release();
delay(1000); // delay a second to see the values
Find_Hot_Object();
delay(1000); // delay a second to see the values
}
int Read_Ping_Sensor() {
//trigger the sensor
int Ping = 0;
pinMode(PingPin, OUTPUT);
digitalWrite(PingPin, LOW);
delayMicroseconds(2);
digitalWrite(PingPin, HIGH);
delayMicroseconds(5);
digitalWrite(PingPin, LOW);
//receive the echo
pinMode(PingPin, INPUT);
Ping = pulseIn(PingPin, HIGH);
return Ping/29/2; // convert to cm
}
int Read_Sharp_Sensor() {
int value = 0;
value = analogRead(SharpPin);
return 509.88*pow(value,-.9154); // convert to cm
}
int Read_Touch_Sensor() {
int Touch=analogRead(TouchPin);
return Touch;
}
void Read_Thermopile_Array(){
for(int i = 0; i < 9; i++){ // Loops and stores temperature data in array
temperature[i] = getTemp(i+1);
}
}
int getTemp(int reg){ // Function to receive one byte of data from TPA81
Wire.beginTransmission(Thermo); // Begin communication with TPA81
Wire.send(reg); // Send reg to TPA81
Wire.endTransmission();
Wire.requestFrom(Thermo, 1); // Request 1 byte
while(Wire.available() < 1); // Wait for byte to arrive
int data = Wire.receive(); // Get byte
return(data); // return byte
}
void Trigger_Wave_Hand() {
PingDistance = Read_Ping_Sensor();
LCDposition(1, 1);
LcdSerial.print("Ping Dist: ");
LcdSerial.print(PingDistance, DEC);
LcdSerial.print(" ");
if (PingDistance < 40 && PingDistance > 30){
Play_Move(Rarm_Wave);
}
}
void Trigger_Music() {
PingDistance = Read_Ping_Sensor();
LCDposition(1, 1);
LcdSerial.print("Ping Dist: ");
LcdSerial.print(PingDistance, DEC);
LcdSerial.print(" ");
if (PingDistance < 30 && PingDistance > 20)
{
Play_Melody();
}
}
void Trigger_Pick_Object() {
IrDistance = Read_Sharp_Sensor();
LCDposition(2, 1);
LcdSerial.print("Sharp Dist: ");
LcdSerial.print(IrDistance, DEC);
LcdSerial.print(" ");
if (IrDistance < Object_here){
Play_Move(Pick_Up_Object);
object = 1;
}
}
void Trigger_Release() {
PingDistance = Read_Ping_Sensor();
LCDposition(1, 1);
LcdSerial.print("Ping Dist: ");
LcdSerial.print(PingDistance, DEC);
LcdSerial.print(" ");
if (PingDistance < 20) {
Play_Move(Release);
object = 0;
}
}
void Find_Hot_Object() {
Read_Thermopile_Array();
byte cluster = 0;
int hotObject = temperature[0]; // ambient temperature
for(byte i = 1; i < 9; i++){
if (temperature[i] > hotObject) {
hotObject = temperature[i]; // store the highest temperature
cluster = i; // store the location of the hottest spot
}
}
LCDposition(1, 1);
LcdSerial.print("Hot Object: ");
LcdSerial.print(hotObject, DEC);
LcdSerial.print(" ");
LCDposition(2, 1);
LcdSerial.print("in cluster ");
LcdSerial.print(cluster, DEC);
LcdSerial.print(" ");
}
void Play_Move(byte moveNumber) {
LCDposition(1, 1);
LcdSerial.print("Playing ");
LCDposition(2, 1);
LcdSerial.print("Move ");
LcdSerial.print(move, DEC);
LcdSerial.print(" ");
byte moveStart = EEPROM.read(490+(2*moveNumber));
byte moveEnd = EEPROM.read(491+(2*moveNumber));
for (byte i = moveStart; i <= moveEnd; i+=2){
sv = EEPROM.read(i);
pos = EEPROM.read(i+1);
switch (sv) {
case 0:
for (int u=1; u<=pos; u++){
StepDelay();
}
break;
case 1:
Waist.write(pos);
break;
case 2:
Lshoulder.write(pos);
break;
case 3:
Rshoulder.write(pos);
break;
case 4:
Larm.write(pos);
break;
case 5:
Rarm.write(pos);
break;
case 6:
Tilt.write(pos);
break;
case 7:
Pan.write(pos);
break;
}
}
}
void Play_Melody() {
digitalWrite(speakerOut, LOW);
for (count = 0; count < MAX_COUNT; count++) {
for (count3 = 0; count3 <= (melody[count*2] - 48) * 30; count3++) {
for (count2=0;count2<8;count2++) {
if (names[count2] == melody[count*2 + 1]) {
digitalWrite(speakerOut,HIGH);
delayMicroseconds(tones[count2]);
digitalWrite(speakerOut, LOW);
delayMicroseconds(tones[count2]);
}
if (melody[count*2 + 1] == 'p') {
// make a pause of a certain size
digitalWrite(speakerOut, 0);
delayMicroseconds(500);
}
}
}
}
}
void StepDelay() {
for (int t=0; t<=10; t++){
delay(20);
}
}
void LCDposition (byte line, byte column) {
LcdSerial.print(line, BYTE); // LCD line
LcdSerial.print(column, BYTE); // LCD column
}
void LCDclear () {
LcdSerial.print(5, BYTE); // select LCD command mode
LcdSerial.print(1, BYTE); // clear screen
}