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