#include "pitches.h"const int BUTTON_PIN = 12;const int PIEZO_PIN = 8;const int OB_LED_PIN = 13;const int PING_PIN = 10;const int CLOSEST_DISTANCE = 4;const int LPINP = 47; // left motor speedconst int LPIN1 = 5;const int LPIN2 = 4;const int RPINP = 37; // right motor speedconst int RPIN1 = 3;const int RPIN2 = 2;const byte ENGINE_STOP = 0;const byte ENGINE_FORWARD = 1;const byte ENGINE_BACK = 2;const byte ENGINE_TLEFT = 3;const byte ENGINE_TRIGHT = 4;const byte DIRECTION_NONE = 0;const byte DIRECTION_LEFT = 1;const byte DIRECTION_RIGHT = 2;const int LOT_TO_TURN = 45; // this can be removed once we get a compassconst int SPEED_STOP = LOW;const int SPEED_LOW = 80;const int SPEED_MEDIUM = 160;const int SPEED_HIGH = HIGH;int buttonState = 0;int currentDistance = 0;int speedToUse = SPEED_STOP;boolean startBot = false;boolean sentCommand = false;byte engineOrders = ENGINE_STOP;byte checkForDirection = DIRECTION_NONE;int turnTime;int leftDistance;int rightDistance;void setup() { Serial.begin(9600); onSound(); // signal that we're turning on pinMode(LPIN1, OUTPUT); pinMode(LPIN2, OUTPUT); pinMode(LPINP, OUTPUT); pinMode(RPIN1, OUTPUT); pinMode(RPIN2, OUTPUT); pinMode(RPINP, OUTPUT); pinMode(BUTTON_PIN, INPUT); pinMode(OB_LED_PIN, OUTPUT); digitalWrite(OB_LED_PIN, LOW); }void loop() { handleButton(); if (startBot) { currentDistance = getDistanceInInches(); // get the current distance from the ping sensor if (currentDistance > CLOSEST_DISTANCE) // if there's nothing in the way, go forward { setEngineCommand(ENGINE_FORWARD); } else { // something in the way (- kurt cobain) if (engineOrders != ENGINE_STOP) { tone(PIEZO_PIN, NOTE_G1, 1000); // beep to let us know that there's something in front of the bot digitalWrite(OB_LED_PIN, LOW); } setEngineCommand(ENGINE_STOP); // stop the tank checkForDirection = DIRECTION_LEFT; // rotate left so we can see if there's nothing to the left of us turnTime = LOT_TO_TURN; } if (checkForDirection != DIRECTION_NONE) // should we rotate? { if (checkForDirection == DIRECTION_LEFT) { if (turnTime > 0) { turnTime = turnTime - 1; setEngineCommand(ENGINE_TLEFT); // turn left } else { leftDistance = getDistanceInInches(); // we are facing the left, so get a reading from the ping delay(50); checkForDirection = DIRECTION_RIGHT; // now go to the right side turnTime = LOT_TO_TURN * 2; } } else { // right side if (turnTime > 0) { turnTime = turnTime - 1; setEngineCommand(ENGINE_TRIGHT); // turn right } else { rightDistance = getDistanceInInches(); // we are facing right of the original position, so get a reading from the ping delay(50); if (leftDistance > rightDistance) // do we have more space on the left side? { setEngineCommand(ENGINE_TLEFT); // go back to the left side turnTime = LOT_TO_TURN * 2; } else { setEngineCommand(ENGINE_FORWARD); // right side has more space, so just go forward since we're already facing right } checkForDirection = DIRECTION_NONE; // no longer need to check for direction } } } } else { setEngineCommand(ENGINE_STOP); // all systems stop } //speedToUse = analogRead(POT_PIN); speedToUse = SPEED_HIGH; if (!sentCommand) { switch (engineOrders) { case ENGINE_FORWARD: analogWrite(LPINP, speedToUse); analogWrite(RPINP, speedToUse); digitalWrite(LPIN1, HIGH); digitalWrite(LPIN2, LOW); digitalWrite(RPIN1, HIGH); digitalWrite(RPIN2, LOW); break; case ENGINE_BACK: analogWrite(LPINP, speedToUse); analogWrite(RPINP, speedToUse); digitalWrite(LPIN1, LOW); digitalWrite(LPIN2, HIGH); digitalWrite(RPIN1, LOW); digitalWrite(RPIN2, HIGH); break; case ENGINE_STOP: analogWrite(LPINP, SPEED_STOP); analogWrite(RPINP, SPEED_STOP); digitalWrite(LPIN1, LOW); digitalWrite(LPIN2, LOW); digitalWrite(RPIN1, LOW); digitalWrite(RPIN2, LOW); break; case ENGINE_TLEFT: analogWrite(LPINP, speedToUse); analogWrite(RPINP, speedToUse); digitalWrite(LPIN1, HIGH); digitalWrite(LPIN2, LOW); digitalWrite(RPIN1, LOW); digitalWrite(RPIN2, HIGH); if (turnTime > 0) { turnTime = turnTime - 1; } else { setEngineCommand(ENGINE_FORWARD); } break; case ENGINE_TRIGHT: analogWrite(LPINP, speedToUse); analogWrite(RPINP, speedToUse); digitalWrite(LPIN1, LOW); digitalWrite(LPIN2, HIGH); digitalWrite(RPIN1, HIGH); digitalWrite(RPIN2, LOW); if (turnTime > 0) { turnTime = turnTime - 1; } else { setEngineCommand(ENGINE_FORWARD); } break; } sentCommand = true; } delay(100);}void setEngineCommand(int command){ if (engineOrders != command) // we only want to send the orders when they change { engineOrders = command; sentCommand = false; }}void handleButton(){ buttonState = digitalRead(BUTTON_PIN); if (buttonState == HIGH) { while (buttonState == HIGH) { buttonState = digitalRead(BUTTON_PIN); } startBot = !startBot; if (startBot) { digitalWrite(OB_LED_PIN, HIGH); tone(PIEZO_PIN, NOTE_C4, 250); delay(250); tone(PIEZO_PIN, NOTE_B4, 250); delay(250); tone(PIEZO_PIN, NOTE_A4, 250); delay(250); tone(PIEZO_PIN, NOTE_A5, 250); delay(250); } else { tone(PIEZO_PIN, NOTE_G3, 1000); digitalWrite(OB_LED_PIN, LOW); } } }int getDistanceInInches(){ return microsecondsToInches(getDistance());}int getDistance(){ pinMode(PING_PIN, OUTPUT); digitalWrite(PING_PIN, LOW); delayMicroseconds(2); digitalWrite(PING_PIN, HIGH); delayMicroseconds(5); digitalWrite(PING_PIN, LOW); // The same pin is used to read the signal from the PING))): a HIGH // pulse whose duration is the time (in microseconds) from the sending // of the ping to the reception of its echo off of an object. pinMode(PING_PIN, INPUT); return pulseIn(PING_PIN, HIGH);}int microsecondsToInches(int microseconds){ // According to Parallax's datasheet for the PING))), there are // 73.746 microseconds per inch (i.e. sound travels at 1130 feet per // second). This gives the distance travelled by the ping, outbound // and return, so we divide by 2 to get the distance of the obstacle. // See: http://www.parallax.com/dl/docs/prod/acc/28015-PING-v1.3.pdf return microseconds / 74 / 2;}void onSound(){ tone(PIEZO_PIN, NOTE_C4, 250); delay(250); tone(PIEZO_PIN, NOTE_C4, 250); delay(250); tone(PIEZO_PIN, NOTE_C4, 250); delay(250);}