Heltec Lora 32 (V3)
Closed this issue · 4 comments
I have an Heltec Lora board and want to sent a message to the KPN Things network. What is wrong I can't get it to work. I have tried lots of code, but there is no connection possible. When I take the example LoraWan from Heltec it can connect and sent, but the signal is not strong enough. I only want to sent one small message every hour.
I'am getting the following message:
07:35:52.536 -> Could not join network. We'll try again later.
07:35:52.536 -> Going to deep sleep now
07:35:52.536 -> Next TX in 900 s
The code I'am using is (the devEui, appEui and appKey is filled in with other values):
/**
*
* FOR THIS EXAMPLE TO WORK, YOU MUST INSTALL THE "LoRaWAN_ESP32" LIBRARY USING
* THE LIBRARY MANAGER IN THE ARDUINO IDE.
*
* This code will send a two-byte LoRaWAN message every 15 minutes. The first
* byte is a simple 8-bit counter, the second is the ESP32 chip temperature
* directly after waking up from its 15 minute sleep in degrees celsius + 100.
*
* If your NVS partition does not have stored TTN / LoRaWAN provisioning
* information in it yet, you will be prompted for them on the serial port and
* they will be stored for subsequent use.
*
* See https://github.com/ropg/LoRaWAN_ESP32
*/
#define MINIMUM_DELAY 900
#include <heltec_unofficial.h>
#include <LoRaWAN_ESP32.h>
LoRaWANNode* node;
RTC_DATA_ATTR uint8_t count = 0;
const char* band = "EU868";
/* OTAA parameters */
uint8_t devEui[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
uint8_t appEui[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
uint8_t appKey[] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
/* ABP parameters (if needed) */
uint8_t nwkSKey[] = { 0x15, 0xb1, 0xd0, 0xef, 0xa4, 0x63, 0xdf, 0xbe, 0x3d, 0x11, 0x18, 0x1e, 0x1e, 0xc7, 0xda, 0x85 };
uint8_t appSKey[] = { 0xd7, 0x2c, 0x78, 0x75, 0x8c, 0xdc, 0xca, 0xbf, 0x55, 0xee, 0x4a, 0x77, 0x8d, 0x16, 0xef, 0x67 };
uint32_t devAddr = ( uint32_t )0x007e6ae1;
void reverseArray(uint8_t *arr, size_t size) {
size_t i = 0;
size_t j = size - 1;
while (i < j) {
uint8_t temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
i++;
j--;
}
}
void setup() {
heltec_setup();
// Obtain directly after deep sleep
float temp = 27.0;
Serial.printf("Temperature: %.1f °C\n", temp);
// initialize radio
Serial.println("Radio init");
int16_t state = radio.begin();
if (state != RADIOLIB_ERR_NONE) {
Serial.println("Radio did not initialize. We'll try again later.");
goToSleep();
}
reverseArray(devEui, 8);
reverseArray(appEui, 8);
bool success = persist.provision(band, 0, *(uint64_t*)appEui, *(uint64_t*)devEui, (uint8_t*)appKey, (uint8_t*)nwkSKey);
if (success) {
Serial.println("Provisioning successful");
} else {
Serial.println("Provisioning failed");
}
node = persist.manage(&radio);
if (!node->isJoined()) {
Serial.println("Could not join network. We'll try again later.");
goToSleep();
}
// If we're still here, it means we joined, and we can send something
node->setDutyCycle(true, 1250);
uint8_t uplinkData[2];
uplinkData[0] = count++;
uplinkData[1] = temp + 100;
uint8_t downlinkData[256];
size_t lenDown = sizeof(downlinkData);
state = node->sendReceive(uplinkData, sizeof(uplinkData), 1, downlinkData, &lenDown);
if(state == RADIOLIB_ERR_NONE || state == RADIOLIB_ERR_RX_TIMEOUT) {
Serial.println("Message sent");
} else {
Serial.printf("sendReceive returned error %d, we'll try again later.\n", state);
}
goToSleep(); // Does not return, program starts over next round
}
void loop() {
// This is never called. There is no repetition: we always go back to
// deep sleep one way or the other at the end of setup()
}
void goToSleep() {
Serial.println("Going to deep sleep now");
persist.saveSession(node);
uint32_t interval = node->timeUntilUplink();
uint32_t delayMs = max(interval, (uint32_t)MINIMUM_DELAY * 1000);
Serial.printf("Next TX in %i s\n", delayMs/1000);
delay(100);
heltec_deep_sleep(delayMs/1000);
}
First comments:
- Why not directly define the EUIs as
uint64_t
as inuint64_t appEui = 0x0000000000000000
? That way, you could skip thereverseArray
thing and just giveappEui
topersist.provision
instead of*(uint64_t*)appEui
. - I haven't tested with ABP, merely with OTAA. My code only uses OTAA, so providing
nwkSKey
looks wrong.
Below is a tested example for using this library with statically compiled provisioning data. You have to get your own endpoint parameters, I deleted this endpoint after testing.
Note that while it can do so just fine, the true power of this library is of course not to use statically compiled values, but to use values entered by the user at runtime, either serially using the built-in dialog, from a web interface you make, or from somewhere else.
// Pause between sends in seconds, so this is every 15 minutes. (Delay will be
// longer if regulatory or TTN Fair Use Policy requires it.)
#define MINIMUM_DELAY 900
#include <heltec_unofficial.h>
#include <LoRaWAN_ESP32.h>
LoRaWANNode* node;
RTC_DATA_ATTR uint8_t count = 0;
const char* band = "EU868";
const uint8_t subband = 0;
const uint64_t joinEUI = 0x0000000000000000;
const uint64_t devEUI = 0x70B3D57ED00670C8;
const uint8_t appKey[] = { 0x4A, 0x2F, 0x86, 0x95, 0x40, 0x25, 0x7C, 0x96, 0xDE, 0xCE, 0x3E, 0x15, 0xBA, 0x4A, 0xF9, 0xD2 };
const uint8_t nwkKey[] = { 0xF4, 0xA8, 0x58, 0xAD, 0x9B, 0x80, 0xA6, 0x97, 0x15, 0x51, 0x75, 0x06, 0x4F, 0xD1, 0x9E, 0xA5 };
void setup() {
heltec_setup();
// Obtain directly after deep sleep
// May or may not reflect room temperature, sort of.
float temp = heltec_temperature();
Serial.printf("Temperature: %.2f °C\n", temp);
// Put the provisioning data in flash. Can do this every time: flash values
// are only ever written if they differ from what's already there.
persist.provision(band, subband, joinEUI, devEUI, appKey, nwkKey);
// initialize radio
Serial.println("Radio init");
int16_t state = radio.begin();
if (state != RADIOLIB_ERR_NONE) {
Serial.println("Radio did not initialize. We'll try again later.");
goToSleep(); // Does not return, program starts over after sleep
}
node = persist.manage(&radio);
if (!node->isJoined()) {
Serial.println("Could not join network. We'll try again later.");
goToSleep(); // Does not return, program starts over after sleep
}
// If we're still here, it means we joined, and we can send something
// Manages uplink intervals to the TTN Fair Use Policy
node->setDutyCycle(true, 1250);
uint8_t uplinkData[2];
uplinkData[0] = count++;
uplinkData[1] = temp + 100;
uint8_t downlinkData[256];
size_t lenDown = sizeof(downlinkData);
state = node->sendReceive(uplinkData, sizeof(uplinkData), 1, downlinkData, &lenDown);
if(state == RADIOLIB_ERR_NONE || state == RADIOLIB_ERR_RX_TIMEOUT) {
Serial.println("Message sent");
} else {
Serial.printf("sendReceive returned error %d, we'll try again later.\n", state);
}
goToSleep(); // Does not return, program starts over after sleep
}
void loop() {
// This is never called. There is no repetition: we always go back to
// deep sleep one way or the other at the end of setup()
}
void goToSleep() {
Serial.println("Going to deep sleep now");
// allows recall of the session after deepsleep
persist.saveSession(node);
// Calculate minimum duty cycle delay (per FUP & law!)
uint32_t interval = node->timeUntilUplink();
// And then pick it or our MINIMUM_DELAY, whichever is greater
uint32_t delayMs = max(interval, (uint32_t)MINIMUM_DELAY * 1000);
Serial.printf("Next TX in %i s\n", delayMs/1000);
delay(100); // So message prints
// And off to bed we go
heltec_deep_sleep(delayMs / 1000);
}
Please let me know if this works for you, if you can. That way I know I can close the issue.
Please let me know if this works for you, if you can. That way I know I can close the issue.
I could not get it to work and have switched to the library from Heltec. It works right now. Thanks for the help.
Alright, then I’ll close it because the thing I posted works for me here. Strange though.