Teste Codigo Automato Arduino
Teste Codigo Automato Arduino
Teste Codigo Automato Arduino
// Autonomous RC Car
//
//
// ARDUINO (UNO) SETUP:
// =======================
// Ping sensor = 5V, GRND, D11 (for both trigger & echo)
// LCD Display = I2C : SCL (A5) & SDA (A4)
// Adafruit GPS = D7 & D8 (GPS Shield, but pins used internally)
// IR Receiver = D5
// Adafruit Magnetometer Adafruit_HMC5883 = I2C : SCL (A5) & SDA (A4)
// SD Card (D10, D11, D12, D13)
//
// Create the motor shield object with the default I2C address
Adafruit_MotorShield AFMS = Adafruit_MotorShield();
// LCD Display
LiquidCrystal_I2C lcd(0x3F, 20, 4); // Set the LCD I2C address and size (4x20)
#define LEFT_ARROW 0x7F
#define RIGHT_ARROW 0x7E
#define DEGREE_SYMBOL 0xDF
//char lcd_buffer[20];
//PString message(lcd_buffer, sizeof(lcd_buffer)); // holds message we display
on line 4 of LCD
// Compass navigation
int targetHeading; // where we want to go to reach current waypoint
int currentHeading; // where we are actually facing now
int headingError; // signed (+/-) difference between targetHeading
and currentHeading
#define HEADING_TOLERANCE 5 // tolerance +/- (in degrees) within which we don't
attempt to turn to intercept targetHeading
// GPS Navigation
#define GPSECHO false // set to TRUE for GPS debugging if needed
//#define GPSECHO true // set to TRUE for GPS debugging if needed
SoftwareSerial mySerial(8, 7); // digital pins 7 & 8
Adafruit_GPS GPS(&mySerial);
boolean usingInterrupt = false;
float currentLat,
currentLong,
targetLat,
targetLong;
int distanceToTarget, // current distance to target (current waypoint)
originalDistanceToTarget; // distance to original waypoing when we started
navigating to it
// Waypoints
#define WAYPOINT_DIST_TOLERANE 5 // tolerance in meters to waypoint; once within
this tolerance, will advance to the next waypoint
#define NUMBER_WAYPOINTS 5 // enter the numebr of way points here (will
run from 0 to (n-1))
int waypointNumber = -1; // current waypoint number; will run from 0 to
(NUMBER_WAYPOINTS -1); start at -1 and gets initialized during setup()
waypointClass waypointList[NUMBER_WAYPOINTS] = {waypointClass(30.508302, -
97.832624), waypointClass(30.508085, -97.832494), waypointClass(30.507715, -
97.832357), waypointClass(30.508422, -97.832760), waypointClass(30.508518,-
97.832665) };
// Steering/turning
enum directions {left = TURN_LEFT, right = TURN_RIGHT, straight = TURN_STRAIGHT} ;
directions turnDirection = straight;
// IR Receiver
#ifdef USE_IR
#include "IRremote.h" // IR remote
#define IR_PIN 5
IRrecv IR_receiver(IR_PIN); // create instance of 'irrecv'
decode_results IR_results; // create instance of 'decode_results'
#endif
// IR result codes
#define IR_CODE_FORWARD 0x511DBB
#define IR_CODE_LEFT 0x52A3D41F
#define IR_CODE_OK 0xD7E84B1B
#define IR_CODE_RIGHT 0x20FE4DBB
#define IR_CODE_REVERSE 0xA3C8EDDB
#define IR_CODE_1 0xC101E57B
#define IR_CODE_2 0x97483BFB
#define IR_CODE_3 0xF0C41643
#define IR_CODE_4 0x9716BE3F
#define IR_CODE_5 0x3D9AE3F7
#define IR_CODE_6 0x6182021B
#define IR_CODE_7 0x8C22657B
#define IR_CODE_8 0x488F3CBB
#define IR_CODE_9 0x449E79F
#define IR_CODE_STAR 0x32C6FDF7
#define IR_CODE_0 0x1BC0157B
#define IR_CODE_HASHTAG 0x3EC3FC1B
//
// Interrupt is called once a millisecond, looks for any new GPS data, and stores
it
SIGNAL(TIMER0_COMPA_vect)
{
GPS.read();
}
//
// turn interrupt on and off
void useInterrupt(boolean v)
{
if (v) {
// Timer0 is already used for millis() - we'll just interrupt somewhere
// in the middle and call the "Compare A" function above
OCR0A = 0xAF;
TIMSK0 |= _BV(OCIE0A);
usingInterrupt = true;
} else {
// do not call the interrupt function COMPA anymore
TIMSK0 &= ~_BV(OCIE0A);
usingInterrupt = false;
}
}
void setup()
{
//
// Start LCD display
lcd.begin(); // start the LCD...new version doesn't require size
startup parameters
#ifdef USE_LCD_BACKLIGHT
lcd.backlight();
#else
lcd.noBacklight();
#endif
lcd.clear();
#ifdef USE_GRAPHING
createLCDChars(); // initialize LCD with graphing characters
#endif
//
// Start motor drives
AFMS.begin(); // create with the default frequency 1.6KHz
//
// start Mag / Compass
if(!compass.begin())
{
#ifdef DEBUG
Serial.println(F("COMPASS ERROR"));
#endif
lcd.print(F("COMPASS ERROR"));
loopForever(); // loop forever, can't operate without compass
}
//
// start GPS and set desired configuration
GPS.begin(9600); // 9600 NMEA default speed
GPS.sendCommand(PMTK_SET_NMEA_OUTPUT_RMCGGA); // turns on RMC and GGA (fix
data)
GPS.sendCommand(PMTK_SET_NMEA_UPDATE_1HZ); // 1 Hz update rate
GPS.sendCommand(PGCMD_NOANTENNA); // turn off antenna status info
useInterrupt(true); // use interrupt to constantly
pull data from GPS
delay(1000);
//
// Wait for GPS to get signal
#ifndef NO_GPS_WAIT
lcd.setCursor(0, 0);
lcd.print(F("Waiting for GPS"));
unsigned long startTime = millis();
while (!GPS.fix) // wait for fix, updating display with each
new NMEA sentence received
{
lcd.setCursor(0, 1);
lcd.print(F("Wait Time: "));
lcd.print((int) (millis() - startTime) / 1000); // show how long we have
waited
if (GPS.newNMEAreceived())
GPS.parse(GPS.lastNMEA());
} // while (!GPS.fix)
//delay(1000);
#endif
//
// Start the IR receiver
#ifdef USE_IR
IR_receiver.enableIRIn(); // Start the receiver
// Wait for operator to press key to start moving
lcd.setCursor(0, 3);
lcd.print(F("Press key to start"));
while(!IR_receiver.decode(&IR_results)) ; // wait for key press
IR_receiver.resume(); // get ready for any additional input
#else
// if not waiting for user input to start driving, at least give a countdown so
they are ready...
lcd.clear();
lcd.print(F("GPS Acquired"));
lcd.setCursor(0, 1);
lcd.print(F("Starting in..."));
lcd.setCursor(0, 2);
for (int i = 10; i > 0; i--)
{
lcd.print(i);
lcd.print(F(" "));
if (GPS.newNMEAreceived())
GPS.parse(GPS.lastNMEA());
delay(500);
}
#endif
//
// get initial waypoint; also sets the distanceToTarget and courseToTarget
varilables
nextWaypoint();
} // setup()
void loop()
{
// Process GPS
if (GPS.newNMEAreceived()) // check for updated GPS information
{
if(GPS.parse(GPS.lastNMEA()) ) // if we successfully parse it, update
our data fields
processGPS();
}
// navigate
currentHeading = readCompass(); // get our current heading
calcDesiredTurn(); // calculate how we would optimatally turn,
without regard to obstacles
} // loop()
//
// Called after new GPS data is received; updates our position and course/distance
to waypoint
void processGPS(void)
{
currentLat = convertDegMinToDecDeg(GPS.latitude);
currentLong = convertDegMinToDecDeg(GPS.longitude);
if (GPS.lat == 'S') // make them signed
currentLat = -currentLat;
if (GPS.lon = 'W')
currentLong = -currentLong;
// update the course and distance to waypoint based on our new position
distanceToWaypoint();
courseToWaypoint();
} // processGPS(void)
void checkSonar(void)
{
int dist;
int readCompass(void)
{
compass.getEvent(&compass_event);
float heading = atan2(compass_event.magnetic.y, compass_event.magnetic.x);
// Once you have your heading, you must then add your 'Declination Angle', which
is the 'Error' of the magnetic field in your location.
// Find yours here: http://www.magnetic-declination.com/
// Cedar Park, TX: Magnetic declination: 4° 11' EAST (POSITIVE); 1 degreee =
0.0174532925 radians
return ((int)headingDegrees);
} // readCompass()
void calcDesiredTurn(void)
{
// calculate where we need to turn to head to destination
headingError = targetHeading - currentHeading;
} // calcDesiredTurn()
void moveAndAvoid(void)
{
return;
}
} // moveAndAvoid()
void nextWaypoint(void)
{
waypointNumber++;
targetLat = waypointList[waypointNumber].getLat();
targetLong = waypointList[waypointNumber].getLong();
processGPS();
distanceToTarget = originalDistanceToTarget = distanceToWaypoint();
courseToWaypoint();
} // nextWaypoint()
return decDeg;
}
//
// Uses 4 line LCD display to show the following information:
// LINE 1: Target Heading; Current Heading;
// LINE 2: Heading Error; Distance to Waypoint;
// LINE 3: Sonar Distance; Speed;
// LINE 4: Memory Availalble; Waypoint X of Y;
void updateDisplay(void)
{
static unsigned long lastUpdate = millis(); // for controlling frequency of
LCD updates
unsigned long currentTime;
// line 1
lcd.clear();
lcd.print(F("tH= "));
lcd.print(targetHeading, DEC);
lcd.write(DEGREE_SYMBOL);
lcd.print(F(" cH= "));
lcd.print(currentHeading, DEC);
lcd.write(DEGREE_SYMBOL);
// line 2
lcd.setCursor(0, 1);
lcd.print(F("Err "));
if (headingError < 0)
lcd.write(LEFT_ARROW);
lcd.print(abs(headingError), DEC);
if (headingError > 0)
lcd.write(RIGHT_ARROW);
lcd.print(F(" Dist "));
lcd.print(distanceToTarget, DEC);
lcd.print(F("m "));
#ifdef USE_GRAPHING
lcd.write(map(distanceToTarget, 0, originalDistanceToTarget, 0, 7)); //
show tiny bar graph of distance remaining
#endif
// line 3
lcd.setCursor(0, 2);
lcd.print(F("Snr "));
lcd.print(sonarDistance, DEC);
#ifdef USE_GRAPHING
lcd.write(map(sonarDistance, 0, MAX_DISTANCE_IN, 0, 7));
#endif
lcd.print(F(" Spd "));
lcd.print(speed, DEC);
#ifdef USE_GRAPHING
lcd.write(map(speed, 0, 255, 0, 7));
#endif
// line 4
lcd.setCursor(0, 3);
lcd.print(F("Mem "));
lcd.print(freeRam(), DEC);
lcd.print(F(" WPT "));
lcd.print(waypointNumber + 1, DEC);
lcd.print(F(" OF "));
lcd.print(NUMBER_WAYPOINTS - 1, DEC);
#ifdef DEBUG
//Serial.print("GPS Fix:");
//Serial.println((int)GPS.fix);
Serial.print(F("LAT = "));
Serial.print(currentLat);
Serial.print(F(" LON = "));
Serial.println(currentLong);
//Serial.print("Waypint LAT =");
//Serial.print(waypointList[waypointNumber].getLat());
//Serial.print(F(" Long = "));
//Serial.print(waypointList[waypointNumber].getLong());
Serial.print(F(" Dist "));
Serial.print(distanceToWaypoint());
Serial.print(F("Original Dist "));
Serial.println(originalDistanceToTarget);
Serial.print(F("Compass Heading "));
Serial.println(currentHeading);
Serial.print(F("GPS Heading "));
Serial.println(GPS.angle);
//Serial.println(GPS.lastNMEA());
//Serial.print(F("Sonar = "));
//Serial.print(sonarDistance, DEC);
//Serial.print(F(" Spd = "));
//Serial.println(speed, DEC);
//Serial.print(F(" Target = "));
//Serial.print(targetHeading, DEC);
//Serial.print(F(" Current = "));
//Serial.print(currentHeading, DEC);
//Serial.print(F(" Error = "));
//Serial.println(headingError, DEC);
//Serial.print(F("Free Memory: "));
//Serial.println(freeRam(), DEC);
#endif
} // updateDisplay()
//
// Display free memory available
//#ifdef DEBUG
int freeRam () // display free memory (SRAM)
{
extern int __heap_start, *__brkval;
int v;
return (int) &v - (__brkval == 0 ? (int) &__heap_start : (int) __brkval);
} // freeRam()
//#endif
// end of program routine, loops forever
void loopForever(void)
{
while (1)
;
}
//
// Graphing (mini-inline bar graph for LCD display)
#ifdef USE_GRAPHING
void createLCDChars(void)
{
int lvl = 0;
byte arry[8];
for (int a = 7; a >= 0; a--)
{
for (int b = 0; b <= 7; b++)
{
if (b >= lvl)
arry[b] = B11111; // solid
else
//arry[b] = B00000; // blank row
arry[b] = B10001; // hollow but with sides
}
lcd.createChar(a, arry);
lvl++;
}
} // createLCDChars(void)
#endif
//
// Implement an IR "kill switch" if selected in configuration options
#ifdef USE_IR
void checkKillSwitch(void)
{
if(IR_receiver.decode(&IR_results)) // check for manual "kill switch"
{
turnMotor->run(RELEASE);
driveMotor->run(RELEASE);
lcd.clear();
lcd.print(F("Press to resume"));
delay(1000);
IR_receiver.resume();
while(!IR_receiver.decode(&IR_results)) ; // wait for key press
IR_receiver.resume(); // get ready for any additional input
}
} // checkKillSwitch()
#endif