/**
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 <SoftwareSerial.h>
#include <LiquidCrystal.h>
#include <string.h>
#include <ctype.h>
#include <math.h>
#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 <LF>, 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;
}
Comments