/** Code to display the time & date from a GPS receiver on a LCD. This code was inspired by http://arduino.cc/en/Tutorial/LiquidCrystal and http://playground.arduino.cc/Tutorials/GPS For more information, see http://quaxio.com/arduino_gps/ Edit: 4 June 2017 : Fixed the direction logic.. North is OR less than 22.5 OR greater than 3sumptin || everything else is AND && Cleaned it up a bit. */ #include #include #include #include #include #define DEBUG 0 SoftwareSerial mySerial(19, 18); // RX, TX LiquidCrystal lcd(8, 9, 4, 5, 6, 7); int VOID = 1; int rxPin = 19; // RX pin int txPin = 18; // TX pin int DayLight = -8; int byteGPS = -1; int counter1 = 0; // counts how many bytes were received (max 300) int counter2 = 0; // counts how many commas were seen int offsets[13]; char buf[310] = ""; int first = 1; byte North[8] = { B00000, B00100, B01110, B10101, B00100, B00100, B00100, B00000 }; byte NorthEast[8] = { B00000, B00000, B01111, B00011, B00101, B01001, B10000, B00000 }; byte East[8] = { B00000, B00100, B00010, B11111, B00010, B00100, B00000, B00000 }; byte SouthEast[8] = { B00000, B10000, B01001, B00101, B00011, B01111, B00000, B00000 }; byte South[8] = { B00000, B00100, B00100, B00100, B10101, B01110, B00100, B00000 }; byte SouthWest[8] = { B00000, B00001, B10010, B10100, B11000, B11110, B00000, B00000 }; byte West[8] = { B00000, B00100, B01000, B11111, B01000, B00100, B00000, B00000 }; byte NorthWest[8] = { B00000, B00000, B11110, B11000, B10100, B10010, B00001, B00000 }; // Keys AnalogRead(0); const int Keyselect = 650; const int KeyLeft = 409; const int KeyRight = 49; const int KeyUp = 100; const int KeyDown = 255; // select 600-650 // left 350-500 // right 0 // up 50-200 // down 201-349 int Key, KeyCount, LastKey; int backLight=125; int BackLightPin = 10; char CRLF[3] = {13,10,0}; char chksum(char checksumsource[300], char header[1], char footer[1]) { int CRC=0; int i,h,f = 0; if(checksumsource[i] == header[0]) h++; #if DEBUG == 5 Serial.println("\n -=-=-=-=-=-=-=-=-= CHK SUM SOURCE =-=-=-=-=-=-=-=-"); Serial.print(checksumsource); Serial.println("\n -=-=-=-=-=-=-=-=-= chksum =-=-=-=-=-=-=-=-"); Serial.print(checksumsource[0]); #endif for(i=h; checksumsource[i] != '*'; i++ ) { #if DEBUG == 1 Serial.print(checksumsource[i]); #endif CRC = (CRC ^ checksumsource[i]) && 255; } f=i; #if DEBUG == 5 Serial.print(checksumsource[f]); Serial.print(CRC,HEX); Serial.print("\n -=-=-=-=-=-=-=-= end chksum =-=-=-=-=-=-=-\n\n"); #endif return CRC; } /** Setup display and gps */ void setup() { char buf2(300); pinMode(rxPin, INPUT); pinMode(txPin, OUTPUT); pinMode(10,OUTPUT); Serial.begin(9600); lcd.createChar(0,North); lcd.createChar(1,NorthEast); lcd.createChar(2,East); lcd.createChar(3,SouthEast); lcd.createChar(4,South); lcd.createChar(5,SouthWest); lcd.createChar(6,West); lcd.createChar(7,NorthWest); lcd.begin(16, 2); lcd.clear(); //Serial.println("Wait for gps"); lcd.print(" Wait for gps"); offsets[0] = 0; reset(); mySerial.begin(9600); //mySerial.println(cmd); #if DEBUG == 1 char buf4[]="$PSRF103,00,00,01,01*11"; delay(1000); //Serial.print("\n"); //Serial.print(buf4); //Serial.print("-"); //Serial.print(chksum(buf4,'$','*'),HEX); //Serial.print(CRLF); #endif } void reset() { counter1 = 0; counter2 = 0; offsets[0] = 0; // offset=0; } int get_size(int offset) { return offsets[offset + 1] - offsets[offset] - 1; } int DoGPRMC(void ) { int b,j,h = 0; float f; char cmd[7] = "$GPRMC"; char buf2[11]; char buf3[11]; if (counter2 == 0) return 0; if ((counter2 == 12 ) && (get_size(0) == 6)) { // Check that we received $GPRMC for (j = 0; j < 6; j++) { if (buf[j] != cmd[j]) { return 0; } } //Serial.println("\n ---------- GPRMC checksum --------------- "); for (j = 1; buf[ j-1] != '*'; ++j) { buf2[j] = buf[ j]; } buf2[0] = '$'; buf2[j]=0; if (get_size(1) != 10) { return 0; } // Check that date is well formed if (get_size(9) != 6) { return 0; } if (first == 1 ) { first = 0; lcd.clear(); } // TODO: compute and validate checksum // TODO: handle timezone offset // 0 1 2 3 4 5 6 7 8 9 10 11 12 // $GPRMC,185726.000,A,3327.8968,N,11707.0896,W,0.00,44.99,060517, , ,A*4B // print time lcd.setCursor(11, 0); for (j = 0; j < 2; j++) { buf2[j] = buf[offsets[1] + j]; } buf2[j] = 0; DayLight = -8; if(buf[offsets[9]]='0' && ( buf[offsets[9]+1]='5' && buf[offsets[9]+2]> '2')) DayLight = -7; if(buf[offsets[9]]='1' && (buf[offsets[9]+1]='1' && buf[offsets[9]+2]<'1')) DayLight = -7; if(buf[offsets[9]]='0' && buf[offsets[9]+1]>'5') DayLight = -7; if(buf[offsets[9]]='1' && buf[offsets[9]+1]<'1') DayLight = -7; if ((atoi(buf2) + DayLight) < 0) j = atoi(buf2) + (24+ DayLight); else j=atoi(buf2) + DayLight; #if DEBUG == 1 //Serial.print(atoi(buf2)); //Serial.print(" <- buf2 j-> "); //Serial.println(j); #endif j=sprintf(buf3,"%2.0d:%c%c",j,buf[offsets[1] + 2],buf[offsets[1] + 3]); lcd.print(buf3); ////Serial.print(buf3); ////Serial.println(" <- buf3"); lcd.setCursor(13, 1); j=sprintf(buf3," %c%c",buf[offsets[1] + 4],buf[offsets[1] + 5]); j=atoi(buf3); lcd.print(buf3); //lcd.print(buf[offsets[1] + 5]); /* * if (buf[offsets[2]] == 'V') { lcd.setCursor(0, 1); lcd.blink(); //lcd.print(" DATA VOID "); //Serial.println(" DATA VOID "); VOID = 1; return 0; } else { if (VOID == 1) lcd.clear(); VOID = 0; lcd.noBlink(); lcd.print(":"); } */ // print Speed for (j = 0; buf[offsets[7] + j] != ','; j++) { buf2[j] = buf[offsets[7] + j]; } buf2[j] = 0; lcd.setCursor(0, 0); f = atoi(buf2); // if (f > 0) { dtostrf(f*1.151,4,1,buf2); if (atof(buf2)*1.151 > 75) { lcd.blink(); //Serial.println("OVER SPEED BLINK "); } else lcd.noBlink(); lcd.print(buf2); lcd.print(" M "); lcd.setCursor(0, 1); dtostrf(f*1.852,4,1,buf2); lcd.print(buf2); lcd.print(" k"); #if DEBUG == 1 //Serial.print(" SPEEEEDDDDD "); //Serial.println(buf2); #endif /* } else { lcd.print("Stopped "); lcd.setCursor(0, 1); lcd.print(" "); } */ // print heading if (get_size(8) > 0) { for (j = 0; buf[offsets[8] + j] != ','; j++) { buf2[j] = buf[offsets[8] + j]; } buf2[j] = 0; lcd.setCursor(9, 1); float f; #if DEBUG == 0 Serial.print(buf2); #endif f = atof(buf2); #if DEBUG == 0 Serial.print(" heading "); Serial.println(f); #endif if(f >= 337.5 || f < 22.5) { j=sprintf(buf2, "N "); h=0; } else if(f >= 22.5 && f < 67.5) { j=sprintf(buf2, "NE "); h=1; } else if (f >= 67.5 && f < 112.5) { j=sprintf(buf2, "E "); h=2; } else if (f >= 112.5 && f < 157.5) { j=sprintf(buf2, "SE "); h=3; } else if (f >= 157.5 && f < 202.5) { j=sprintf(buf2, "S"); h=4; } else if (f >= 202.5 && f < 247.5) { j=sprintf(buf2, "SW "); h=5; } else if (f >= 247.5 && f < 292.5) { j=sprintf(buf2, "W "); h=6; } else if (f >= 292.5 && f < 337.5) { j=sprintf(buf2, "NW "); h=7; } #if DEBUG == 0 Serial.print(" Buf2 "); Serial.println(buf2); #endif lcd.print(buf2); lcd.setCursor(12,1); lcd.write(byte(h)); //Serial.print(buf2); // lcd.print("D"); } buf2[0] = 0; counter2 = 0; counter1 = 0; // offset=0; offsets[0] = 0; buf[0] = '*'; return 0; } else { return 0; } } int DoGPVTG(void ) { char cmd[7]="$GPVTG"; int j,h=0; char buf2[11]; char buf3[11]; for (j = 0; j < 6; j++) { if (buf[j] != cmd[j]) { return 0; } } return 0; } int DoGPGGA(void ) { char cmd[7]="$GPGGA"; int j,h=0; char buf2[11]; char buf3[11]; for (j = 0; j < 6; j++) { if (buf[j] != cmd[j]) { return 0; } } return 0; } int DoGPGSV(void ) { char cmd[7]="$GPGSV"; int j,h=0; char buf2[11]; char buf3[11]; for (j = 0; j < 6; j++) { if (buf[j] != cmd[j]) { return 0; } } for (j = 1; buf[ j-1] != '*'; ++j) { buf2[j] = buf[ j]; } buf2[0] = '$'; buf2[j]=0; #if DEBUG > 0 Serial.println(buf2); Serial.print(cmd); Serial.print(" Satellites in view"); #endif lcd.setCursor(7,0); for (j = 0; buf[offsets[3]+j]!=','; j++) { lcd.print(buf[offsets[3]+j]); } lcd.print("S "); return 0; } int handle_byte(int byteGPS) { if (byteGPS == '$') { //offsets[12] = counter1; counter1 = 0; counter2 = 0; offsets[0] = 0; buf[1] = 0; } buf[counter1] = byteGPS; buf[counter1 + 1] = 0; buf[counter1 + 2] = 0; counter1++; if (counter1 == 300) { buf[0] = 0; buf[40] = 0; buf[80] = 0; return 0; } if (byteGPS == ',') { counter2++; offsets[counter2] = counter1; } if (byteGPS == '*') { if (buf[counter1 - 2] == 'V') { VOID = 1; } buf[counter1 + 1] = 0; buf[counter1 + 2] = 0; buf[counter1 + 3] = 0; buf[counter1 + 4] = 0; } // Check if we got a , which indicates the end of line if (byteGPS == 10) { int h = 0; buf[counter1 - 1] = 0; buf[counter1] = 0; buf[counter1 + 1] = 0; buf[counter1 + 2] = 0; DoGPRMC(); DoGPVTG(); DoGPGSV(); DoGPGGA(); #if DEBUG == 2 Serial.println(buf); #endif } return 1; } /** Main loop */ void loop() { if (mySerial.available() > 0) { byteGPS = mySerial.read(); #if DEBUG > 5 Serial.print(byteGPS); // Read a byte of the serial port #endif //delay(50); if (!handle_byte(byteGPS)) { reset(); } } Key = analogRead(0); if(abs(LastKey-Key)<20) { if(++KeyCount>3) { if(abs(Key-KeyUp)<30 ) { if(backLight<251) backLight += 5; KeyCount=0; //Serial.println(backLight); } else if(abs(Key-KeyDown)<30 ) { if(backLight>4) backLight -= 5; KeyCount=0; //Serial.println(backLight); } } // else KeyCount++; }else { KeyCount=0; if(Key<800) { //Serial.print("LastKey " ); //Serial.print(LastKey); //Serial.print(" Key "); //Serial.println(Key); } } LastKey=Key; analogWrite(BackLightPin,backLight); #if DEBUG > 3 Serial.print("BackLight : "); Serial.println(backLight); #endif // int backLight=128; //int BackLightPin = 10; }