Created
August 20, 2022 13:39
-
-
Save bitbank2/9f07b6882dc558a65ff94c5d5644ea64 to your computer and use it in GitHub Desktop.
Simplest possible program to capture GPS current time and location (no external dependencies for parsing NMEA strings)
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// GP-02 GPS/BDS/GNSS module performance test | |
// tested with a ESP32-S2 module (USB CDC serial + exposed HW UART pins) | |
// | |
#include <OneBitDisplay.h> | |
ONE_BIT_DISPLAY obd; | |
uint8_t u8Flags; | |
#define FLAG_TIMEDATE 1 | |
#define FLAG_POSITION 2 | |
int iHour, iMin, iSec, iDate, iMonth, iYear; | |
float fLat, fLong; | |
char cLat, cLong; | |
void setup() { | |
// pinMode(A1, output); | |
// digitalWrite(A1, HIGH); // set N/F signal high to enable module (shutdown control) | |
obd.setI2CPins(41,40); // Adafruit QT Py ESP32-S2 has the Qwiic connector on 41/40 | |
obd.I2Cbegin(); // initialize a SSD1306 128x64 OLED (default display type) | |
obd.fillScreen(0); | |
Serial.begin(115200); // try to start CDC (USB) serial terminal | |
Serial1.begin(9600); // GPS serial port (RX/TX pins) | |
if (Serial) | |
Serial.println("Starting GPS test..."); | |
} /* setup() */ | |
// | |
// Read characters from the serial port | |
// until EOL/CR is reached | |
// | |
int captureString (char *szText) | |
{ | |
int i = 0; | |
while (1) { | |
if (Serial1.available()) { | |
char c = Serial1.read(); | |
if (c >= ' ') { | |
szText[i++] = c; | |
} else if (i > 0) { | |
szText[i] = 0; // terminate | |
return i; | |
} | |
} else { // wait for more chars to arrive | |
delay(10); | |
} | |
} // while (1) | |
} /* captureString() */ | |
// | |
// Capture 2 ASCII digits as an integer | |
// | |
int twoDigits(char *s) | |
{ | |
int i; | |
i = (s[0] - '0') * 10; | |
i += (s[1] - '0'); | |
return i; | |
} /* twoDigits() */ | |
// | |
// Returns true for a valid string | |
// | |
bool parseString(char *szText, int iLen, uint8_t *pFlags) | |
{ | |
if (szText[0] == '$') { | |
if (szText[1] == 'G' && szText[2] == 'N') { // GNSS talker id | |
if (memcmp(&szText[3], "GGA", 3) == 0 && iLen > 40) { // GPS location data | |
fLat = (atof(&szText[18]) / 100.0f); // capture latitude | |
cLat = szText[29]; // N/S | |
fLong = (atof(&szText[31]) / 100.0f); // capture longitude | |
cLong = szText[43]; // E/W | |
*pFlags |= FLAG_POSITION; | |
return true; | |
} | |
if (memcmp(&szText[3], "RMC", 3) == 0 && szText[17] == 'A') { // minimum (valid) GNSS location data | |
fLat = (atof(&szText[19]) / 100.0f); // capture latitude | |
cLat = szText[32]; // N/S | |
fLong = (atof(&szText[34]) / 100.0f); // capture longitude | |
cLong = szText[48]; // E/W | |
*pFlags |= FLAG_POSITION; | |
return true; | |
} | |
if (memcmp(&szText[3], "ZDA", 3) == 0 && iLen > 28) { // valid time and date | |
iHour = twoDigits(&szText[7]); | |
iMin = twoDigits(&szText[9]); | |
iSec = twoDigits(&szText[11]); | |
iDate = twoDigits(&szText[18]); | |
iMonth = twoDigits(&szText[21]); | |
iYear = 2000 + twoDigits(&szText[26]); | |
*pFlags |= FLAG_TIMEDATE; | |
return true; | |
} | |
} else if (szText[1] == 'G' && szText[2] == 'P') { // GPS talker id | |
} else if (szText[1] == 'B' && szText[2] == 'D') { // BDS talker id | |
} | |
} | |
return false; | |
} /* parseString() */ | |
void loop() { | |
int iLen, iCount; | |
char szTemp[256]; | |
long lTime; | |
bool bGotTime = false, bGotLoc = false; | |
u8Flags = 0; | |
iCount = 0; | |
lTime = millis(); | |
while (1) { | |
iLen = captureString(szTemp); | |
if (Serial) { | |
Serial.println(szTemp); // echo to CDC terminal if available | |
} | |
if (iLen > 6) { // only parse potentially valid strings | |
obd.setFont(FONT_8x8); | |
obd.setCursor(0,0); | |
iCount++; | |
obd.printf("GPS recvd %d", iCount); | |
if (parseString(szTemp, iLen, &u8Flags)) { | |
if (u8Flags & FLAG_TIMEDATE) { | |
u8Flags &= ~FLAG_TIMEDATE; | |
// mark when time was acquired | |
if (!bGotTime) { | |
bGotTime = true; | |
obd.setCursor(0,8); | |
obd.printf("time @ %dms", (int)(millis() - lTime)); | |
} | |
obd.setCursor(0,24); | |
obd.setFont(FONT_8x8); | |
obd.printf("%02d:%02d:%02d", iHour, iMin, iSec); | |
} | |
if (u8Flags & FLAG_POSITION) { | |
u8Flags &= ~FLAG_POSITION; | |
// mark when location was acquired | |
if (!bGotLoc) { | |
bGotLoc = true; | |
obd.setCursor(0,16); | |
obd.printf("loc @ %dms", (int)(millis() - lTime)); | |
} | |
// obd.setFont(FONT_6x8); | |
obd.setCursor(0,32); | |
// obd.setTextWrap(true); | |
// obd.print(szTemp); | |
obd.setFont(FONT_8x8); | |
sprintf(szTemp, "LAT: %02.4f,%c", fLat, cLat); | |
obd.println(szTemp); | |
sprintf(szTemp, "LONG: %03.4f,%c", fLong, cLong); | |
obd.print(szTemp); | |
} | |
} | |
} | |
} | |
} /* loop() */ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment