0% found this document useful (0 votes)
55 views4 pages

GPS Speedometer

The document configures an Arduino to communicate with a GPS module and display location data on an OLED screen. It sets up the GPS module to send specific UBX messages and disables all NMEA messages. When a UBX message is received, it parses the payload and extracts GPS data like speed and satellite count, then displays this on the screen along with refresh indicators.

Uploaded by

tehatelu
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
55 views4 pages

GPS Speedometer

The document configures an Arduino to communicate with a GPS module and display location data on an OLED screen. It sets up the GPS module to send specific UBX messages and disables all NMEA messages. When a UBX message is received, it parses the payload and extracts GPS data like speed and satellite count, then displays this on the screen along with refresh indicators.

Uploaded by

tehatelu
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as TXT, PDF, TXT or read online on Scribd
You are on page 1/ 4

/*

Connections:
GPS TX -> Arduino 0 (disconnect to upload this sketch)
GPS RX -> Arduino 1
Screen SDA -> Arduino A4
Screen SCL -> Arduino A5
*/

#include "U8glib.h"

U8GLIB_SSD1306_128X64 u8g(U8G_I2C_OPT_DEV_0|U8G_I2C_OPT_NO_ACK|U8G_I2C_OPT_FAST);
// Fast I2C / TWI

#define GPS Serial

const unsigned char UBLOX_INIT[] PROGMEM = {


// Disable NMEA

0xB5,0x62,0x06,0x01,0x08,0x00,0xF0,0x00,0x00,0x00,0x00,0x00,0x00,0x01,0x00,0x24, //
GxGGA off

0xB5,0x62,0x06,0x01,0x08,0x00,0xF0,0x01,0x00,0x00,0x00,0x00,0x00,0x01,0x01,0x2B, //
GxGLL off

0xB5,0x62,0x06,0x01,0x08,0x00,0xF0,0x02,0x00,0x00,0x00,0x00,0x00,0x01,0x02,0x32, //
GxGSA off

0xB5,0x62,0x06,0x01,0x08,0x00,0xF0,0x03,0x00,0x00,0x00,0x00,0x00,0x01,0x03,0x39, //
GxGSV off

0xB5,0x62,0x06,0x01,0x08,0x00,0xF0,0x04,0x00,0x00,0x00,0x00,0x00,0x01,0x04,0x40, //
GxRMC off

0xB5,0x62,0x06,0x01,0x08,0x00,0xF0,0x05,0x00,0x00,0x00,0x00,0x00,0x01,0x05,0x47, //
GxVTG off

// Disable UBX

0xB5,0x62,0x06,0x01,0x08,0x00,0x01,0x07,0x00,0x00,0x00,0x00,0x00,0x00,0x17,0xDC, //
NAV-PVT off

0xB5,0x62,0x06,0x01,0x08,0x00,0x01,0x02,0x00,0x00,0x00,0x00,0x00,0x00,0x12,0xB9, //
NAV-POSLLH off

0xB5,0x62,0x06,0x01,0x08,0x00,0x01,0x03,0x00,0x00,0x00,0x00,0x00,0x00,0x13,0xC0, //
NAV-STATUS off

// Enable UBX

0xB5,0x62,0x06,0x01,0x08,0x00,0x01,0x07,0x00,0x01,0x00,0x00,0x00,0x00,0x18,0xE1, //
NAV-PVT on

//0xB5,0x62,0x06,0x01,0x08,0x00,0x01,0x02,0x00,0x01,0x00,0x00,0x00,0x00,0x13,0xBE,
//NAV-POSLLH on

//0xB5,0x62,0x06,0x01,0x08,0x00,0x01,0x03,0x00,0x01,0x00,0x00,0x00,0x00,0x14,0xC5,
//NAV-STATUS on

// Rate
0xB5,0x62,0x06,0x08,0x06,0x00,0x64,0x00,0x01,0x00,0x01,0x00,0x7A,0x12, //(10Hz)
//0xB5,0x62,0x06,0x08,0x06,0x00,0xC8,0x00,0x01,0x00,0x01,0x00,0xDE,0x6A, //(5Hz)
//0xB5,0x62,0x06,0x08,0x06,0x00,0xE8,0x03,0x01,0x00,0x01,0x00,0x01,0x39 //(1Hz)
};

const unsigned char UBX_HEADER[] = { 0xB5, 0x62 };

