Hello,
I am trying to make a small lora gps tracker using the adafruit feather m0 rfm915. I have the following code, which works and sends what it should, but transmission runs only once (see serial monitor at the bottom), not in a loop at specified interval. I need to make TX send fom 30 to 30 seconds. Any ideea what i am doing wrong? Thanks in advance.
#include <lmic.h>
#include <hal/hal.h>
#include <SPI.h>
#include <TinyGPS++.h>
osjob_t sendTTNjob;
const unsigned long TX_INTERVAL = 30;
TinyGPSPlus gps;
const lmic_pinmap lmic_pins = {
.nss = 8,
.rxtx = LMIC_UNUSED_PIN,
.rst = 4,
.dio = {3, 6, LMIC_UNUSED_PIN},
.rxtx_rx_active = 0,
.rssi_cal = 8, // LBT cal for the Adafruit Feather M0 LoRa, in dB
.spi_freq = 8000000,
};
// This EUI must be in little-endian format, so least-significant-byte
// first. When copying an EUI from ttnctl output, this means to reverse
// the bytes. For TTN issued EUIs the last bytes should be 0xD5, 0xB3,
// 0x70.
static const u1_t PROGMEM APPEUI[8]={ };
void os_getArtEui (u1_t* buf) { memcpy_P(buf, APPEUI, 8);}
// This should also be in little endian format, see above.
static const u1_t PROGMEM DEVEUI[8]={ };
void os_getDevEui (u1_t* buf) { memcpy_P(buf, DEVEUI, 8);}
// This key should be in big endian format (or, since it is not really a
// number but a block of memory, endianness does not really apply). In
// practice, a key taken from ttnctl can be copied as-is.
// The key shown here is the semtech default key.
static const u1_t PROGMEM APPKEY[16] = {};
void os_getDevKey (u1_t* buf) { memcpy_P(buf, APPKEY, 16);}
uint8_t coords[9];
uint32_t LatitudeBinary, LongitudeBinary;
uint16_t altitudeGps;
uint8_t hdopGps;
static osjob_t sendjob;
void get_coords () {
for (unsigned long start = millis(); millis() - start < 1000;) {
while (Serial1.available()) {
char c = Serial1.read();
Serial.write(c);
gps.encode(c);
}
}
if (gps.location.isValid()) {
LatitudeBinary = ((gps.location.lat() + 90) / 180.0) * 16777215;
LongitudeBinary = ((gps.location.lng() + 180) / 360.0) * 16777215;
coords[0] = ( LatitudeBinary >> 16 ) & 0xFF;
coords[1] = ( LatitudeBinary >> 8 ) & 0xFF;
coords[2] = LatitudeBinary & 0xFF;
coords[3] = ( LongitudeBinary >> 16 ) & 0xFF;
coords[4] = ( LongitudeBinary >> 8 ) & 0xFF;
coords[5] = LongitudeBinary & 0xFF;
altitudeGps = gps.altitude.meters();
coords[6] = ( altitudeGps >> 8 ) & 0xFF;
coords[7] = altitudeGps & 0xFF;
hdopGps = gps.hdop.value() / 10;
coords[8] = hdopGps & 0xFF;
}
}
void do_send(osjob_t* j) {
// Check if there is not a current TX/RX job running
if (LMIC.opmode & OP_TXRXPEND) {
Serial.println(F("OP_TXRXPEND, not sending"));
} else {
// Prepare upstream data transmission at the next possible time.
get_coords();
LMIC_setTxData2(1, (uint8_t*) coords, sizeof(coords), 0);
Serial.println(F("Packet queued"));
}
// Next TX is scheduled after TX_COMPLETE event.
}
void onEvent (ev_t ev) {
Serial.print(os_getTime());
Serial.print(": ");
switch (ev) {
case EV_SCAN_TIMEOUT:
Serial.println(F("EV_SCAN_TIMEOUT"));
break;
case EV_BEACON_FOUND:
Serial.println(F("EV_BEACON_FOUND"));
break;
case EV_BEACON_MISSED:
Serial.println(F("EV_BEACON_MISSED"));
break;
case EV_BEACON_TRACKED:
Serial.println(F("EV_BEACON_TRACKED"));
break;
case EV_JOINING:
Serial.println(F("EV_JOINING"));
break;
case EV_JOINED:
Serial.println(F("EV_JOINED"));
// Start sending data to TTN
os_setCallback(&sendTTNjob, do_send);
LMIC_setLinkCheckMode(0);
break;
case EV_JOIN_FAILED:
Serial.println(F("EV_JOIN_FAILED"));
break;
case EV_REJOIN_FAILED:
Serial.println(F("EV_REJOIN_FAILED"));
break;
case EV_TXCOMPLETE:
Serial.println(F("EV_TXCOMPLETE (includes waiting for RX windows)"));
digitalWrite(LED_BUILTIN, LOW);
if (LMIC.txrxFlags & TXRX_ACK)
Serial.println(F("Received ack"));
if (LMIC.dataLen) {
Serial.println(F("Received "));
Serial.println(LMIC.dataLen);
Serial.println(F(" bytes of payload"));
}
os_setTimedCallback(&sendTTNjob, os_getTime()+sec2osticks(TX_INTERVAL), do_send);
break;
case EV_LOST_TSYNC:
Serial.println(F("EV_LOST_TSYNC"));
break;
case EV_RESET:
Serial.println(F("EV_RESET"));
break;
case EV_RXCOMPLETE:
// data received in ping slot
Serial.println(F("EV_RXCOMPLETE"));
break;
case EV_LINK_DEAD:
Serial.println(F("EV_LINK_DEAD"));
break;
case EV_LINK_ALIVE:
Serial.println(F("EV_LINK_ALIVE"));
break;
case EV_TXSTART:
Serial.println(F("EV_TXSTART"));
break;
default:
Serial.println(F("Unknown event"));
break;
}
}
void setup()
{
Serial.begin(115200);
Serial.println(F("Starting"));
Serial1.begin(9600);
delay(5000);
Serial1.print("$PMTK301,2*2E\r\n"); // Select SBAS as DGPS source (RTCM)
Serial1.print("$PMTK313,1*2E\r\n"); // Enable to search a SBAS satellite
Serial1.print("$PMTK513,1*28\r\n");
// LMIC init
os_init();
// Reset the MAC state. Session and pending data transfers will be discarded.
LMIC_reset();
LMIC_setClockError(MAX_CLOCK_ERROR * 5 / 100);
LMIC_setLinkCheckMode(0);
LMIC_setDrTxpow(DR_SF7,14);
LMIC_setAdrMode(0);
do_send(&sendTTNjob);
}
void loop() {
os_runloop_once();
}
And the serial monitor output:
07:37:59.860 -> $GPGSV,3,1,11,02,33,049,15,05,24,105,,11,20,044,,12,25,121,*73
07:37:59.907 -> $GPGSV,3,2,11,18,34,199,,20,25,067,,22,00,256,,25,66,125,*73
07:38:00.000 -> $GPGSV,3,3,11,26,16,306,17,29,76,321,,31,42,283,*4E
07:38:00.046 -> $GPGLL,,,,,043757.00,V,N*48
07:38:00.140 -> Packet queued
07:38:00.140 -> 376205: EV_JOINING
07:38:08.020 -> 866599: EV_TXSTART
07:38:13.124 -> 1187829: EV_JOINED
07:38:13.124 -> 1188012: EV_TXSTART
07:38:13.124 -> OP_TXRXPEND, not sending
07:38:14.262 -> 1257189: EV_TXCOMPLETE (includes waiting for RX windows)
07:38:18.782 -> 1540938: EV_TXSTART