Arduino sketch to provide a node on a GPSnet broadcast network to communicate GPS positions of all nodes throughout the network. Uses RF22 radios to preiodically broadcast GPS data to nearby nodes, who in turn broadcast to nodes near them etc.
Includes serial GPS interface, RF22 radio interface and USB-serial interface for configuration and emitting position reports. Saves configuration to EEPROM You can use this with the PC based viewer program GPSNetViewer discussed in the main documentation.
#include <GPSNet.h>
#define HAVE_RF22
#define HAVE_GPS
#include <GPSNet.h>
#include <EEPROM.h>
#ifdef HAVE_RF22
#include <RF22.h>
#include <SPI.h>
#endif
#ifdef HAVE_GPS
#include <TinyGPS.h>
TinyGPS gps;
#ifdef SOFTWARE_SERIAL
#include <SoftwareSerial.h>
SoftwareSerial softwareserial(8, 9);
#define GPS_SERIAL softwareserial
#else // SOFTWARE_SERIAL
#define GPS_SERIAL Serial1 // Change the hardware port if you need
#endif // SOFTWARE_SERIAL
#endif // HAVE_GPS
boolean debugFlag = 0;
#ifdef HAVE_RF22
RF22 rf22;
#endif // HAVE_RF22
uint8_t radioChannel = 0;
uint8_t id[GPSNET_REPORT_ID_LEN] = "?????";
uint8_t updateInterval = 0;
{
if (debugFlag)
{
Serial.println("Transmit:");
printReport(report);
}
#ifdef HAVE_RF22
rf22.send((uint8_t*)report, sizeof(*report));
rf22.waitPacketSent();
#endif // HAVE_RF22
}
void setRadioChannel(uint8_t channel)
{
#ifdef HAVE_RF22
rf22.setFrequency(434.0 + 0.1 * radioChannel, 0.05);
#endif // HAVE_RF22
}
boolean loadConfigFromEeprom()
{
uint8_t eepromIndex = 0;
if ( EEPROM.read(eepromIndex++) == 'G'
&& EEPROM.read(eepromIndex++) == 'P'
&& EEPROM.read(eepromIndex++) == 'S'
&& EEPROM.read(eepromIndex++) == 'n'
&& EEPROM.read(eepromIndex++) == 'e'
&& EEPROM.read(eepromIndex++) == 't'
&& EEPROM.read(eepromIndex++) == '1'
)
{
uint8_t i;
for (i = 0; i < GPSNET_REPORT_ID_LEN; i++)
id[i] = EEPROM.read(eepromIndex++);
radioChannel = EEPROM.read(eepromIndex++);
return true;
}
else
return false;
}
boolean saveConfigToEeprom()
{
uint8_t eepromIndex = 0;
EEPROM.write(eepromIndex++, 'G');
EEPROM.write(eepromIndex++, 'P');
EEPROM.write(eepromIndex++, 'S');
EEPROM.write(eepromIndex++, 'n');
EEPROM.write(eepromIndex++, 'e');
EEPROM.write(eepromIndex++, 't');
EEPROM.write(eepromIndex++, '1');
uint8_t i;
for (i = 0; i < GPSNET_REPORT_ID_LEN; i++)
EEPROM.write(eepromIndex++, id[i]);
EEPROM.write(eepromIndex++, radioChannel);
return true;
}
void setup()
{
Serial.begin(115200);
if (!loadConfigFromEeprom())
Serial.println("Could not load valid config from EEPROM");
#ifdef HAVE_GPS
GPS_SERIAL.begin(4800);
#endif // HAVE_GPS
#ifdef HAVE_RF22
if (!rf22.init())
Serial.println("RF22 init failed");
#endif // HAVE_RF22
setRadioChannel(radioChannel);
#if 0
strcpy((
char*)report.
id,
" test2");
strcpy((
char*)report.
id,
" test3");
strcpy((
char*)report.
id,
" test4");
strcpy((
char*)report.
id,
" test5");
#endif
Serial.println("\nGPSNet");
}
unsigned long ddmmyy_to_yymmdd(unsigned long ddmmyy)
{
return (ddmmyy / 10000) + (((ddmmyy / 100) % 100) * 100) + ((ddmmyy % 100) * 10000);
}
unsigned long hhmmsscc_to_hhmmss(unsigned long hhmmsscc)
{
return hhmmsscc / 100;
}
void checkForGPSInput()
{
#ifdef HAVE_GPS
while (GPS_SERIAL.available())
{
char c = GPS_SERIAL.read();
if (gps.encode(c))
{
uint32_t date;
uint32_t time;
uint32_t age;
gps.get_datetime(&date, &time, &age);
if (date != TinyGPS::GPS_INVALID_DATE)
{
memcpy(report.
id,
id, GPSNET_REPORT_ID_LEN);
report.
date = ddmmyy_to_yymmdd(date);
report.
time = hhmmsscc_to_hhmmss(time);
report.
speed = gps.speed() / 100;
report.
course = gps.course() / 100;
if ( report.
latitude != TinyGPS::GPS_INVALID_ANGLE
&& report.
altitude != TinyGPS::GPS_INVALID_ALTITUDE)
{
{
if (debugFlag)
{
Serial.println("LocalGPS:");
printReport(&report);
}
lastReport = report;
}
}
}
}
}
#endif // HAVE_GPS
}
{
Serial.print((
char*)report->
id);
Serial.print(':');
Serial.print(report->
date);
Serial.print(':');
Serial.print(report->
time);
Serial.print(':');
Serial.print(':');
Serial.print(':');
Serial.print(':');
Serial.print(report->
speed);
Serial.print(':');
Serial.print(':');
Serial.print(report->
flags, HEX);
Serial.print(':');
Serial.print(report->
status, HEX);
Serial.print(':');
Serial.println(report->
hops);
}
void printReports()
{
Serial.print("Reports:");
Serial.println(numReports);
uint8_t i;
for (i = 0; i < numReports; i++)
{
}
}
void checkForLocalOutput()
{
static unsigned long lastOutputTime = 0;
if (updateInterval == 0)
return;
if (millis() > lastOutputTime + (updateInterval * 1000))
{
printReports();
lastOutputTime = millis();
}
}
void checkForReceivedMessages()
{
#ifdef HAVE_RF22
if (rf22.available())
{
uint8_t len = sizeof(report);
if (rf22.recv((uint8_t*)&report, &len))
{
if ( len == sizeof(report)
&& report.
magic == GPSNET_MAGIC_VERSION_1)
{
if (debugFlag)
{
Serial.println("Received:");
printReport(&report);
}
}
}
}
#endif // HAVE_RF22
}
void decodeConfigurationCommand(char* buf)
{
if (buf[0] == 'd')
{
debugFlag = ~debugFlag;
Serial.print("Debug:");
Serial.println(debugFlag ? "on" : "off");
}
else if (buf[0] == 'c')
{
radioChannel = atoi(&buf[1]);
setRadioChannel(radioChannel);
Serial.print("Channel:");
Serial.println(radioChannel);
}
else if (buf[0] == 'i')
{
strncpy((char*)id, &buf[1], GPSNET_REPORT_ID_LEN);
Serial.print("NodeID:");
Serial.println((char*)id);
}
else if (buf[0] == 's')
{
saveConfigToEeprom();
Serial.println("Saved to EEPROM");
}
else if (buf[0] == 'p')
{
Serial.print("NodeID:");
Serial.println((char*)id);
Serial.print("Channel:");
Serial.println(radioChannel);
}
else if (buf[0] == 'u')
{
updateInterval = atoi(&buf[1]);
Serial.print("UpdateInterval:");
Serial.println(updateInterval);
}
else if (buf[0] == 'l')
{
printReports();
}
}
void checkForConfigurationCommands()
{
static char buf[10] = { '\0' };
static uint8_t buflen = 0;
while (Serial.available())
{
char c = Serial.read();
if (c == '\n')
{
decodeConfigurationCommand(buf);
buflen = 0;
buf[0] = '\0';
}
else if (c == '\r')
{
}
else
{
if (buflen < sizeof(buf) - 1)
{
buf[buflen++] = c;
buf[buflen] = '\0';
}
}
}
}
void loop()
{
checkForGPSInput();
checkForLocalOutput();
checkForReceivedMessages();
checkForConfigurationCommands();
}