Skip to content

Instantly share code, notes, and snippets.

@nobodyguy
Last active September 21, 2022 03:13
Show Gist options
  • Save nobodyguy/7920482dd00f300b973126f9d7188db4 to your computer and use it in GitHub Desktop.
Save nobodyguy/7920482dd00f300b973126f9d7188db4 to your computer and use it in GitHub Desktop.
GpsLoRaWANTracker using Arduino, RN2483 and L86/neo-m8n GPS module
#include <TinyGPS++.h>
#include <SoftwareSerial.h>
#include <avr/sleep.h>
#include <avr/power.h>
// ----------------------------------------------
// DEFINES
// ----------------------------------------------
#define rxGpsPin 10
#define txGpsPin 11
#define ledPin 6
#define loraResetPin 4
#define loraTxPin 8
#define loraRxPin 7
#define wakePin 2
#define sleepTime 60000 // 1 minute
#define minSatelites 8
const String devaddr = "XXXXXXXX";
const String appskey = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
const String nwkskey = "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX";
// ----------------------------------------------
// DEBUG TOOLS
// ----------------------------------------------
#define DEBUG
#ifdef DEBUG
void trace(String str) {
Serial.println(str);
}
#else
#define trace(x)
#endif
// ----------------------------------------------
// GLOBALS
// ----------------------------------------------
String str;
SoftwareSerial gpsSerial = SoftwareSerial(rxGpsPin, txGpsPin);
SoftwareSerial loraSerial = SoftwareSerial(loraRxPin, loraTxPin);
TinyGPSPlus gps;
// ----------------------------------------------
// SLEEP FUNCTIONS
// ----------------------------------------------
void wakeUpArduino(void)
{
/* This will bring us back from sleep. */
/* We detach the interrupt to stop it from
* continuously firing while the interrupt pin
* is low.
*/
detachInterrupt(0);
}
void sleepArduino(void)
{
/* Setup pin2 as an interrupt and attach handler. */
attachInterrupt(0, wakeUpArduino, CHANGE);
delay(100);
set_sleep_mode(SLEEP_MODE_PWR_DOWN);
sleep_enable();
sleep_mode();
/* The program will continue from here. */
/* First thing to do is disable sleep. */
sleep_disable();
}
// ----------------------------------------------
// SETUP
// ----------------------------------------------
void setup() {
// put your setup code here, to run once:
#ifdef DEBUG
Serial.begin(9600);
while (!Serial);
#endif
loraSerial.begin(57600);
while (!loraSerial);
//pinMode(rxGpsPin, INPUT);
//pinMode(txGpsPin, OUTPUT);
gpsSerial.begin(9600);
pinMode(wakePin, INPUT);
pinMode(ledPin, OUTPUT);
digitalWrite(ledPin, HIGH);
// reset the module
pinMode(loraResetPin, OUTPUT);
digitalWrite(loraResetPin, LOW);
delay(500);
digitalWrite(loraResetPin, HIGH);
delay(2000);
loraSerial.setTimeout(50000);
loraSerial.listen();
trace("reset");
//str = loraSerial.readStringUntil('\n');
//trace(str);
trace("init");
loraSerial.println("mac set devaddr " + devaddr);
str = loraSerial.readStringUntil('\n');
trace(str);
loraSerial.println("mac set appskey " + appskey);
str = loraSerial.readStringUntil('\n');
trace(str);
loraSerial.println("mac set nwkskey " + nwkskey);
str = loraSerial.readStringUntil('\n');
trace(str);
//loraSerial.println("mac set dr 5");
//str = loraSerial.readStringUntil('\n');
//trace(str);
loraSerial.println("mac save");
delay(2000);
str = loraSerial.readStringUntil('\n');
trace(str);
loraSerial.println("mac join abp");
delay(2000);
str = loraSerial.readStringUntil('\n');
trace(str);
str = loraSerial.readStringUntil('\n');
trace(str);
digitalWrite(ledPin, LOW);
gpsSerial.listen();
trace("GPS listening...");
}
double lat;
double lng;
char latBuffer[20];
char lngBuffer[20];
char payload[100];
// ----------------------------------------------
// MAIN LOOP
// ----------------------------------------------
void loop() {
while (gpsSerial.available())
{
if (gps.encode(gpsSerial.read()))
{
int satellites = gps.satellites.value();
//Serial.print(satellites);
if (gps.satellites.isValid() && (satellites >= minSatelites) && ((gps.location.isValid() && gps.location.age() < 2000)) && (gps.location.lat() > 0) && (gps.location.lng() > 0)) {
digitalWrite(ledPin, HIGH);
lat = gps.location.lat();
lng = gps.location.lng();
dtostrf(lat, 10, 8, latBuffer);
dtostrf(lng, 10, 8, lngBuffer);
sprintf(payload, "%s,%s,%d", latBuffer, lngBuffer, satellites);
gpsSerial.end();
loraSerial.listen();
sendRadioMsgBuffer(payload);
str = loraSerial.readStringUntil('\n');
trace(str);
if (str.startsWith("ok"))
{
str = loraSerial.readStringUntil('\n');
trace(str);
if (str.startsWith("not_joi")) {
loraSerial.println("mac join abp");
delay(3000);
str = loraSerial.readStringUntil('\n');
str = loraSerial.readStringUntil('\n');
trace(str);
if (str.startsWith("acc")) {
sendRadioMsgBuffer(payload);
str = loraSerial.readStringUntil('\n');
trace(str);
}
} else if (!str.startsWith("mac_tx_ok") && !str.startsWith("mac_rx")) {
errorLoop();
}
}
else
{
errorLoop();
}
digitalWrite(ledPin, LOW);
loraSerial.print("sys sleep ");
loraSerial.println(sleepTime);
delay(100);
trace("Sleeping...");
sleepArduino(); // put arduino into sleep - it will be woken up by lora module
gpsSerial.begin(9600);
gpsSerial.listen();
}
}
}
}
// ----------------------------------------------
// RADIO FUNCTIONS
// ----------------------------------------------
void sendRadioMsgBuffer(char* msg)
{
size_t len = strlen(msg);
loraSerial.print("mac tx cnf 1 ");
for (int i = 0; i < len; i++) {
loraSerial.print(msg[i], HEX);
}
loraSerial.println();
Serial.println("Message was sent");
}
void sendRadioMsg(String msg)
{
char charBuf[200];
msg.toCharArray(charBuf, 200);
sendRadioMsgBuffer(charBuf);
}
void errorLoop()
{
while (true)
{
digitalWrite(ledPin, HIGH);
delay(1000);
digitalWrite(ledPin, LOW);
delay(1000);
}
}
Copy link

