Help With Heltec Wireless Stick V3 hello World

Hi everyone,

I’m new to PlatformIO and need some help getting started with the Heltec Wireless Stick V3. My goal is:

  1. Create a simple “Hello World” using the serial monitor to confirm the setup works.
  2. Use the RadioLib library: I’ve used this library successfully in Arduino IDE, but I can’t figure out how to set it up in PlatformIO.

What I’ve tried:

  • Basic setup in PlatformIO, but I’m unsure how to correctly configure this board.
  • Searching for RadioLib in PlatformIO, but it’s not working as it did in Arduino IDE.

What I need:

  • A guide to set up this board in PlatformIO from scratch.
  • Instructions to use RadioLib with this board in PlatformIO.

I don’t have much experience with PlatformIO, so any step-by-step advice would be greatly appreciated. Thanks in advance!

Create a new PlatformIO Project and choose the board “Heltec WiFi LoRa 32 (V3)

Add the following lines to your platformio.ini to install the RadioLib library:

lib_deps = 
  jgromes/RadioLib@^7.1.1

See

Please be more specific.

There is no difference on how to use the library on ArduinoIDE vs on PlatformIO. Your source code will be the same. See the examples

Thank you for your help, I achieve to Set a hello World with my Heltec Wireless Stick V3 and send some in LoRaWAN. I have two more questions, the first is why is the reason that using other board for the project in this case the Heltec WiFi LoRa 32 (V3) make works with the Wireless stick, I’m really curious about it.

My second question is about the code, I need to hear data that arrives in Serial1 pins 19 and 20 at any time, and then send it thought LoRaWAN. I’m not sure about what command is using to send the data in the example. This is the code that I’m using.

#include "config.h"
#include <RadioLib.h>
#include <Preferences.h>

Preferences store;
RTC_DATA_ATTR uint16_t bootCount = 0;
RTC_DATA_ATTR uint16_t bootCountSinceUnsuccessfulJoin = 0;
RTC_DATA_ATTR uint8_t LWsession[RADIOLIB_LORAWAN_SESSION_BUF_SIZE];

// Configuración de tiempos ajustables
const uint32_t rejoinIntervalSeconds = 5;  // Tiempo de reintento de unión en segundos
const uint32_t sendIntervalMillis = 10000; // Tiempo de envío de datos en milisegundos
bool sleepEnabled = true;                  // Controla si el dispositivo se duerme después de enviar
uint32_t sleepDurationSeconds = 10;        // Duración del sueño en segundos

void print_wakeup_reason()
{
  esp_sleep_wakeup_cause_t wakeup_reason = esp_sleep_get_wakeup_cause();
  if (wakeup_reason == ESP_SLEEP_WAKEUP_TIMER)
  {
    Serial.println(F("Wake from sleep"));
  }
  else
  {
    Serial.print(F("Wake not caused by deep sleep: "));
    Serial.println(wakeup_reason);
  }
  Serial.print(F("Boot count: "));
  Serial.println(++bootCount);
}

void printStoredNonces()
{
  uint8_t buffer[RADIOLIB_LORAWAN_NONCES_BUF_SIZE];
  store.getBytes("nonces", buffer, RADIOLIB_LORAWAN_NONCES_BUF_SIZE);
  Serial.println(F("Stored Nonces:"));
  for (size_t i = 0; i < RADIOLIB_LORAWAN_NONCES_BUF_SIZE; i++)
  {
    Serial.print(buffer[i], HEX);
    Serial.print(" ");
  }
  Serial.println();
}

void printStoredSession()
{
  Serial.println(F("Stored Session Buffer:"));
  for (size_t i = 0; i < RADIOLIB_LORAWAN_SESSION_BUF_SIZE; i++)
  {
    Serial.print(LWsession[i], HEX);
    Serial.print(" ");
  }
  Serial.println();
}

void gotoSleep(uint32_t seconds)
{
  Serial.print(F("Sleeping for "));
  Serial.print(seconds);
  Serial.println(F(" seconds\n"));

  esp_sleep_enable_timer_wakeup(seconds * 1000UL * 1000UL);
  Serial.flush();
  esp_deep_sleep_start();

  Serial.println(F("\n\n### Sleep failed, restarting ###\n"));
  delay(5000);
  ESP.restart();
}

