Hello all.
I just wanted to know if there is anybody out there that can help me a bit, with polishing my code.
I started a project after a lot of research to create a GPS logger with an LCD screen. I want to use this device to monitor the speed in my classic car. At the same time it would be nice to plot a track. After a lot of work I have finally got my Arduino gps logger working on my own. However the code might not be the most optimal. And with turning on and of of the arduino it starts logging in the middle of the previous (broken) line in the file on the SD card.
The hardware:
- Arduino Uno
- GPS logger board on basis of the U-Blox neo 6m with an SD card reader from ELECROW.
- Blue LCD screen 16x2 with I2C backpack
- perforated prototyping board to attach everything to.
Goals:
Display speed
Display heading
Display logging status
Display voltage of a carsensor
Log beginning of track
log latitude
Log longitude
log course
log speed
log date
log time
here is my code:
#include <SoftwareSerial.h>
#include <TinyGPS.h>
#include <LiquidCrystal_I2C.h> // more info: http://arduino-info.wikispaces.com/LCD-Blue-I2C
#include <SD.h>
#include <SPI.h>
// set up variables using the SD utility library functions:
Sd2Card card;
TinyGPS gps;
SoftwareSerial ss(3, 2); //RX, TX
LiquidCrystal_I2C lcd(0x27, 2, 1, 0, 4, 5, 6, 7, 3, POSITIVE); // Set the LCD I2C address
File mySensorData; //Data object you will write your sesnor data to
const int chipSelect = 10;
int temp = 80;
int stat;
unsigned long pos;
String newtrack = "1";
String filename = "NMEA.txt";
static void smartdelay(unsigned long ms);
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);
static void log_float(float val, float invalid, int len, int prec);
void setup()
{
pinMode(chipSelect, OUTPUT); //Must declare 10 an output and reserve it to keep SD card happy
if (!card.init(SPI_HALF_SPEED, chipSelect)) {
stat = 0;
} else {
stat = 1;
}
SD.begin(chipSelect); //Initialize the SD card reader
Serial.begin(115200);
lcd.begin(20,4); // initialize the lcd for 20 chars 4 lines and turn on backlight
lcd.setCursor(0,0);
lcd.write("GPS SYSTEM START");
smartdelay(1000);
lcd.clear();
lcd.setCursor(4,0);
lcd.write("Kmh");
lcd.setCursor(4,1);
lcd.write("DegC");
lcd.setCursor(8,0);
lcd.write("H:");
lcd.setCursor(10,1);
lcd.write("LoG:");
ss.begin(9600);
}
void loop()
{
float flat, flon;
unsigned long age, date, time, chars = 0;
gps.f_get_position(&flat, &flon, &age);
log_string(gps, "T"); //print normal characters and send gps date as test.
log_string(gps, newtrack); //print if track begins
log_float(flat, TinyGPS::GPS_INVALID_F_ANGLE, 10, 6);
log_float(flon, TinyGPS::GPS_INVALID_F_ANGLE, 11, 6);
log_float(gps.f_course(), TinyGPS::GPS_INVALID_F_ANGLE, 7, 2);
log_float(gps.f_speed_kmph(), TinyGPS::GPS_INVALID_F_SPEED, 6, 2);
log_date(gps);
print_spd(gps.f_speed_kmph(), TinyGPS::GPS_INVALID_F_SPEED, 3, 3);
print_head(gps.f_course(), TinyGPS::GPS_INVALID_F_ANGLE, 3, 0, 13);
print_temp(temp, 1);
print_log(gps.satellites(), TinyGPS::GPS_INVALID_SATELLITES, 1, 1, 15);
smartdelay(1000);
}
static void smartdelay(unsigned long ms)
{
unsigned long start = millis();
do
{
while (ss.available())
gps.encode(ss.read());
} while (millis() - start < ms);
}
static void print_spd(float val, float invalid, int len, int prec)
{
if (val == invalid)
{
lcd.setCursor(0,0);
while (len-- > 0)
lcd.write('*');
}
else
{
lcd.setCursor(0,0);
while (len-- > 0)
lcd.write(' ');
lcd.setCursor(0,0);
char buf [3];
dtostrf(val,3,0,buf);
//sprintf(buf, "%f", val);
lcd.write(buf);
}
smartdelay(0);
}
static void print_head(float val, float invalid, int len, int prec, int pos)
{
if (val == invalid)
{
lcd.setCursor(pos,0);
while (len-- > 0)
lcd.write('*');
}
else
{
lcd.setCursor(pos,0);
while (len-- > 0)
lcd.write(' ');
lcd.setCursor(pos,0);
char buf [3];
dtostrf(val,len,prec,buf);
lcd.write(buf);
int iDeg = int(val);
int idegpos;
idegpos = pos - 3;
lcd.setCursor(idegpos ,0);
lcd.write(" ");
lcd.setCursor(idegpos ,0);
if (iDeg > 68 && iDeg < 112) {
lcd.write("E");
}
if (iDeg > 23 && iDeg < 67) {
lcd.write("NE");
}
if (iDeg > 338 && iDeg < 22) {
lcd.write("N");
}
if (iDeg > 293 && iDeg < 337) {
lcd.write("NW");
}
if (iDeg > 248 && iDeg < 292) {
lcd.write("W");
}
if (iDeg > 202 && iDeg < 247) {
lcd.write("SW");
}
if (iDeg > 158 && iDeg < 201) {
lcd.write("S");
}
if (iDeg > 113 && iDeg < 157) {
lcd.write("SE");
}
}
smartdelay(0);
}
static void print_log(float val, float invalid, int len, int prec, int pos)
{
if (stat == 0)
{
lcd.setCursor(pos,1);
while (len-- > 0)
lcd.write('C');
}
else
{
if (val == invalid)
{
lcd.setCursor(pos,1);
while (len-- > 0)
lcd.write(' ');
lcd.setCursor(pos,1);
lcd.write("S");
}
else
{ lcd.setCursor(pos,1);
while (len-- > 0)
lcd.write(' ');
lcd.setCursor(pos,1);
lcd.write("A");
}
}
smartdelay(0);
}
static void print_temp(int t, int pos)
{
lcd.setCursor(pos,1);
lcd.write(" ");
lcd.setCursor(pos,1);
String tmp = String(t);
lcd.write("80");
smartdelay(0);
}
static void log_float(float val, float invalid, int len, int prec)
{
mySensorData = SD.open(filename, FILE_WRITE); //Open file on SD card for writing
if (val != invalid)
{
char buf [len];
dtostrf(val,len,prec,buf);
// cardbuffer += buf;
mySensorData.print(buf); //Write buffer to SD card
mySensorData.print(", ");
// Serial.print(buf);
}
mySensorData.close(); //Close the file
smartdelay(0);
}
static void log_date(TinyGPS &gps)
{
mySensorData = SD.open(filename, FILE_WRITE); //Open file on SD card for writing
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)
{
char sz[32];
sprintf(sz, "%02d/%02d/%02d, %02d:%02d:%02d ",
month, day, year, hour, minute, second);
// cardbuffer += sz;
mySensorData.print(sz);
mySensorData.println("");
// Serial.print(sz);
}
// log_int(age, TinyGPS::GPS_INVALID_AGE, 5);
mySensorData.close(); //Close the file
smartdelay(0);
}
static void log_string(TinyGPS &gps, String text)
{
int year;
byte month, day, hour, minute, second, hundredths;
unsigned long age;
gps.crack_datetime(&year, &month, &day, &hour, &minute, &second, &hundredths, &age);
mySensorData = SD.open(filename, FILE_WRITE); //Open file on SD card for writing
if (age != TinyGPS::GPS_INVALID_AGE)
{
mySensorData.print(text);
mySensorData.print(",");
if (text == "1")
{
newtrack = "0";
}
}
mySensorData.close(); //Close the file
smartdelay(0);
}
Thanks in advance
-Hop