ghost commented Mar 17, 2017

Mine is not so different. I also want to make everything small as possible to be able to put it in everything.
(Funny idea to track an animal, maybe i could figure out where my cat goes in the night Oo)

But my main goal is to build dropable sensors to meassure tide information on lakes, temp, salt and water height.
Im really interessted in your web interface! My current progress is just to log the positions to a .gpx file... (With horrible bugs, but you cant expect from a E-ing high quality java code, but im future using aprs solves all my problems because then im using excisting APRS software)

But if we implement APRS we could use Software like SARTrack to collect gps location information, weather, etc. Pls check out http://www.cbaprs.de/

You can simply push data to cbaprs using telnet. Im trying to implement telnet in this project:
https://github.com/CongducPham/LowCostLoRaGw

I think APRS is excactly what we both want.

@Jeannotisintheplace
Copy link

Interesting (and lowtech) project @nobodyguy

Would you be like sharing the circuit connections between board,gps and RNJ2483 as well by any chance?
(I would love to try to replicate to train on ARDUINO).

@nobodyguy
Copy link
Author

nobodyguy commented Jun 15, 2021

Interesting (and lowtech) project @nobodyguy

Would you be like sharing the circuit connections between board,gps and RNJ2483 as well by any chance?
(I would love to try to replicate to train on ARDUINO).

Bonjour Jean, I don't really have the project assembled anymore, but I'm sure it was heavily inspired by these resources: https://www.disk91.com/2016/technology/internet-of-things-technology/simple-lora-gps-tracker-based-on-rn2483-and-l80/
https://github.com/hidnseek/hidnseek
https://github.com/ttnmapper/ttntrackernode

@Jeannotisintheplace
Copy link

Děkuji !

I start reading those links with much interest.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment