I have since updated this to use a larger screen. Here are some pictures
This is the GPS module sitting on a breadboard shield on top of an Arduino Uno.
This is the display on the LCD.
To code the display I have used a library called u8glib.h available on GitHub. This is a quite complex library. It allows you to create an LCD object and defines a number of methods for acting on it.
There are a number of ways to define a "construct" (or object) but I have used this simple one for the display which is 128 x 64 with an ST7920 controller.
U8GLIB_ST7920_128X64_1X lcd(SCK, MOSI, SS);
The Arduino pins SCK is the SPI bus clock, MOSI is the data line and SS is the chip select. These are connected to the display LCD signals E, R/W and RS.
Methods
lcd.begin(); // reset display and put in default state lcd.enableCursor(); // cursor visible lcd,disableCursor(); // cursor not visible (default state) lcd.setCursorPos(x, y); // cursor to x, y lcd.setColorindex(col); // BW on = 1, off = 0 lcd.drawBitMap(x, y, cnt, h, *bitmap); // draw bit map of cnt bytes // width is cnt * 8 // at x, y (top left) of height h lcd.drawBox(x, y, w, h); // filled box at x, y. width w, height h // fill set by color index lcd.drawCircle(x, y, rad, opt); // x, y centre of circle radius rad, // opt is option to draw part of circle // U8G_DRAW_UPPER_RIGHT, ...LEFT, // ... LOWER_LEFT, ... RIGHT, ...ALL lcd.drawDisk(x, y, rad, opt); // as above but filled circle lcd.drawFrame(x, y, w, h); // frame at x, y width w height h, color index lcd.drawRFrame(x, y, w, h, r); // rounded frame, edges radius r lcd.drawHLine(x, y, w); // draw horizontal line from x,y width w (pixels) lcd.drawVLine(x, y, h); // draw vertical line from x, y height h (pixels) lcd.drawLine(x1, y1, x2, y2,); // draw line from x1, y1 to x2, y2 drawTriangle(x1, y1, x2, y2, x3, y3); // filled triangle lcd.drawPixel(x, y); // pixel at x, y lcd.setFont(*font); // sets font - see table below lcd.getStrWidth(*s); // returns string width in pixels in current font lcd.drawStr(x, y, *s); // string at x, lower left of characters in setFont // variations on this draw at 90, 180, 270 degrees lcd.firstPage(); // starts a “picture loop” lcd.nextPage(); // marks end of “picture loop”, returns 0 if finished
The display can use a wide range of fonts, the one I used is called "u8g_font_helvR08" or Helvetica Regular 8 point.
Code
#include "SoftwareSerial.h" #include "U8glib.h" // GPS comms 11 RX, 10 TX and LCD u8g object 6 SCK(E), 5 MOSI(RW), 4 SS(RS) SoftwareSerial gps(10, 11); U8GLIB_ST7920_128X64_1X u8g(6, 5, 4); void setup() { gps.begin(9600); // start GPS serial } void loop() { char gpsbuf[200]; char ebuf[9][20]; readgps(gpsbuf); // read each $GPxxx NMEAstrings+CRLF into gpsbuf // use $GPRMC, 142759.00,A,5204.81158,N,00120.76633,W,0.107,,,090114,,,A*67 // fields 1, 3, 4, 5, 6, 9 if(strncmp(gpsbuf, "$GPRMC", 6) == 0) { extract(1, gpsbuf, ebuf[1]); // get utc fmt(ebuf[1], "**:**:**"); // format utc extract(3, gpsbuf, ebuf[3]); // get lat fmt(ebuf[3], "** ****"); // format lat extract(4, gpsbuf, ebuf[4]); // get N|S fmt(ebuf[4], "*"); // format N|S extract(5, gpsbuf, ebuf[5]); // get lon fmt(ebuf[5], "*** ****"); // format lon extract(6, gpsbuf, ebuf[6]); // get E|W fmt(ebuf[6], "*"); // format E|W extract(9, gpsbuf, ebuf[9]); // get date fmt(ebuf[9], "**-**-**"); // format date u8g.firstPage(); do { u8g.setFont(u8g_font_helvR08); u8g.drawStr(2, 8, "Latitude"); u8g.drawStr(66, 8, "Longitude"); u8g.drawStr(2, 19, ebuf[3]); // Lat u8g.drawStr(40, 19, ebuf[4]); u8g.drawStr(66, 19, ebuf[5]); // Lon u8g.drawStr(110, 19, ebuf[6]); u8g.drawStr(2, 40, "Time"); u8g.drawStr(66, 40, "Date"); u8g.drawStr(2, 51, ebuf[1]); // UTC u8g.drawStr(66, 51, ebuf[9]); // Date } while(u8g.nextPage()); } } // read GPxxx NMEA string into buffer void readgps(char *buffer) { int bp; char c; bp = 0; do { c = gps.read(); if(c == -1) continue; // gps sends -1 when idle buffer[bp++] = c; } while(c != '\n'); // ends with LF buffer[bp] = '\0'; // add '\0' } // extract string from field 0-10 from inbuf to outbuf void extract(int field, char *inbuf, char *outbuf) { int fcount; // field counter int ip; // inbuf pointer int op; // outbuf ptr fcount = 0; ip = 0; op = 0; while(fcount != field) // find field { while(inbuf[ip++] != ','); fcount++; } while(inbuf[ip] != ',') // copy inbuf to outbuf { outbuf[op++] = inbuf[ip++]; } outbuf[op] = '\0'; // mark end of string } // formats buffer with fmtstr, result back in buffer void fmt(char *buffer, char *fmtstr) { char tmp[20]; int bp, fp, tp; // buffer, fmtstr & tmp pointers bp = 0; fp = 0; tp = 0; strcpy(tmp, buffer); while(fmtstr[fp] != '\0') { if(fmtstr[fp] == '*') { buffer[bp] = tmp[tp++]; } else { buffer[bp] = fmtstr[fp]; } fp++; bp++; } buffer[bp] = '\0'; }
No comments:
Post a Comment