struct NAV_PVT {
unsigned char cls;
unsigned char id;
unsigned short len;
unsigned long iTOW; // GPS time of week of the navigation epoch (ms)

unsigned short year; // Year (UTC)


unsigned char month; // Month, range 1..12 (UTC)
unsigned char day; // Day of month, range 1..31 (UTC)
unsigned char hour; // Hour of day, range 0..23 (UTC)
unsigned char minute; // Minute of hour, range 0..59 (UTC)
unsigned char second; // Seconds of minute, range 0..60 (UTC)
char valid; // Validity Flags (see graphic below)
unsigned long tAcc; // Time accuracy estimate (UTC) (ns)
long nano; // Fraction of second, range -1e9 .. 1e9 (UTC) (ns)
unsigned char fixType; // GNSSfix Type, range 0..5
char flags; // Fix Status Flags
unsigned char reserved1; // reserved
unsigned char numSV; // Number of satellites used in Nav Solution

long lon; // Longitude (deg)


long lat; // Latitude (deg)
long height; // Height above Ellipsoid (mm)
long hMSL; // Height above mean sea level (mm)
unsigned long hAcc; // Horizontal Accuracy Estimate (mm)
unsigned long vAcc; // Vertical Accuracy Estimate (mm)

long velN; // NED north velocity (mm/s)


long velE; // NED east velocity (mm/s)
long velD; // NED down velocity (mm/s)
long gSpeed; // Ground Speed (2-D) (mm/s)
long heading; // Heading of motion 2-D (deg)
unsigned long sAcc; // Speed Accuracy Estimate
unsigned long headingAcc; // Heading Accuracy Estimate
unsigned short pDOP; // Position dilution of precision
short reserved2; // Reserved
unsigned long reserved3; // Reserved
};

NAV_PVT pvt;

void calcChecksum(unsigned char* CK) {


memset(CK, 0, 2);
for (int i = 0; i < (int)sizeof(NAV_PVT); i++) {
CK[0] += ((unsigned char*)(&pvt))[i];
CK[1] += CK[0];
}
}

long numGPSMessagesReceived = 0;

bool processGPS() {
static int fpos = 0;
static unsigned char checksum[2];
const int payloadSize = sizeof(NAV_PVT);

while ( GPS.available() ) {
byte c = GPS.read();
if ( fpos < 2 ) {
if ( c == UBX_HEADER[fpos] )
fpos++;
else
fpos = 0;
}
else {
if ( (fpos-2) < payloadSize )
((unsigned char*)(&pvt))[fpos-2] = c;

fpos++;

if ( fpos == (payloadSize+2) ) {
calcChecksum(checksum);
}
else if ( fpos == (payloadSize+3) ) {
if ( c != checksum[0] )
fpos = 0;
}
else if ( fpos == (payloadSize+4) ) {
fpos = 0;
if ( c == checksum[1] ) {
return true;
}
}
else if ( fpos > (payloadSize+4) ) {
fpos = 0;
}
}
}
return false;
}

void setup()
{
GPS.begin(9600);

u8g.setColorIndex(1);

// send configuration data in UBX protocol


for(unsigned int i = 0; i < sizeof(UBLOX_INIT); i++) {
GPS.write( pgm_read_byte(UBLOX_INIT+i) );
delay(5); // simulating a 38400baud pace (or less), otherwise commands are not
accepted by the device.
}

long gSpeed = 0;
int numSV = 0;
unsigned long lastScreenUpdate = 0;
char speedBuf[16];
char satsBuf[16];
char* spinner = "/-\\|";
byte screenRefreshSpinnerPos = 0;
byte gpsUpdateSpinnerPos = 0;

void loop() {
if ( processGPS() ) {
numSV = pvt.numSV;
gSpeed = pvt.gSpeed;
gpsUpdateSpinnerPos = (gpsUpdateSpinnerPos + 1) % 4;
}

unsigned long now = millis();


if ( now - lastScreenUpdate > 100 ) {
updateScreen();
lastScreenUpdate = now;
screenRefreshSpinnerPos = (screenRefreshSpinnerPos + 1) % 4;
}
}

void draw() {
//u8g.setScale2x2(); don't do this!
u8g.setFont(u8g_font_courB24);
u8g.drawStr( 36, 45, speedBuf);
//u8g.undoScale();
u8g.setFont(u8g_font_fur11);
u8g.drawStr( 2, 12, satsBuf);
}

void updateScreen() {

int kmh = gSpeed * 0.0036;


sprintf(speedBuf, "%3d", kmh);
sprintf(satsBuf, "%c %c %d", spinner[screenRefreshSpinnerPos],
spinner[gpsUpdateSpinnerPos], numSV);

u8g.firstPage();
do {
draw();
} while( u8g.nextPage() );
}

You might also like