Guides the user to their classes

Dependencies:   4DGL-uLCD-SE Course SDFileSystem mbed PinDetect LSM9DS1_Library_cal MBed_Adafruit-GPS-Library

Committer:
nkela6
Date:
Fri Dec 09 00:39:19 2016 +0000
Revision:
17:1de531cd3d4a
Parent:
16:4b4e6cf66e7c
Final commit after fixing timer errors (Still limited to 1 snooze call)

Who changed what in which revision?

UserRevisionLine numberNew contents of line
kkizirian 0:ce60014510e5 1 // Class Scheduler
kkizirian 0:ce60014510e5 2 #include "mbed.h"
kkizirian 0:ce60014510e5 3 #include "uLCD_4DGL.h"
kkizirian 0:ce60014510e5 4 #include <string>
kkizirian 0:ce60014510e5 5 #include <vector>
kkizirian 0:ce60014510e5 6 #include "Course.h"
kkizirian 0:ce60014510e5 7 #include "SDFileSystem.h"
kkizirian 5:430f44669f94 8 #include "MBed_Adafruit_GPS.h"
kkizirian 3:0ca91f8afec5 9 #include "LSM9DS1.h"
kkizirian 2:c708e2027970 10 #include "PinDetect.h"
kkizirian 3:0ca91f8afec5 11 #define PI 3.14159
kkizirian 3:0ca91f8afec5 12 #define DECLINATION -4.94 // Declination (degrees) in Atlanta,GA.
kkizirian 0:ce60014510e5 13
kkizirian 0:ce60014510e5 14 SDFileSystem sd(p5, p6, p7, p8, "sd"); // the pinout on the mbed Cool Components workshop board
kkizirian 0:ce60014510e5 15 Serial pc(USBTX, USBRX);
kkizirian 3:0ca91f8afec5 16 uLCD_4DGL uLCD(p13,p14,p15); // serial tx, serial rx, reset pin;
kkizirian 3:0ca91f8afec5 17 PinDetect left(p20);
kkizirian 3:0ca91f8afec5 18 PinDetect right(p18);
nkela6 16:4b4e6cf66e7c 19 PinDetect center(p19);
kkizirian 5:430f44669f94 20 Serial * gps_Serial;
kkizirian 0:ce60014510e5 21
kkizirian 0:ce60014510e5 22 int update;
kkizirian 0:ce60014510e5 23 vector<Course> courseVec;
kkizirian 4:93a4b415fe6c 24 void readClassFile(vector<Course>& cVec);
kkizirian 5:430f44669f94 25 int getNextClass(vector<Course>& cVec);
kkizirian 2:c708e2027970 26 void displayCourseVec();
kkizirian 3:0ca91f8afec5 27 float calculateHeading(float mx, float my), computeAngleToDestination(float diffLat, float diffLong);
kkizirian 9:5b871fb9f554 28 float longToDecimal(float longitudeInDDMM, char eastOrWest), latToDecimal(float latitudeInDDMM, char northOrSouth);
kkizirian 4:93a4b415fe6c 29 int xEnd, yEnd = 0.0;
kkizirian 5:430f44669f94 30 int currHour, currMinute, currSecond = 0;
kkizirian 5:430f44669f94 31 int hoursToNextClass, minutesToNextClass, secondsToNextClass = 0;
kkizirian 5:430f44669f94 32 int nextClass = 0;
kkizirian 5:430f44669f94 33 int currClass = -1;
kkizirian 5:430f44669f94 34 const int refresh_Time = 1000; //refresh time in ms
kkizirian 3:0ca91f8afec5 35 bool screen_refreshed = false;
kkizirian 2:c708e2027970 36 int volatile current_screen = 0;
kkizirian 2:c708e2027970 37 bool volatile screen_change = false;
kkizirian 5:430f44669f94 38 void timeToNextClass();
nkela6 13:0eb9fbd63fb2 39 float displacement(float diffLat,float diffLong);
nkela6 13:0eb9fbd63fb2 40 float calc_eta(float displacement, float speed);
nkela6 13:0eb9fbd63fb2 41 bool late(float eta);
nkela6 17:1de531cd3d4a 42 Timer t2;
nkela6 17:1de531cd3d4a 43
nkela6 17:1de531cd3d4a 44 bool volatile snooze = 0;
nkela6 16:4b4e6cf66e7c 45
nkela6 17:1de531cd3d4a 46 void center_callback(void)
nkela6 17:1de531cd3d4a 47 {
nkela6 17:1de531cd3d4a 48 snooze=1;
nkela6 17:1de531cd3d4a 49 }
kkizirian 0:ce60014510e5 50
kkizirian 2:c708e2027970 51 void left_callback(void)
kkizirian 2:c708e2027970 52 {
kkizirian 3:0ca91f8afec5 53 if (courseVec.size() != 0) {
kkizirian 3:0ca91f8afec5 54 current_screen = (3 + current_screen - 1)%3;
kkizirian 3:0ca91f8afec5 55 screen_change = true;
kkizirian 3:0ca91f8afec5 56 } else
kkizirian 3:0ca91f8afec5 57 current_screen = 0;
kkizirian 5:430f44669f94 58 currClass = -1;
kkizirian 5:430f44669f94 59 uLCD.cls();
kkizirian 2:c708e2027970 60 }
kkizirian 2:c708e2027970 61
kkizirian 2:c708e2027970 62 void right_callback(void)
kkizirian 2:c708e2027970 63 {
kkizirian 3:0ca91f8afec5 64 if (courseVec.size() != 0) {
kkizirian 3:0ca91f8afec5 65 current_screen = (3 + current_screen + 1)%3;
kkizirian 3:0ca91f8afec5 66 screen_change = true;
kkizirian 3:0ca91f8afec5 67 } else
kkizirian 3:0ca91f8afec5 68 current_screen = 0;
kkizirian 5:430f44669f94 69 currClass = -1;
kkizirian 5:430f44669f94 70 uLCD.cls();
kkizirian 2:c708e2027970 71 }
kkizirian 2:c708e2027970 72
kkizirian 0:ce60014510e5 73 int main()
kkizirian 0:ce60014510e5 74 {
kkizirian 3:0ca91f8afec5 75 LSM9DS1 IMU(p9, p10, 0xD6, 0x3C);
kkizirian 3:0ca91f8afec5 76 float h = 0.0;
kkizirian 3:0ca91f8afec5 77 float angleToDest = 0.0;
kkizirian 3:0ca91f8afec5 78 IMU.begin();
kkizirian 3:0ca91f8afec5 79 if (!IMU.begin()) {
kkizirian 3:0ca91f8afec5 80 pc.printf("Failed to communicate with LSM9DS1.\n");
kkizirian 3:0ca91f8afec5 81 }
kkizirian 3:0ca91f8afec5 82 uLCD.cls();
kkizirian 3:0ca91f8afec5 83 uLCD.printf("Place IMU flat");
kkizirian 3:0ca91f8afec5 84 IMU.calibrate(1);
kkizirian 3:0ca91f8afec5 85 uLCD.cls();
kkizirian 3:0ca91f8afec5 86 uLCD.printf("Rotate IMU 360\ndegrees in \nhorizontal plane");
kkizirian 3:0ca91f8afec5 87 IMU.calibrateMag(0);
kkizirian 3:0ca91f8afec5 88
kkizirian 2:c708e2027970 89 left.mode(PullUp);
kkizirian 2:c708e2027970 90 right.mode(PullUp);
nkela6 17:1de531cd3d4a 91 center.mode(PullUp);
kkizirian 2:c708e2027970 92 left.attach_deasserted(&left_callback);
kkizirian 2:c708e2027970 93 right.attach_deasserted(&right_callback);
nkela6 17:1de531cd3d4a 94 center.attach_deasserted(&center_callback);
kkizirian 2:c708e2027970 95 left.setSampleFrequency();
kkizirian 2:c708e2027970 96 right.setSampleFrequency();
nkela6 17:1de531cd3d4a 97 center.setSampleFrequency();
kkizirian 0:ce60014510e5 98 readClassFile(courseVec);
kkizirian 5:430f44669f94 99
kkizirian 5:430f44669f94 100 gps_Serial = new Serial(p28,p27); //serial object for use w/ GPS
kkizirian 5:430f44669f94 101 Adafruit_GPS myGPS(gps_Serial); //object of Adafruit's GPS class
kkizirian 5:430f44669f94 102 char c; //when read via Adafruit_GPS::read(), the class returns single character stored here
kkizirian 5:430f44669f94 103 Timer refresh_Timer; //sets up a timer for use in loop; how often do we print GPS info?
kkizirian 5:430f44669f94 104 const int refresh_Time = 2000; //refresh time in ms
kkizirian 5:430f44669f94 105
kkizirian 5:430f44669f94 106 myGPS.begin(9600); //sets baud rate for GPS communication; note this may be changed via Adafruit_GPS::sendCommand(char *)
kkizirian 5:430f44669f94 107 //a list of GPS commands is available at http://www.adafruit.com/datasheets/PMTK_A08.pdf
kkizirian 5:430f44669f94 108
kkizirian 5:430f44669f94 109 myGPS.sendCommand(PMTK_SET_NMEA_OUTPUT_RMCGGA); //these commands are defined in MBed_Adafruit_GPS.h; a link is provided there for command creation
kkizirian 5:430f44669f94 110 myGPS.sendCommand(PMTK_SET_NMEA_UPDATE_1HZ);
kkizirian 5:430f44669f94 111 myGPS.sendCommand(PGCMD_ANTENNA);
kkizirian 5:430f44669f94 112
kkizirian 4:93a4b415fe6c 113 float myLat = 33.775991;
kkizirian 4:93a4b415fe6c 114 float myLong = -84.397128;
kkizirian 2:c708e2027970 115
kkizirian 5:430f44669f94 116 float destinationLat = courseVec[1].getLat();
kkizirian 5:430f44669f94 117 float destinationLong = courseVec[1].getLong();
kkizirian 5:430f44669f94 118
kkizirian 4:93a4b415fe6c 119 screen_change = true;
kkizirian 0:ce60014510e5 120 pc.baud(9600);
kkizirian 5:430f44669f94 121 c = myGPS.read(); //queries the GPS
kkizirian 5:430f44669f94 122 currHour = myGPS.hour - 5; //for eastern time zone
kkizirian 5:430f44669f94 123 if (currHour < 0)
kkizirian 5:430f44669f94 124 currHour += 24;
kkizirian 5:430f44669f94 125 currMinute = myGPS.minute;
kkizirian 5:430f44669f94 126 currSecond = myGPS.seconds;
kkizirian 5:430f44669f94 127 nextClass = getNextClass(courseVec);
kkizirian 2:c708e2027970 128
kkizirian 5:430f44669f94 129 refresh_Timer.start(); //starts the clock on the timer
kkizirian 0:ce60014510e5 130 while(1) {
kkizirian 5:430f44669f94 131 c = myGPS.read(); //queries the GPS
kkizirian 5:430f44669f94 132
kkizirian 5:430f44669f94 133 //if (c) { pc.printf("%c", c); } //this line will echo the GPS data if not paused
kkizirian 5:430f44669f94 134
kkizirian 5:430f44669f94 135 //check if we recieved a new message from GPS, if so, attempt to parse it,
kkizirian 5:430f44669f94 136 if ( myGPS.newNMEAreceived() ) {
kkizirian 5:430f44669f94 137 if ( !myGPS.parse(myGPS.lastNMEA()) ) {
kkizirian 5:430f44669f94 138 continue;
kkizirian 5:430f44669f94 139 }
kkizirian 5:430f44669f94 140 }
kkizirian 5:430f44669f94 141
kkizirian 5:430f44669f94 142 if (refresh_Timer.read_ms() >= refresh_Time) {
kkizirian 5:430f44669f94 143 refresh_Timer.reset();
kkizirian 6:ceb6a5426add 144 if (myGPS.fix) {
kkizirian 9:5b871fb9f554 145 myLat = latToDecimal(myGPS.latitude, myGPS.lat);
kkizirian 9:5b871fb9f554 146 myLong = longToDecimal(myGPS.longitude, myGPS.lon);
kkizirian 6:ceb6a5426add 147 }
kkizirian 9:5b871fb9f554 148
kkizirian 5:430f44669f94 149 currHour = myGPS.hour - 5; //for eastern time zone
kkizirian 5:430f44669f94 150 if (currHour < 0)
kkizirian 5:430f44669f94 151 currHour += 24;
kkizirian 5:430f44669f94 152 currMinute = myGPS.minute;
kkizirian 5:430f44669f94 153 currSecond = myGPS.seconds;
kkizirian 5:430f44669f94 154 nextClass = getNextClass(courseVec);
kkizirian 5:430f44669f94 155 timeToNextClass();
nkela6 13:0eb9fbd63fb2 156 destinationLat = courseVec[nextClass].getLat();
nkela6 13:0eb9fbd63fb2 157 destinationLong = courseVec[nextClass].getLong();
nkela6 13:0eb9fbd63fb2 158 float diffLat = destinationLat - myLat;
nkela6 13:0eb9fbd63fb2 159 float diffLong = destinationLong - myLong;
nkela6 13:0eb9fbd63fb2 160 float dis = displacement(diffLat,diffLong);
nkela6 13:0eb9fbd63fb2 161 float speed = 3.1; //mph. Source:https://lmgtfy.com/?q=average+human+walking+speed
nkela6 13:0eb9fbd63fb2 162 float eta = calc_eta(dis,speed)*60;//(miles, mph)*60
nkela6 16:4b4e6cf66e7c 163 if((late(eta)==1)&&(snooze==0)) {
nkela6 14:d8a6134cafa3 164 uLCD.background_color(RED);
nkela6 16:4b4e6cf66e7c 165 uLCD.textbackground_color(RED);
nkela6 17:1de531cd3d4a 166 } else if((late(eta)==1)&&(snooze==1)) {
nkela6 16:4b4e6cf66e7c 167 t2.start();
nkela6 17:1de531cd3d4a 168 if(t2.read()<120) { //2 minute snooze
nkela6 16:4b4e6cf66e7c 169 uLCD.background_color(BLACK);
nkela6 16:4b4e6cf66e7c 170 uLCD.textbackground_color(BLACK);
nkela6 17:1de531cd3d4a 171 } else {
nkela6 17:1de531cd3d4a 172 t2.stop();
nkela6 17:1de531cd3d4a 173 snooze = 0;
nkela6 16:4b4e6cf66e7c 174 }
nkela6 17:1de531cd3d4a 175 } else {
nkela6 14:d8a6134cafa3 176 uLCD.background_color(BLACK);
nkela6 16:4b4e6cf66e7c 177 uLCD.textbackground_color(BLACK);
nkela6 13:0eb9fbd63fb2 178 }
kkizirian 5:430f44669f94 179
kkizirian 5:430f44669f94 180 switch(current_screen) {
kkizirian 5:430f44669f94 181 case 0:
kkizirian 5:430f44669f94 182 wait(.2);
kkizirian 5:430f44669f94 183 if (screen_change) {
kkizirian 5:430f44669f94 184 displayCourseVec();
kkizirian 5:430f44669f94 185 screen_change = false;
kkizirian 5:430f44669f94 186 }
kkizirian 5:430f44669f94 187 break;
kkizirian 5:430f44669f94 188 case 1:
kkizirian 5:430f44669f94 189 IMU.readMag();
kkizirian 5:430f44669f94 190 h = calculateHeading(IMU.calcMag(IMU.mx), IMU.calcMag(IMU.my));
kkizirian 5:430f44669f94 191 pc.printf("Heading: %f\n", h);
kkizirian 5:430f44669f94 192 angleToDest = computeAngleToDestination(diffLat, diffLong);
kkizirian 5:430f44669f94 193 h = angleToDest - h;
kkizirian 3:0ca91f8afec5 194 h = h - 90;
kkizirian 5:430f44669f94 195 if (h < 0)
kkizirian 5:430f44669f94 196 h = h + 360;
kkizirian 5:430f44669f94 197 if (h > 360)
kkizirian 5:430f44669f94 198 h = h - 360;
kkizirian 5:430f44669f94 199 xEnd = 0;
kkizirian 5:430f44669f94 200 yEnd = 0;
kkizirian 5:430f44669f94 201 float rads = 0.0;
kkizirian 5:430f44669f94 202 //uLCD.cls();
kkizirian 5:430f44669f94 203 if (h < 90) {
kkizirian 5:430f44669f94 204 rads = h * PI / 180;
kkizirian 5:430f44669f94 205 xEnd = floor(63 * sin(rads) + .5);
kkizirian 5:430f44669f94 206 yEnd = floor(63 * cos(rads) + .5);
kkizirian 5:430f44669f94 207 xEnd = 63 + xEnd;
kkizirian 5:430f44669f94 208 yEnd = 63 + yEnd;
kkizirian 5:430f44669f94 209 } else if (90 < h < 180) {
kkizirian 5:430f44669f94 210 h = h - 90;
kkizirian 5:430f44669f94 211 rads = h * PI / 180;
kkizirian 5:430f44669f94 212 xEnd = floor(63 * cos(rads) + .5);
kkizirian 5:430f44669f94 213 yEnd = floor(63 * sin(rads) + .5);
kkizirian 5:430f44669f94 214 xEnd = 63 + xEnd;
kkizirian 5:430f44669f94 215 yEnd = 63 - yEnd;
kkizirian 5:430f44669f94 216 } else if (180 < h < 270) {
kkizirian 5:430f44669f94 217 h = h - 180;
kkizirian 5:430f44669f94 218 rads = h * PI / 180;
kkizirian 5:430f44669f94 219 xEnd = floor(63 * sin(rads) + .5);
kkizirian 5:430f44669f94 220 yEnd = floor(63 * cos(rads) + .5);
kkizirian 5:430f44669f94 221 xEnd = 63 - xEnd;
kkizirian 5:430f44669f94 222 yEnd = 63 - yEnd;
kkizirian 5:430f44669f94 223 } else if (270 < h) {
kkizirian 5:430f44669f94 224 h = h - 270;
kkizirian 5:430f44669f94 225 rads = h * PI / 180;
kkizirian 5:430f44669f94 226 xEnd = floor(63 * cos(rads) + .5);
kkizirian 5:430f44669f94 227 yEnd = floor(63 * sin(rads) + .5);
kkizirian 5:430f44669f94 228 xEnd = 63 - xEnd;
kkizirian 5:430f44669f94 229 yEnd = 63 + yEnd;
kkizirian 5:430f44669f94 230 }
kkizirian 2:c708e2027970 231 uLCD.cls();
kkizirian 5:430f44669f94 232 uLCD.line(63, 63, xEnd, yEnd, WHITE);
kkizirian 5:430f44669f94 233 break;
kkizirian 5:430f44669f94 234 case 2:
kkizirian 5:430f44669f94 235 //uLCD.cls();
nkela6 16:4b4e6cf66e7c 236 //uLCD.text_mode(TRANSPARENT);
kkizirian 7:e4d667beaf33 237 uLCD.locate(0,2);
kkizirian 8:3266cc9eda81 238 uLCD.printf(" ");
kkizirian 6:ceb6a5426add 239 uLCD.locate(0,3);
kkizirian 5:430f44669f94 240 uLCD.printf("Time to next class");
kkizirian 6:ceb6a5426add 241 uLCD.locate(0, 4);
kkizirian 5:430f44669f94 242 uLCD.printf("%02dhrs %02dminutes", hoursToNextClass, minutesToNextClass);
kkizirian 6:ceb6a5426add 243 uLCD.locate(0, 5);
kkizirian 5:430f44669f94 244 uLCD.printf("%02dseconds", secondsToNextClass);
nkela6 15:75a121b14e5d 245 uLCD.locate(0,7);
nkela6 15:75a121b14e5d 246 uLCD.printf("ETA: (min)");
nkela6 15:75a121b14e5d 247 uLCD.locate(0,8);
nkela6 15:75a121b14e5d 248 uLCD.printf("%f",eta);
nkela6 15:75a121b14e5d 249 uLCD.locate(0,10);
nkela6 15:75a121b14e5d 250 uLCD.printf("Displacement:");
nkela6 15:75a121b14e5d 251 uLCD.locate(0,11);
nkela6 15:75a121b14e5d 252 uLCD.printf("%f",dis);
kkizirian 6:ceb6a5426add 253 uLCD.locate(0, 0);
kkizirian 7:e4d667beaf33 254 uLCD.printf("Next class ");
kkizirian 5:430f44669f94 255 if (nextClass != currClass) {
kkizirian 6:ceb6a5426add 256 uLCD.locate(0, 1);
kkizirian 5:430f44669f94 257 uLCD.printf(" ");
kkizirian 6:ceb6a5426add 258 uLCD.locate(0, 1);
kkizirian 5:430f44669f94 259 uLCD.printf("%s", courseVec[nextClass].getDisplayString());
kkizirian 5:430f44669f94 260 }
kkizirian 5:430f44669f94 261 currClass = nextClass;
kkizirian 5:430f44669f94 262 break;
kkizirian 5:430f44669f94 263 }
kkizirian 0:ce60014510e5 264 }
kkizirian 0:ce60014510e5 265 }
kkizirian 0:ce60014510e5 266 }
kkizirian 0:ce60014510e5 267
kkizirian 2:c708e2027970 268 void readClassFile(vector<Course>& cVec)
kkizirian 2:c708e2027970 269 {
kkizirian 0:ce60014510e5 270 cVec.clear();
kkizirian 0:ce60014510e5 271
kkizirian 0:ce60014510e5 272 FILE *readFp = fopen("/sd/classdir/classes.txt", "r");
kkizirian 0:ce60014510e5 273 char line[15];
kkizirian 0:ce60014510e5 274 char buildingBuf[4];
kkizirian 0:ce60014510e5 275 char hourBuf[3];
kkizirian 0:ce60014510e5 276 int hour;
kkizirian 0:ce60014510e5 277 char minuteBuf[3];
kkizirian 0:ce60014510e5 278 int minute;
kkizirian 0:ce60014510e5 279 char ampmBuf[3];
kkizirian 0:ce60014510e5 280 uLCD.cls();
kkizirian 0:ce60014510e5 281 uLCD.locate(0, 1);
kkizirian 0:ce60014510e5 282 uLCD.printf("Reading class file...");
kkizirian 2:c708e2027970 283
kkizirian 0:ce60014510e5 284 memset(buildingBuf, 0, sizeof(buildingBuf));
kkizirian 0:ce60014510e5 285 memset(hourBuf, 0, sizeof(hourBuf));
kkizirian 0:ce60014510e5 286 memset(minuteBuf, 0, sizeof(minuteBuf));
kkizirian 0:ce60014510e5 287 memset(ampmBuf, 0, sizeof(ampmBuf));
kkizirian 0:ce60014510e5 288 memset(line, 0, sizeof(line));
kkizirian 0:ce60014510e5 289
kkizirian 0:ce60014510e5 290 if (readFp == NULL)
kkizirian 0:ce60014510e5 291 return;
kkizirian 0:ce60014510e5 292 else {
kkizirian 0:ce60014510e5 293 while (!feof(readFp)) {
kkizirian 0:ce60014510e5 294 fgets(line, 15, readFp);
kkizirian 0:ce60014510e5 295 if(line[8] == NULL)
kkizirian 0:ce60014510e5 296 continue;
kkizirian 0:ce60014510e5 297 memcpy(buildingBuf, line, 3);
kkizirian 0:ce60014510e5 298 memcpy(hourBuf, &line[4], 2);
kkizirian 0:ce60014510e5 299 memcpy(minuteBuf, &line[7], 2);
kkizirian 0:ce60014510e5 300 memcpy(ampmBuf, &line[10], 2);
kkizirian 0:ce60014510e5 301
kkizirian 0:ce60014510e5 302 string building = buildingBuf;
kkizirian 0:ce60014510e5 303 hour = atoi(hourBuf);
kkizirian 0:ce60014510e5 304 minute = atoi(minuteBuf);
kkizirian 0:ce60014510e5 305 string ampm = ampmBuf;
kkizirian 0:ce60014510e5 306
kkizirian 0:ce60014510e5 307 Course temp(building, hour, minute, ampm);
kkizirian 0:ce60014510e5 308 cVec.push_back(temp);
kkizirian 0:ce60014510e5 309 }
kkizirian 0:ce60014510e5 310 }
kkizirian 0:ce60014510e5 311 fclose(readFp);
kkizirian 0:ce60014510e5 312 return;
kkizirian 2:c708e2027970 313 }
kkizirian 2:c708e2027970 314
kkizirian 2:c708e2027970 315 void displayCourseVec()
kkizirian 2:c708e2027970 316 {
nkela6 16:4b4e6cf66e7c 317 //uLCD.text_mode(TRANSPARENT);
kkizirian 2:c708e2027970 318 if (courseVec.size() == 0) {
kkizirian 2:c708e2027970 319 uLCD.cls();
kkizirian 2:c708e2027970 320 uLCD.locate(0,0);
kkizirian 2:c708e2027970 321 uLCD.printf("No classes input!");
kkizirian 2:c708e2027970 322 uLCD.locate(0,1);
kkizirian 2:c708e2027970 323 } else {
kkizirian 2:c708e2027970 324 uLCD.cls();
kkizirian 2:c708e2027970 325 uLCD.locate(0,1);
kkizirian 2:c708e2027970 326 for (int i = 0; i < courseVec.size(); i++) {
kkizirian 2:c708e2027970 327 uLCD.locate(0, i);
kkizirian 2:c708e2027970 328 uLCD.printf("%s", courseVec[i].getDisplayString());
kkizirian 2:c708e2027970 329 }
kkizirian 2:c708e2027970 330 }
kkizirian 3:0ca91f8afec5 331 }
kkizirian 3:0ca91f8afec5 332
kkizirian 3:0ca91f8afec5 333 float calculateHeading(float mx, float my)
kkizirian 3:0ca91f8afec5 334 {
kkizirian 3:0ca91f8afec5 335 float heading = 0.0;
kkizirian 3:0ca91f8afec5 336 if (my == 0.0)
kkizirian 3:0ca91f8afec5 337 heading = (mx < 0.0) ? 180.0 : 0.0;
kkizirian 3:0ca91f8afec5 338 else
kkizirian 3:0ca91f8afec5 339 heading = atan2(mx, my)*360.0/(2.0*PI);
kkizirian 3:0ca91f8afec5 340 //pc.printf("heading atan=%f \n\r",heading);
kkizirian 3:0ca91f8afec5 341 heading -= DECLINATION; //correct for geo location
kkizirian 3:0ca91f8afec5 342 if(heading>180.0) heading = heading - 360.0;
kkizirian 3:0ca91f8afec5 343 else if(heading<-180.0) heading = 360.0 + heading;
kkizirian 3:0ca91f8afec5 344 else if(heading<0.0) heading = 360.0 + heading;
kkizirian 3:0ca91f8afec5 345
kkizirian 3:0ca91f8afec5 346 // Convert everything from radians to degrees:
kkizirian 3:0ca91f8afec5 347 //heading *= 180.0 / PI;
kkizirian 3:0ca91f8afec5 348
kkizirian 3:0ca91f8afec5 349 //pc.printf("Magnetic Heading: %f degress\n\r",heading);
kkizirian 3:0ca91f8afec5 350 return heading;
kkizirian 3:0ca91f8afec5 351 }
kkizirian 3:0ca91f8afec5 352
kkizirian 3:0ca91f8afec5 353 float computeAngleToDestination(float diffLat, float diffLong)
kkizirian 3:0ca91f8afec5 354 {
kkizirian 3:0ca91f8afec5 355 float angle = 0.0;
kkizirian 3:0ca91f8afec5 356
kkizirian 3:0ca91f8afec5 357 if (diffLat > 0) {
kkizirian 3:0ca91f8afec5 358 if (diffLong > 0) {
kkizirian 3:0ca91f8afec5 359 // in quadrant 1
kkizirian 3:0ca91f8afec5 360 angle = 180*atan2(diffLat,diffLong)/PI;
kkizirian 3:0ca91f8afec5 361 } else {
kkizirian 3:0ca91f8afec5 362 // in quadrant 2
kkizirian 3:0ca91f8afec5 363 angle = 180*atan2(diffLat,-1 * diffLong)/PI;
kkizirian 3:0ca91f8afec5 364 angle = 180 - angle;
kkizirian 3:0ca91f8afec5 365 }
kkizirian 3:0ca91f8afec5 366 } else {
kkizirian 3:0ca91f8afec5 367 if (diffLong > 0) {
kkizirian 3:0ca91f8afec5 368 // in quadrant 4
kkizirian 3:0ca91f8afec5 369 angle = 180*atan2(-1*diffLat, diffLong)/PI;
kkizirian 3:0ca91f8afec5 370 angle = 360 - angle;
kkizirian 3:0ca91f8afec5 371 } else {
kkizirian 3:0ca91f8afec5 372 // in quadrant 3
kkizirian 3:0ca91f8afec5 373 angle = 180*atan2(-1*diffLat, -1*diffLong)/PI;
kkizirian 3:0ca91f8afec5 374 angle = 180 + angle;
kkizirian 3:0ca91f8afec5 375 }
kkizirian 3:0ca91f8afec5 376 }
kkizirian 3:0ca91f8afec5 377
kkizirian 3:0ca91f8afec5 378 //pc.printf("Angle to Destination: %f degress\n\r",angle);
kkizirian 3:0ca91f8afec5 379 return angle;
kkizirian 5:430f44669f94 380 }
kkizirian 5:430f44669f94 381
kkizirian 5:430f44669f94 382 int getNextClass(vector<Course>& cVec)
kkizirian 5:430f44669f94 383 {
kkizirian 5:430f44669f94 384 int numIterations = 0;
kkizirian 5:430f44669f94 385 for (int i = 0; i < cVec.size(); i++) {
kkizirian 5:430f44669f94 386 numIterations++;
kkizirian 5:430f44669f94 387 pc.printf("Iteration : %i\ncurrHour: %i\ncourseHour: %i\n", numIterations, currHour, cVec[i].getHour_inMilitaryTime());
kkizirian 5:430f44669f94 388 if (courseVec[i].getHour_inMilitaryTime() < currHour)
kkizirian 5:430f44669f94 389 continue;
kkizirian 5:430f44669f94 390 else if (courseVec[i].getHour_inMilitaryTime() > currHour)
kkizirian 5:430f44669f94 391 return i;
kkizirian 5:430f44669f94 392 else if (courseVec[i].getHour_inMilitaryTime() == currHour) {
kkizirian 5:430f44669f94 393 if (courseVec[i].getMinute() <= currMinute)
kkizirian 5:430f44669f94 394 continue;
kkizirian 5:430f44669f94 395 else if (courseVec[i].getMinute() > currMinute) {
kkizirian 5:430f44669f94 396 return i;
kkizirian 5:430f44669f94 397 }
kkizirian 5:430f44669f94 398 }
kkizirian 5:430f44669f94 399 if (numIterations == cVec.size())
kkizirian 5:430f44669f94 400 return 0;
kkizirian 5:430f44669f94 401 }
kkizirian 5:430f44669f94 402 return 0;
kkizirian 5:430f44669f94 403 }
kkizirian 5:430f44669f94 404
kkizirian 5:430f44669f94 405 void timeToNextClass()
kkizirian 6:ceb6a5426add 406 {
kkizirian 5:430f44669f94 407 hoursToNextClass = courseVec[nextClass].getHour_inMilitaryTime() - currHour;
kkizirian 5:430f44669f94 408 if (hoursToNextClass < 0)
kkizirian 5:430f44669f94 409 hoursToNextClass += 24;
kkizirian 5:430f44669f94 410
kkizirian 5:430f44669f94 411 minutesToNextClass = courseVec[nextClass].getMinute() - currMinute;
kkizirian 5:430f44669f94 412 if (minutesToNextClass < 0) {
kkizirian 5:430f44669f94 413 hoursToNextClass--;
kkizirian 5:430f44669f94 414 minutesToNextClass += 60;
kkizirian 5:430f44669f94 415 }
kkizirian 6:ceb6a5426add 416
kkizirian 5:430f44669f94 417 secondsToNextClass = 60 - currSecond;
kkizirian 5:430f44669f94 418 minutesToNextClass--;
kkizirian 6:ceb6a5426add 419
kkizirian 5:430f44669f94 420 if (minutesToNextClass < 0) {
kkizirian 5:430f44669f94 421 hoursToNextClass--;
kkizirian 5:430f44669f94 422 minutesToNextClass += 60;
kkizirian 5:430f44669f94 423 }
kkizirian 6:ceb6a5426add 424
kkizirian 5:430f44669f94 425 if (hoursToNextClass < 0)
kkizirian 5:430f44669f94 426 hoursToNextClass += 24;
kkizirian 6:ceb6a5426add 427 }
kkizirian 6:ceb6a5426add 428
kkizirian 6:ceb6a5426add 429 // convert from DDMM.mmmm to decimal
kkizirian 9:5b871fb9f554 430 float latToDecimal(float latitudeInDDMM, char northOrSouth)
kkizirian 6:ceb6a5426add 431 {
kkizirian 6:ceb6a5426add 432 float latInDec = 0.0;
kkizirian 6:ceb6a5426add 433 float temp = 0.0;
kkizirian 6:ceb6a5426add 434 latInDec = latitudeInDDMM / 100;
kkizirian 6:ceb6a5426add 435 temp = latInDec - floor(latInDec);
kkizirian 6:ceb6a5426add 436 temp = temp / .6;
kkizirian 6:ceb6a5426add 437 latInDec = floor(latInDec) + temp;
kkizirian 10:5579618161ef 438 if (northOrSouth == 'S')
kkizirian 9:5b871fb9f554 439 return -1 * latInDec;
kkizirian 6:ceb6a5426add 440 return latInDec;
kkizirian 6:ceb6a5426add 441 }
kkizirian 6:ceb6a5426add 442
nkela6 13:0eb9fbd63fb2 443 float displacement(float diffLat,float diffLong)
nkela6 13:0eb9fbd63fb2 444 {
nkela6 14:d8a6134cafa3 445 float d = sqrt(diffLat*diffLat+diffLong*diffLong);
nkela6 14:d8a6134cafa3 446 return d;
nkela6 13:0eb9fbd63fb2 447 }
nkela6 13:0eb9fbd63fb2 448 float calc_eta(float displacement, float speed)
nkela6 13:0eb9fbd63fb2 449 {
nkela6 15:75a121b14e5d 450 float estTimeArr = displacement/speed; // for displacement. take average speed // convert to minutes later
nkela6 15:75a121b14e5d 451 estTimeArr = estTimeArr+ 0.25*estTimeArr; //adding delay for distance vs displacement and traffic lights
nkela6 15:75a121b14e5d 452 return estTimeArr;
nkela6 14:d8a6134cafa3 453 }
nkela6 13:0eb9fbd63fb2 454
kkizirian 9:5b871fb9f554 455 float longToDecimal(float longitudeInDDMM, char eastOrWest)
kkizirian 6:ceb6a5426add 456 {
kkizirian 6:ceb6a5426add 457 float longInDec = 0.0;
kkizirian 6:ceb6a5426add 458 float temp = 0.0;
kkizirian 6:ceb6a5426add 459 longInDec = longitudeInDDMM / 100;
kkizirian 6:ceb6a5426add 460 temp = longInDec - floor(longInDec);
kkizirian 6:ceb6a5426add 461 temp = temp / .6;
kkizirian 6:ceb6a5426add 462 longInDec = floor(longInDec) + temp;
kkizirian 9:5b871fb9f554 463 if (eastOrWest == 'E')
kkizirian 9:5b871fb9f554 464 return longInDec;
kkizirian 6:ceb6a5426add 465 return -1 * longInDec;
nkela6 13:0eb9fbd63fb2 466 }
nkela6 13:0eb9fbd63fb2 467
nkela6 13:0eb9fbd63fb2 468 bool late(float eta)
nkela6 13:0eb9fbd63fb2 469 {
nkela6 13:0eb9fbd63fb2 470 float totalMinutes = hoursToNextClass*60+ minutesToNextClass+ secondsToNextClass/60;
nkela6 17:1de531cd3d4a 471 if(eta>totalMinutes) {
nkela6 13:0eb9fbd63fb2 472 return 1;
nkela6 14:d8a6134cafa3 473 } else {
nkela6 13:0eb9fbd63fb2 474 return 0;
nkela6 13:0eb9fbd63fb2 475 }
nkela6 14:d8a6134cafa3 476 }
nkela6 17:1de531cd3d4a 477