int16_t lwActivate()
{
  int16_t state = RADIOLIB_ERR_UNKNOWN;

  node.beginOTAA(joinEUI, devEUI, nwkKey, appKey);

  Serial.println(F("Recalling LoRaWAN nonces & session"));
  store.begin("radiolib");

  if (store.isKey("nonces"))
  {
    uint8_t buffer[RADIOLIB_LORAWAN_NONCES_BUF_SIZE];
    store.getBytes("nonces", buffer, RADIOLIB_LORAWAN_NONCES_BUF_SIZE);
    state = node.setBufferNonces(buffer);
    debug(state != RADIOLIB_ERR_NONE, F("Restoring nonces buffer failed"), state, false);

    state = node.setBufferSession(LWsession);
    debug((state != RADIOLIB_ERR_NONE) && (bootCount > 1), F("Restoring session buffer failed"), state, false);

    if (state == RADIOLIB_ERR_NONE)
    {
      Serial.println(F("Succesfully restored session - now activating"));
      state = node.activateOTAA();
      if (state == RADIOLIB_LORAWAN_SESSION_RESTORED)
      {
        Serial.println(F("Session successfully restored. Current credentials:"));
        printStoredNonces();
        printStoredSession();
        store.end();
        return state;
      }
      else
      {
        Serial.println(F("Failed to activate restored session, retrying join."));
      }
    }
  }
  else
  {
    Serial.println(F("No Nonces saved - starting fresh."));
  }

  state = RADIOLIB_ERR_NETWORK_NOT_JOINED;
  while (state != RADIOLIB_LORAWAN_NEW_SESSION)
  {
    Serial.println(F("Join ('login') to the LoRaWAN Network"));
    state = node.activateOTAA();

    uint8_t buffer[RADIOLIB_LORAWAN_NONCES_BUF_SIZE];
    uint8_t *persist = node.getBufferNonces();
    memcpy(buffer, persist, RADIOLIB_LORAWAN_NONCES_BUF_SIZE);
    store.putBytes("nonces", buffer, RADIOLIB_LORAWAN_NONCES_BUF_SIZE);
    printStoredNonces();

    if (state != RADIOLIB_LORAWAN_NEW_SESSION)
    {
      Serial.print(F("Join failed: "));
      Serial.println(state);
      delay(rejoinIntervalSeconds * 1000);
    }
  }

  Serial.println(F("Joined"));
  bootCountSinceUnsuccessfulJoin = 0;
  delay(1000);
  store.end();
  return state;
}

void setup()
{
  Serial.begin(115200);
  while (!Serial)
    ;
  delay(2000);
  Serial.println(F("\nSetup"));
  print_wakeup_reason();

  int16_t state = radio.begin();
  debug(state != RADIOLIB_ERR_NONE, F("Initialize radio failed"), state, true);

  state = lwActivate();

  if (state == RADIOLIB_LORAWAN_NEW_SESSION || state == RADIOLIB_LORAWAN_SESSION_RESTORED)
  {
    uint8_t value1 = radio.random(100);
    uint16_t value2 = radio.random(2000);

    uint8_t uplinkPayload[3];
    uplinkPayload[0] = value1;
    uplinkPayload[1] = highByte(value2);
    uplinkPayload[2] = lowByte(value2);

    state = node.sendReceive(uplinkPayload, sizeof(uplinkPayload));
    debug((state < RADIOLIB_ERR_NONE) && (state != RADIOLIB_ERR_NONE), F("Error in sendReceive"), state, false);

    Serial.print(F("FCntUp: "));
    Serial.println(node.getFCntUp());

    uint8_t *persist = node.getBufferSession();
    memcpy(LWsession, persist, RADIOLIB_LORAWAN_SESSION_BUF_SIZE);
    printStoredSession();

    if (sleepEnabled)
    {
      gotoSleep(sleepDurationSeconds); // Dormir si está habilitado
    }
    else
    {
      Serial.println(F("Sleep disabled, staying awake."));
    }
  }
  else
  {
    Serial.println(F("Failed to join the network, retrying."));
    while (true)
    {
      state = lwActivate();
      if (state == RADIOLIB_LORAWAN_NEW_SESSION || state == RADIOLIB_LORAWAN_SESSION_RESTORED)
      {
        break;
      }
    }
  }
}

void loop() {}

The configuration must match the board - otherwise it will not work. There may be similar configurations that will also work.

Unfortunately, I am not familiar with LoRa or the board. However, your code deals with many other things that have nothing to do with LoRa, such as Deep Sleep. Leave that out for now and focus purely on LoRa.

You can find good tutorials at randomnerdtutorials.com.