Skip to content

Instantly share code, notes, and snippets.

@bitbank2
Created August 20, 2022 13:39
Show Gist options
  • Save bitbank2/9f07b6882dc558a65ff94c5d5644ea64 to your computer and use it in GitHub Desktop.
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)
//
// 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