Hello,
I’m using a Heltec WiFi LoRa 32 (ESP32) board and I need some kind of multitasking as it has to monitor and write to a CAN bus, get GPS data, use Bluetooth LE and communicate with TTN.
I started with the ttn-otaa example and modified it.
I tried using freeRTOS tasks but weird things happen. The following code sends multiple join requests per second, I don’t understand why:
// LoRa libraries
#include <lmic.h>
#include <hal/hal.h>
#include <SPI.h>
//------------- LoRa TTN (OTAA) config -------------//
// Device EUI (lsb format)
static const u1_t PROGMEM DEVEUI[8] = { hidden };
void os_getDevEui (u1_t* buf) {
memcpy_P(buf, DEVEUI, 8);
}
// Application EUI (lsb format)
static const u1_t PROGMEM APPEUI[8] = { hidden };
void os_getArtEui (u1_t* buf) {
memcpy_P(buf, APPEUI, 8);
}
// App key (msb format)
static const u1_t PROGMEM APPKEY[16] = { hidden };
void os_getDevKey (u1_t* buf) {
memcpy_P(buf, APPKEY, 16);
}
// Pin mapping
const lmic_pinmap lmic_pins = {
.nss = 18,
.rxtx = LMIC_UNUSED_PIN,
.rst = 14,
.dio = {26, 33, 32},
};
// Data to be sent via LoRa and interval
static uint8_t mydata[] = "C2";
static osjob_t sendjob;
const unsigned TX_INTERVAL = 120; // seconds
void onEvent (ev_t ev) {
switch(ev) {
case EV_TXCOMPLETE:
//Serial.println(F("EV_TXCOMPLETE (includes waiting for RX windows)"));
// Schedule next transmission
os_setTimedCallback(&sendjob, os_getTime()+sec2osticks(TX_INTERVAL), do_send);
break;
}
}
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.
LMIC_setTxData2(1, mydata, sizeof(mydata)-1, 0);
//Serial.println(F("Packet queued"));
}
// Next TX is scheduled after TX_COMPLETE event.
}
void setup() {
xTaskCreate(
ttnTask, /* Task function. */
"TTN Task", /* name of task. */
4096, /* Stack size of task */
NULL, /* parameter of the task */
1, /* priority of the task */
NULL); /* Task handle to keep track of created task */
}
void loop() {
}
void ttnTask( void * parameter ){
// LMIC init
os_init();
// Reset the MAC state. Session and pending data transfers will be discarded.
LMIC_reset();
// Start job (sending automatically starts OTAA too)
do_send(&sendjob);
for (;;) {
os_runloop_once();
}
}
I also tried not using a FreeRTOS task. The ttn-otaa example works like this. But as soon as the arduino loop() function slows down (e.g. by updating the OLED display) the device cannot join the network (the join request is sent but no response received). I then tested with delay().
This works (device joins and payload is displayed on the TTN console):
void loop() {
delay(1);
os_runloop_once();
}
This does not work correctly (join request displayed on the TTN console but no message with payload). It might work after about 10 join requests:
void loop() {
delay(10);
os_runloop_once();
}
What is the proper approach I should use?
How have you integrated LMIC in your code so the arduino can do other things than only communicate with TTN?
Thanks !
Ben