Got the LS20031 to play nice with TineGPS with NO check sum error
Here is the sketch that the LS20031 play nice with TinyGPS with no CheckSum errors for over 8 hours >>
You have to use a logic voltage converter between the to so you can communicate with the LS20031.
The logic voltage converter I am using is from http://www.dsscircuits.com/i2c-level-converter.html.
The cool thing about using this one, is that it does not require pull up resistors on either side of the converter.
Also I have killed a number of the Mosfet voltage converters sitting on my desk. This one survived on my desk for over 6 months.
See http://www.dsscircuits.com/images/schem … Wiring.pdf for wiring Diagram.
#include <SoftwareSerial.h>
#define rxPin 3
#define txPin 4
/*you need to go into Arduino -> Libraries-> SoftwareSerial-> SoftwareSerial.h and increase buffersize from 64 to 128. >>
Open the file named "SoftwareSerial.h" in a text editor and scroll down to line 42, where you should see:
#define _SS_MAX_RX_BUFF 64 // RX buffer size
Increase the value 64, to a more reasonable 128 and then save the file. See Wayneholder web page for more information>>
https://sites.google.com/site/wayneholder/self-driving-rc-car/navigating-with-gps
*/
#define PMTK_SET_NMEA_UPDATE_HALF_HZ "$PMTK220,2000*1C\r\n" // Every 2000ms (0.5Hz)
#define PMTK_SET_NMEA_UPDATE_1HZ "$PMTK220,1000*1F\r\n" // Every 1000ms (1Hz)
#define PMTK_SET_NMEA_UPDATE_2HZ "$PMTK220,500*2B\r\n>" // Every 500ms (2Hz)
#define PMTK_SET_NMEA_UPDATE_5HZ "$PMTK220,200*2C\r\n" // Every 200ms (5Hz)
#define PMTK_SET_NMEA_UPDATE_10HZ "$PMTK220,100*2F\r\n" // Every 100ms (10Hz)
/* If the command is correct and executed, GPS module will output message $PMTK001,220,3*30<CR><LF>*/
#define PMTK_Set_NMEA_OUTPUT_GLL "$PMTK314,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0*29\r\n" // turn on only GLL - Geographic position, latitude / longitude
#define PMTK_SET_NMEA_OUTPUT_RMC "$PMTK314,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0*29\r\n" // turn on only RMC - Recommended minimum specific Loran-C data
#define PMTK_SET_NEMA_OUTPUT_VTG "$PMTK314,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0*29\r\n" // turn on only VTG - Track made good and ground speed
#define PMTK_SET_NEMA_OUTPUT_GGA "$PMTK314,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0*29\r\n" // turn on only GGA - Global Positioning System Fix Data
#define PMTK_SET_NMEA_OUTPUT_RMCGGA "$PMTK314,0,1,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0*28\r\n" // turn on GPRMC and GPGGA ----- TinyGPS only uses these two, all others can be turned off
#define PMTK_SET_NMEA_OUTPUT_GSA "$PMTK314,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0,0*29\r\n" // turn on only GSA - GPS DOP and active satellites
#define PMTK_SET_NMEA_OUTPUT_GSV "$PMTK314,0,0,0,0,0,1,0,0,0,0,0,0,0,0,0,0,0,0,0*29\r\n" // turn on only GSV - GPS Satellites in view
#define PMTK_SET_NEMA_OUTPUT_ZDA "$PMTK314,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,1,0*29\r\n" // turn on only ZDA - Date & Time - UTC, day, month, year, and local time zone.
#define PMTK_SET_NEMA_OUTPUT_RMCGAAGSA "$PMTK314,0,1,0,1,1,5,0,0,0,0,0,0,0,0,0,0,0,0,0*2C\r\n" // RMC, GGA, GSA at 1Hz and GSV at 0.2Hz
#define PMTK_SET_NMEA_OUTPUT_ALLDATA "$PMTK314,1,1,1,1,1,1,0,0,0,0,0,0,0,0,0,0,0,0,0*28\r\n" // turn on ALL THE DATA for the LS20031- except ZDA
#define PMTK_SET_NMEA_OUTPUT_OFF "$PMTK314,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0*28\r\n" // turn off output
/* If the command is correct and executed, GPS module will output message "$PMTK001,314,3*36<CR><LF>" See Flag upabove */
#define PMTK_Q_RELEASE "$PMTK605*31\r\n" /* Query FW release information -- MTK-3301s send firmware release name and version - Note: not sure of accuracy of this information */
/* if the command is correct and executed, GPS module will output message example >> "$PMTK705,AXN_1.30,29BF,MC-1513,*0E"
Data field >> "$PMTK705,ReleaseStr,Mod eID,,*0E"
ReleaseSTr: Firmware release name & version
ModelID: Model ID
*/
/*
Demonstration sketch for Adafruit i2c/SPI LCD backpack
using MCP23008 I2C expander - NOTE at this time all LCD functions have been REM out
( http://www.ladyada.net/products/i2cspilcdbackpack/index.html )
This sketch prints "Hello World!" to the LCD
and shows the time.
The circuit:
* 5V to Arduino 5V pin
* GND to Arduino GND pin
* CLK to Analog #5
* DAT to Analog #4
*/
// include the library code:
#include <Wire.h>
//#include <LiquidTWI.h>
// Connect via i2c, default address #0 (A0-A2 not jumpered)
// LiquidTWI lcd(0);
#include <TinyGPS.h>
/* This sample code demonstrates the normal use of a TinyGPS object.
It requires the use of SoftwareSerial, and assumes that you have a
57600-baud serial GPS device hooked up on pins 3(rx) and 4(tx).
*/
TinyGPS gps;
SoftwareSerial nss(rxPin, txPin);
static void gpsdump(TinyGPS &gps);
static bool feedgps();
static void print_float(float val, float invalid, int len, int prec);
static void print_int(unsigned long val, unsigned long invalid, int len);
static void print_date(TinyGPS &gps);
static void print_str(const char *str, int len);
void setup()
{
Serial.begin(115200);
nss.begin(57600); // LS20031 baud- 57600
while (!nss.available()){}
nss.print(PMTK_SET_NMEA_OUTPUT_RMCGGA); // $GPxxx Messages
nss.print(PMTK_SET_NMEA_UPDATE_1HZ); // messages 1 times a second
nss.print(PMTK_Q_RELEASE);
Serial.print("Testing TinyGPS library v. "); Serial.println(TinyGPS::library_version());
Serial.println("by Mikal Hart");
Serial.println();
Serial.print("Sizeof(gpsobject) = "); Serial.println(sizeof(TinyGPS));
Serial.println();
Serial.println("Sats HDOP Latitude Longitude Fix Date Time Date Alt Course Speed Card Distance Course Card Chars Sentences Checksum");
Serial.println(" (deg) (deg) Age Age (m) --- from GPS ---- ---- to London ---- RX RX Fail");
Serial.println("--------------------------------------------------------------------------------------------------------------------------------------");
// set up the LCD's number of rows and columns:
//lcd.begin(16, 2);
// Print a message to the LCD.
//lcd.print("hello, world!");
}
void loop()
{
// set the cursor to column 0, line 1
// (note: line 1 is the second row, since counting begins with 0):
// lcd.setCursor(0, 1);
bool newdata = false;
unsigned long start = millis();
// lcd.print(start/1000);
// Every second we print an update
while (millis() - start < 1000)
{
if (feedgps())
newdata = true;
}
gpsdump(gps);
//lcd.setBacklight(HIGH);
}
static void gpsdump(TinyGPS &gps)
{
float flat, flon;
unsigned long age, date, time, chars = 0;
unsigned short sentences = 0, failed = 0;
static const float LONDON_LAT = 51.508131, LONDON_LON = -0.128002;
Serial.print(" ");
print_int(gps.satellites(), TinyGPS::GPS_INVALID_SATELLITES, 5);
//lcd.setCursor(0, 2); lcd.print("Satellites: "); lcd.print(gps.satellites());lcd.print(".");
feedgps();
print_int(gps.hdop(), TinyGPS::GPS_INVALID_HDOP, 5);
gps.f_get_position(&flat, &flon, &age);
print_float(flat, TinyGPS::GPS_INVALID_F_ANGLE, 9, 5);
print_float(flon, TinyGPS::GPS_INVALID_F_ANGLE, 10, 5);
print_int(age, TinyGPS::GPS_INVALID_AGE, 5);
print_date(gps);
print_float(gps.f_altitude(), TinyGPS::GPS_INVALID_F_ALTITUDE, 8, 2);
print_float(gps.f_course(), TinyGPS::GPS_INVALID_F_ANGLE, 7, 2);
print_float(gps.f_speed_kmph(), TinyGPS::GPS_INVALID_F_SPEED, 6, 2);
print_str(gps.f_course() == TinyGPS::GPS_INVALID_F_ANGLE ? "*** " : TinyGPS::cardinal(gps.f_course()), 6);
print_int(flat == TinyGPS::GPS_INVALID_F_ANGLE ? 0UL : (unsigned long)TinyGPS::distance_between(flat, flon, LONDON_LAT, LONDON_LON) / 1000, 0xFFFFFFFF, 9);
print_float(flat == TinyGPS::GPS_INVALID_F_ANGLE ? 0.0 : TinyGPS::course_to(flat, flon, 51.508131, -0.128002), TinyGPS::GPS_INVALID_F_ANGLE, 7, 2);
print_str(flat == TinyGPS::GPS_INVALID_F_ANGLE ? "*** " : TinyGPS::cardinal(TinyGPS::course_to(flat, flon, LONDON_LAT, LONDON_LON)), 6);
gps.stats(&chars, &sentences, &failed);
print_int(chars, 0xFFFFFFFF, 6);
print_int(sentences, 0xFFFFFFFF, 10);
print_int(failed, 0xFFFFFFFF, 9);
Serial.println();
}
static void print_int(unsigned long val, unsigned long invalid, int len)
{
char sz[32];
if (val == invalid)
strcpy(sz, "*******");
else
sprintf(sz, "%ld", val);
sz[len] = 0;
for (int i=strlen(sz); i<len; ++i)
sz[i] = ' ';
if (len > 0)
sz[len-1] = ' ';
Serial.print(sz); feedgps();
}
static void print_float(float val, float invalid, int len, int prec)
{
char sz[32];
if (val == invalid){
strcpy(sz, "*******");
sz[len] = 0;
if (len > 0)
sz[len-1] = ' ';
for (int i=7; i<len; ++i)
sz[i] = ' ';
Serial.print(sz);
}
else
{
Serial.print(val, prec);
int vi = abs((int)val);
int flen = prec + (val < 0.0 ? 2 : 1);
flen += vi >= 1000 ? 4 : vi >= 100 ? 3 : vi >= 10 ? 2 : 1;
for (int i=flen; i<len; ++i)
Serial.print(" ");
}
feedgps();
}
static void print_date(TinyGPS &gps)
{
int year;
byte month, day, hour, minute, second, hundredths;
unsigned long age;
gps.crack_datetime(&year, &month, &day, &hour, &minute, &second, &hundredths, &age);
if (age == TinyGPS::GPS_INVALID_AGE)
Serial.print("******* ******* ");
else
{
char sz[32];
sprintf(sz, "%02d/%02d/%02d %02d:%02d:%02d ",
month, day, year, hour, minute, second);
Serial.print(sz); //lcd.setCursor(0, 1); lcd.print(sz);
}
print_int(age, TinyGPS::GPS_INVALID_AGE, 5);
feedgps();
}
static void print_str(const char *str, int len)
{
int slen = strlen(str);
for (int i=0; i<len; ++i)
Serial.print(i<slen ? str[i] : ' ');
feedgps();
}
static bool feedgps()
{
while (nss.available())
{
if (gps.encode(nss.read()))
return true;
}
return false;
}