ropg / heltec_esp32_lora_v3

Proper working Arduino library for the Heltec ESP32 LoRa v3 board, as well as for Wireless Stick v3 and Wireless Stick Lite v3. Uses RadioLib
MIT License
330 stars 16 forks source link

Heltec Lora 32 (V3) #25

Closed johnp2605 closed 3 months ago

johnp2605 commented 4 months ago

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);
}
ropg commented 4 months ago

First comments:

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);
}
ropg commented 3 months ago

Please let me know if this works for you, if you can. That way I know I can close the issue.

johnp2605 commented 3 months ago

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.

ropg commented 3 months ago

Alright, then I’ll close it because the thing I posted works for me here. Strange though.