Skip to content

Instantly share code, notes, and snippets.

@Helios-vmg
Created February 5, 2017 17:42
Show Gist options
  • Save Helios-vmg/1d98f29b1979bd87ed2253c9c466ed9b to your computer and use it in GitHub Desktop.
Save Helios-vmg/1d98f29b1979bd87ed2253c9c466ed9b to your computer and use it in GitHub Desktop.
Arduino GPS
#include <SPI.h>
#include <SD.h>
#include <SoftwareSerial.h>
#include <EEPROM.h>
#include <Arduino.h> // for type definitions
int EEPROM_writeInt(int ee, int value){
byte *p = (byte *)(void *)&value;
unsigned i;
for (i = 0; i < sizeof(value); i++)
EEPROM.write(ee++, *p++);
return i;
}
int EEPROM_readInt(int ee){
int ret;
byte *p = (byte *)(void *)&ret;
unsigned i;
for (i = 0; i < sizeof(ret); i++)
*p++ = EEPROM.read(ee++);
return ret;
}
const int cs_sd = 10;
const int rx_gps = 3;
const int tx_gps = 2;
const int buf_size = 256;
byte buf[buf_size];
int buf_pos = 0;
bool ok = false;
SoftwareSerial gps(rx_gps, tx_gps);
File file;
//#define ENABLE_SERIAL_OUTPUT
const byte turn_off_GGA[] PROGMEM = { 0xB5, 0x62, 0x06, 0x01, 0x08, 0x00, 0xF0, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xFF, 0x23 };
const byte turn_off_GLL[] PROGMEM = { 0xB5, 0x62, 0x06, 0x01, 0x08, 0x00, 0xF0, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x2A };
const byte turn_off_GSA[] PROGMEM = { 0xB5, 0x62, 0x06, 0x01, 0x08, 0x00, 0xF0, 0x02, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x01, 0x31 };
const byte turn_off_GSV[] PROGMEM = { 0xB5, 0x62, 0x06, 0x01, 0x08, 0x00, 0xF0, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x38 };
const byte turn_off_RMC[] PROGMEM = { 0xB5, 0x62, 0x06, 0x01, 0x08, 0x00, 0xF0, 0x04, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x03, 0x3F };
const byte turn_off_VTG[] PROGMEM = { 0xB5, 0x62, 0x06, 0x01, 0x08, 0x00, 0xF0, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x04, 0x46 };
const byte turn_off_GRS[] PROGMEM = { 0xB5, 0x62, 0x06, 0x01, 0x08, 0x00, 0xF0, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x05, 0x4D };
const byte turn_off_GST[] PROGMEM = { 0xB5, 0x62, 0x06, 0x01, 0x08, 0x00, 0xF0, 0x07, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x06, 0x54 };
const byte turn_off_ZDA[] PROGMEM = { 0xB5, 0x62, 0x06, 0x01, 0x08, 0x00, 0xF0, 0x08, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x07, 0x5B };
const byte turn_off_GBS[] PROGMEM = { 0xB5, 0x62, 0x06, 0x01, 0x08, 0x00, 0xF0, 0x09, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x08, 0x62 };
const byte turn_off_DTM[] PROGMEM = { 0xB5, 0x62, 0x06, 0x01, 0x08, 0x00, 0xF0, 0x0A, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x09, 0x69 };
const byte turn_off_GNS[] PROGMEM = { 0xB5, 0x62, 0x06, 0x01, 0x08, 0x00, 0xF0, 0x0D, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0C, 0x7E };
const byte turn_off_THS[] PROGMEM = { 0xB5, 0x62, 0x06, 0x01, 0x08, 0x00, 0xF0, 0x0E, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0D, 0x85 };
const byte turn_off_VLW[] PROGMEM = { 0xB5, 0x62, 0x06, 0x01, 0x08, 0x00, 0xF0, 0x0F, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x0E, 0x8C };
const byte turn_on_GGA[] PROGMEM = { 0xB5, 0x62, 0x06, 0x01, 0x08, 0x00, 0xF0, 0x00, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x04, 0x37 };
const byte turn_on_ZDA[] PROGMEM = { 0xB5, 0x62, 0x06, 0x01, 0x08, 0x00, 0xF0, 0x08, 0x01, 0x01, 0x01, 0x01, 0x01, 0x00, 0x0C, 0x6F };
const byte set_positioning_rate_4_Hz[] PROGMEM = { 0xB5, 0x62, 0x06, 0x08, 0x06, 0x00, 0xF4, 0x01, 0x01, 0x00, 0x01, 0x00, 0x0B, 0x77 };
void send_array(const byte *begin, const byte *end){
int i = 0;
for (; begin != end; begin++)
gps.write(*begin);
gps.println();
gps.flush();
}
void calc_checksum(byte *dst, const byte *begin, const byte *end){
byte a = 0,
b = 0;
for (; begin != end; begin++){
a += *begin;
b += a;
}
dst[0] = a;
dst[1] = b;
}
int get_ack(const byte *msg_id){
unsigned long ack_start = millis();
const unsigned long ack_timeout = 3000;
byte ack_packet[10] = {0xB5, 0x62, 0x05, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00};
int i = 0;
while (i < 10){
if (gps.available()){
byte incoming_char = gps.read();
if (incoming_char == ack_packet[i]){
i++;
continue;
}else if (i > 2){
ack_packet[i] = incoming_char;
i++;
continue;
}
}
if (millis() > ack_start + ack_timeout)
return 100 + i;
}
if (ack_packet[3] == 0x00 || msg_id[0] != ack_packet[6] || msg_id[1] != ack_packet[7])
return 2;
byte checksum[2];
calc_checksum(checksum, ack_packet + 2, ack_packet + 8);
if (checksum[0] == ack_packet[8] && checksum[1] == ack_packet[9])
return 0;
delay(1000);
return 3;
}
int send_array_and_confirm(const byte *begin, const byte *end){
send_array(begin, end);
return get_ack(begin + 2);
}
void SEND_ARRAY2(const byte *begin, const byte *end){
for (byte i = 0; send_array_and_confirm(begin, end) && i < 3; i++);
}
#define SEND_ARRAY(x){ \
byte temp[sizeof(x)]; \
for (int i = 0; i < sizeof(x); i++) \
temp[i] = pgm_read_byte(x + i); \
SEND_ARRAY2(temp, temp + sizeof(x)); \
}
void initial_configuration(){
SEND_ARRAY(turn_off_GGA);
SEND_ARRAY(turn_off_GLL);
SEND_ARRAY(turn_off_GSA);
SEND_ARRAY(turn_off_GSV);
SEND_ARRAY(turn_off_RMC);
SEND_ARRAY(turn_off_VTG);
SEND_ARRAY(turn_off_GRS);
SEND_ARRAY(turn_off_GST);
SEND_ARRAY(turn_off_GBS);
SEND_ARRAY(turn_off_DTM);
SEND_ARRAY(turn_off_GNS);
SEND_ARRAY(turn_off_THS);
SEND_ARRAY(turn_off_VLW);
SEND_ARRAY(turn_on_ZDA);
SEND_ARRAY(set_positioning_rate_4_Hz);
}
unsigned long setup_return_time;
const unsigned long wait_time = 2000;
bool fully_configured = 0;
void final_configuration(){
if (fully_configured || millis() < setup_return_time + wait_time)
return;
SEND_ARRAY(turn_on_GGA);
SEND_ARRAY(turn_off_ZDA);
fully_configured = 1;
}
void setup(){
pinMode(rx_gps, INPUT);
pinMode(tx_gps, OUTPUT);
pinMode(10, OUTPUT);
#ifdef ENABLE_SERIAL_OUTPUT
Serial.begin(115200);
Serial.print("Initializing SD card...");
#endif
if (!SD.begin(cs_sd)){
#ifdef ENABLE_SERIAL_OUTPUT
Serial.println("Card failed, or not present");
#endif
return;
}
ok = true;
gps.begin(9600);
initial_configuration();
int fileIndex = EEPROM_readInt(0);
EEPROM_writeInt(0, fileIndex + 1);
String filename = String(fileIndex) + ".txt";
#ifdef ENABLE_SERIAL_OUTPUT
Serial.println("OK!");
Serial.println("Using file " + filename);
#endif
file = SD.open(filename.c_str(), O_WRITE | O_CREAT);
setup_return_time = millis();
}
bool only_once = false;
const int counter_initial = 256;
int counter = counter_initial;
void loop(){
final_configuration();
if (!ok || !gps.available())
return;
byte b;
if (gps.overflow()){
file.write("\r\n");
#ifdef ENABLE_SERIAL_OUTPUT
Serial.write("\r\n");
#endif
}
while (gps.available()){
b = gps.read();
file.write(b);
#ifdef ENABLE_SERIAL_OUTPUT
Serial.write(b);
#endif
if (!--counter){
file.flush();
counter = counter_initial;
}
}
if (b == '\n'){
file.flush();
counter = counter_initial;
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment