Advertisement
Guest User

Team roadrunner AVC Code 2011

a guest
May 1st, 2011
768
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 10.71 KB | None | 0 0
  1. /* 2011 Sparkfun Autonomous Vehicle Competition Vehicle Code
  2. Author: Richard Burnside
  3. Verion: 1.0
  4. Last Update, 2:00PM: 4/23/2011
  5. */
  6.  
  7. //Included Libraries
  8. #include <Wire.h>
  9. #include <Servo.h>
  10. #include <math.h>
  11. #include <TinyGPS.h>
  12. #include <LiquidCrystal.h>
  13.  
  14. //Sensors & Servors
  15. #define RECEIVER_IN 13          //pin # for receiver IN
  16. #define STROBE 11               //pin # for Strobe
  17. #define SELECT 10               //pin # for Select
  18. #define SERVO 12                //pin # for steering servo
  19. #define THROTTLE 7              // pin # for throttle
  20. Servo steering;                 // steering servo setup and direction
  21. Servo speed;
  22. bool autonomous = false;        // true is ON, false is OFF
  23. bool race_start = true;     // creates a 3 second delay to start the vehicle
  24. unsigned long temp_time = 0;    // CHANGE THIS SINCE THE SD CARD IS NOT USED ANYMORE
  25.  
  26. //Compass
  27. #define XCLR 8                  // pin # for compass XCLR
  28. #define MCLCK 9                 // pin # for compass master clock
  29. #define C_ADDRESS B0110000      // compass address, [0110xx0] [xx] is determined by factory programming, total 4 different addresses are available
  30. #define COMP_X 2041             // compass center X
  31. #define COMP_Y 2040             // compass center Y
  32. double compass_heading = 0;
  33. double angle_diff;              // for the compass
  34.  
  35. //LCD Setup
  36. #define RS 22
  37. #define ENABLE_1 24
  38. #define ENABLE_2 23
  39. #define D4 25
  40. #define D5 26
  41. #define D6 27
  42. #define D7 28
  43. LiquidCrystal lcd1(RS, ENABLE_2, D4, D5, D6, D7);
  44. LiquidCrystal lcd2(RS, ENABLE_1, D4, D5, D6, D7);
  45. String dataString = "";
  46.  
  47. //GPS Initialization
  48. TinyGPS gps;
  49. float flat, flon;
  50. unsigned long age, date, time, chars;
  51. unsigned short sentences, failed;
  52. int gps_speed, max_speed = 0, course;
  53. double waypoint_distance, waypoint_heading = 0, lat_dist[5] = {0,0,0,0,0}, lon_dist[5] = {0,0,0,0,0};
  54.  
  55. /* GPS Waypoints */
  56. int waypoint_num = 0;
  57. int special_waypoint_num = 4; // ALWAYS 1 LESS 'cause arrays start at 0, not 1!
  58. const int waypoint_total = 15;  // <- should always be the same number of GPS waypoints
  59. // 0 = lat use, 1 = south lat use, 2 = north lat use
  60. double gps_array[15][3] = {{40.0651517950864528, -105.2097273131420, 0}, // 1st corner
  61. {40.0650036900410714, -105.2097272812302, 1}, // 1st line up point
  62. {40.0649066081190785, -105.2097109401257, 1}, // 2nd line up point or start of straight line
  63. {40.06485, -105.20975, 1}, // just added today
  64. {40.064528, -105.2097763511701, 1}, // lat point for start of turn
  65. {40.06448686920148, -105.20985212357533, 0}, // 2nd corner, just inside of south parking lot
  66. {40.06445080617122, -105.21016393037269, 0}, // bottom middle of south parking lot
  67. {40.06449104008855, -105.21041203470733, 0}, // inbetween sidewalks for 3rd corner
  68. {40.06450670940305, -105.2104463610966, 0}, // 3rd corner
  69. {40.06465758628262, -105.21046433778312, 2}, // line up for inbetween next bottleneck
  70. {40.06475817068338, -105.21046970220115, 2}, // past the bottleneck
  71. {40.06493060073908, -105.21048043103721, 2}, // middle of the 3rd side
  72. {40.06514305860027, -105.21048311324623, 2}, // end of 3rd side
  73. {40.06519745591719, -105.21041069360282, 0}, // 4th corner
  74. {40.06518985782108, -105.21001238556421, 0}}; // way past the finish line
  75.  
  76. void setup() {
  77.     //Set the car to manual mode
  78.     autonomous = false;
  79.     pinMode(RECEIVER_IN, INPUT);
  80.     pinMode(STROBE, OUTPUT);
  81.     pinMode(SELECT, OUTPUT);
  82.     digitalWrite(STROBE, LOW);
  83.     digitalWrite(SELECT, HIGH);
  84.  
  85.     steering.attach(SERVO);     //Servo Initialization
  86.     speed.attach(THROTTLE);     //Speed control initialization
  87.    
  88.     //Serial Output Initialization
  89.     Serial.begin(115200);
  90.     Serial.println("Time,IR Distance,Ultrasonic Distance, Gyro Heading, Lat, Lon, Date, Time, Course, Speed, Failed");
  91.     Serial1.begin(4800);        //GPS serial port initialization
  92.  
  93.     //Compass Module Initialization
  94.     pinMode(XCLR, OUTPUT);
  95.     digitalWrite(XCLR, LOW);
  96.     pinMode(MCLCK, OUTPUT);
  97.     digitalWrite(MCLCK, LOW);
  98.  
  99.     Wire.begin();
  100.     delay(20);                              //give some time (who's in a hurry?)
  101.     Wire.beginTransmission(C_ADDRESS);      //Send target (master)address
  102.     Wire.send(0x00);                        //Wake up call, send SET signal to set/reset coil
  103.     Wire.send(0x02);
  104.     Wire.endTransmission();                 //wait for SET action to settle
  105.     delay(10);
  106.    
  107.     //LCD Setup
  108.     lcd1.begin(40, 2);
  109.     lcd2.begin(40, 2);
  110.     lcd1.clear();
  111.     lcd2.clear();
  112.     lcd1.setCursor(0, 0); // top left
  113.     lcd1.print("THE ARDUINO AUTONOMOUS VEHICLE PROJECT");
  114.     lcd2.setCursor(0, 0); // top left
  115.     lcd2.print("DESIGNED BY RICHARD BURNSIDE, HIGHLANDS, CO");
  116.     delay(500);
  117.  
  118.     lcd1.clear();
  119.     lcd2.clear();
  120.     delay(500);
  121. }
  122.  
  123. void loop() {
  124.     //GPS data update
  125.     bool newdata = false;
  126.     if(feedgps())
  127.         newdata = true;
  128.     if(newdata)
  129.         gpsdump(gps);
  130.  
  131.     waypoint();
  132.     compass();
  133.     set_turn();
  134.     set_speed();
  135.  
  136.         if((millis() - temp_time) > 250) {
  137.         auto_control();                 // check for autonomous mode 4x / second
  138.         LCD_data_log();
  139. //      Serial_data_log();
  140.         temp_time = millis();
  141.     }
  142. }
  143.  
  144. /*----------Functions----------*/
  145. void set_speed(void) {  // test this and delete the delays after it works
  146.         if(waypoint_distance <= 20)     speed.write(112);
  147.         if(waypoint_distance > 20)      speed.write(150);
  148.     return;
  149. }
  150.  
  151. void waypoint(void) {               // Distance and angle to next waypoint
  152.     double x, y;
  153.  
  154.     x = 69.1*(gps_array[waypoint_num][1] - flon) * cos(flat/57.3);
  155.     y = 69.1*(gps_array[waypoint_num][0] - flat);
  156.    
  157.     waypoint_distance = sqrt(pow(x,2) + pow(y,2))*5280.0;   // converts distance to feet
  158.     waypoint_heading = atan2(y,x)*180.0/M_PI;               // 180/pi converts from rads to degrees
  159.     if(waypoint_heading < 0)    waypoint_heading += 360.0;
  160.  
  161.     if(waypoint_num == special_waypoint_num) waypoint_heading = 289.0;
  162.  
  163.     if((gps_array[waypoint_num][2] == 1) && (gps_array[waypoint_num][0] > flat)) waypoint_num++; // going south
  164.     else if((gps_array[waypoint_num][2] == 2) && (gps_array[waypoint_num][0] < flat)) waypoint_num++; // going north
  165.     else if(waypoint_distance < 10) waypoint_num++;
  166.  
  167.     while(waypoint_num >= waypoint_total) {     // shuts off the vehicle by disabling autonomous mode & MUXER & sets speed to 0
  168.         autonomous = false;
  169.         digitalWrite(STROBE, LOW);
  170.         digitalWrite(SELECT, LOW);
  171.         speed.write(90);
  172.     }
  173.  
  174.     return;
  175. }
  176.  
  177. void set_turn(void) {               // Set servo to steer in the direction of the next waypoint
  178. double servo_angle;
  179.  
  180.     angle_diff = compass_heading - waypoint_heading;
  181.  
  182.     if(angle_diff < -180)   angle_diff += 360.0;
  183.     if(angle_diff >= 180)   angle_diff -= 360.0;
  184.  
  185.     servo_angle = angle_diff/2.0 + 90.0;        //changes domain from -180...180 to 0...180
  186.     servo_angle = 180.0 - servo_angle;
  187.    
  188.     if(servo_angle > 130.0)     steering.write(130);
  189.     else if(servo_angle < 50.0) steering.write(50);
  190.     else                        steering.write(servo_angle);
  191.     return;
  192. }
  193.  
  194. void compass(void) {                // Determine compass heading with 0-deg matching standard graph
  195.     int xParam, yParam;
  196.     double x, y, northFi;
  197.  
  198.     byte rcvByte[4];
  199.     Wire.beginTransmission(C_ADDRESS);      //Send target (master)address
  200.     Wire.send(0x00);                        //Wake up call, request for data
  201.     Wire.send(0x01);
  202.     Wire.endTransmission();
  203.     delay(7);                               //wait 5ms min for compass to acquire data
  204.     Wire.requestFrom(C_ADDRESS, 4);
  205.  
  206.     for(int i=0; i < 4; i++) {
  207.         rcvByte[i] = 0;
  208.         rcvByte[i] = Wire.receive();
  209.     }
  210.  
  211.     xParam = rcvByte[0] << 8;
  212.     xParam = xParam | rcvByte[1];
  213.     yParam = rcvByte[2] << 8;
  214.     yParam = yParam | rcvByte[3];
  215.  
  216.     x = -(xParam - COMP_X);
  217.     y = (yParam - COMP_Y);
  218.     northFi = atan2(y,x);
  219.     compass_heading = (northFi * 180.0) / M_PI + 90.0 - 10.0; // 9 is to correct for magnetic north
  220.     if(compass_heading < 0) compass_heading += 360.0;
  221.  
  222.     return;
  223. }
  224.  
  225. void auto_control(void) {           // Autonomous Mode
  226.     int pulse_length;
  227.  
  228.     pulse_length = pulseIn(RECEIVER_IN, HIGH, 50000);
  229.  
  230.     Serial.println(pulse_length);
  231.     if(pulse_length < 500) {
  232.         if(race_start) {
  233.             delay(250);
  234.             race_start = false;
  235.         }
  236.        
  237.         autonomous = true;
  238.         digitalWrite(STROBE, LOW);
  239.         digitalWrite(SELECT, LOW);
  240.     }
  241.     else {
  242.         autonomous = false;
  243.         digitalWrite(STROBE, LOW);
  244.         digitalWrite(SELECT, HIGH);
  245.     }
  246.  
  247.     return;
  248. }
  249.  
  250. bool feedgps() {                    // GPS Data Input
  251.     while(Serial1.available()) {
  252.         if(gps.encode(Serial1.read()))
  253.             return true;
  254.     }
  255.     return false;
  256. }
  257.  
  258. void gpsdump(TinyGPS &gps) {        // GPS Calculation
  259.     gps.f_get_position(&flat, &flon, &age);
  260.     gps.get_datetime(&date, &time, &age);
  261.     gps.stats(&chars, &sentences, &failed); //should be removed later...just a waste of time
  262.     gps_speed = gps.f_speed_mph();  //not needed also
  263.     if(gps_speed > max_speed) max_speed = gps_speed;
  264.     course = gps.course();  //could be useful once i figure out what it does
  265.  
  266.     return;
  267. }
  268.  
  269. void Serial_data_log() {            // Serial Data Logging
  270.     //String() will not handle float/doubles...this will convert these to arrays
  271.     long latitude, longitude, wp_distance, wp_heading, latitude_array, longitude_array;
  272.     latitude = flat*1000000;
  273.     longitude = flon*1000000;
  274.     latitude_array = gps_array[waypoint_num][0]*1000000;
  275.     longitude_array = gps_array[waypoint_num][1]*1000000;
  276.     wp_distance = waypoint_distance;
  277.     wp_heading = waypoint_heading;
  278.     long angle_string;
  279.  
  280.     //String creation
  281.     dataString += String(millis());
  282.     dataString += ","; dataString += String(time);
  283.     dataString += ","; dataString += String(gps_speed);
  284.     dataString += ","; dataString += String(angle);
  285.     dataString += ","; dataString += String(angle_string);
  286.     dataString += ","; dataString += String(latitude);
  287.     dataString += ","; dataString += String(longitude);
  288.     dataString += ","; dataString += String(latitude_array);
  289.     dataString += ","; dataString += String(longitude_array);  
  290.     dataString += ","; dataString += String(wp_distance);
  291.     dataString += ","; dataString += String(wp_heading);
  292.     dataString += ","; dataString += String(failed);
  293.  
  294.     if(autonomous)
  295.         dataString += ",Auto";
  296.     else
  297.         dataString += ",Manual";
  298.  
  299.     Serial.println(compass_heading,1);
  300.     Serial.println(waypoint_heading,1);
  301. //  servo_angle is not a global variable Serial.println(servo_angle,1);
  302.     Serial.println(angle_diff,1);
  303.  
  304.     //Serial printing of string
  305.     Serial.println(dataString);
  306.     dataString = "";                //resets the datastring to 0
  307.    
  308.     return;
  309. }
  310.  
  311. void LCD_data_log() {               // LCD Data Logging
  312.     lcd1.clear();
  313.     lcd1.setCursor(0,0);    lcd1.print("Lt/Ln: "); lcd1.print(flat,6); lcd1.print(" "); lcd1.print(flon,6);
  314.     lcd1.setCursor(29,0);   lcd1.print("Dft: "); lcd1.print(waypoint_distance,1);
  315.     lcd1.setCursor(0,1);    lcd1.print("NWP:   "); lcd1.print(gps_array[waypoint_num][0],6); lcd1.print(" "); lcd1.print(gps_array[waypoint_num][1],6);
  316.     lcd1.setCursor(29,1);   lcd1.print("Spd: "); lcd1.print(max_speed);
  317.     lcd1.setCursor(36,1);   lcd1.print("M: "); lcd1.print(autonomous);
  318.  
  319.     lcd2.clear();
  320.     lcd2.setCursor(20,0);   lcd2.print("Tm: "); lcd2.print(millis()/1000);
  321.     lcd2.setCursor(0,1);    lcd2.print("CM: "); lcd2.print(compass_heading,1);
  322.     lcd2.setCursor(10,1);   lcd2.print("Hdng: "); lcd2.print(waypoint_heading,1);
  323.     lcd2.setCursor(22,1);   lcd2.print("Diff: "); lcd2.print(angle_diff,1);
  324.     lcd2.setCursor(33,1);   lcd2.print("WP: "); lcd2.print(waypoint_num);
  325.  
  326. return;
  327. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement