Hi all,
I’m trying to connect an ESP32 + SX1262 node to my ChirpStack 1.1 server in IN865 region using RadioLib (LoRaWAN 1.1 OTAA), but OTAA fails with error -1116 (RADIOLIB_ERR_NO_JOIN_ACCEPT).
Setup
- ESP32 DevKit, SX1262
- RadioLib version: 7.2.1
- LoRaWAN 1.1, Class A
- ChirpStack 1.1, IN865
- Node keys:
- DevEUI: 0x899F6EEE7E9D77F2
- AppKey: 3E 41 74 2C D8 65 70 BC 65 95 1A 80 5A AB 19 7E
- NwkKey: 28 EC CB 64 AB D0 4D 80 7F 21 86 F9 3B FF B7 B7
- JoinEUI: 0 (not used)
- Node sketch: minimal RadioLib OTAA example
Serial Output
[5] Initialising node (OTAA 1.1.0)…
→ Node init OK
[6] Sending JoinRequest…
→ OTAA state: -1116
→ Join failed
What I tried
- Verified raw LoRa transmission works.
- Confirmed gateway receives uplink.
- Radio configured for IN865.
- Keys match the device registered in ChirpStack (DevEUI, AppKey, NwkKey).
How do I correctly configure RadioLib/ESP32 for OTAA 1.1 to join a ChirpStack server without using JoinEUI? Am I missing something in the sketch or ChirpStack setup?
Thanks in advance!
#define RADIOLIB_DEBUG
#include "config.h"
bool joined = false;
void setup() {
Serial.begin(115200);
SPI.begin(6, 2, 7, 10); // (SCK, MISO, MOSI, SS)
while (!Serial);
delay(2000);
Serial.println(F("\n=== LoRaWAN Debug Start ==="));
// 1. Init radio
Serial.println(F("[1] Initialising radio..."));
int16_t state = radio.begin(
865.0625, // IN865 join channel 1
125.0, // bandwidth in kHz
7, // spreading factor (SF7 is standard for join)
7, // coding rate (4/7 is common)
RADIOLIB_SX126X_SYNC_WORD_PRIVATE,
10, 8, 0, false
);
if (state == RADIOLIB_ERR_NONE) {
Serial.println(F(" -> Radio init OK"));
} else {
Serial.print(F(" -> Radio init FAILED: "));
Serial.println(state);
while (true);
}
// Test raw transmit
Serial.println(F("[2] Test raw transmit..."));
state = radio.transmit("Hello");
if (state == RADIOLIB_ERR_NONE) {
Serial.println(F(" -> Transmission successful!"));
} else {
Serial.print(F(" -> Transmit failed, code: ")); Serial.println(state);
}
// 2. Print region/subBand
Serial.print(F("[3] Region: ")); Serial.println("IN865");
Serial.print(F(" SubBand: ")); Serial.println(subBand);
// 3. Print credentials
Serial.println(F("[4] Device credentials:"));
Serial.print(F(" DevEUI: 0x")); Serial.println((uint64_t)devEUI, HEX);
Serial.print(F(" JoinEUI: 0x")); Serial.println((uint64_t)joinEUI, HEX);
Serial.print(F(" AppKey: "));
for (uint8_t i = 0; i < 16; i++) { Serial.print(appKey[i], HEX); Serial.print(" "); }
Serial.println();
Serial.print(F(" NwkKey: "));
for (uint8_t i = 0; i < 16; i++) { Serial.print(nwkKey[i], HEX); Serial.print(" "); }
Serial.println();
// 4. Init node (OTAA 1.1)
Serial.println(F("[5] Initialising node (OTAA 1.1.0)..."));
state = node.beginOTAA(joinEUI, devEUI, nwkKey, appKey);
if (state == RADIOLIB_ERR_NONE) {
Serial.println(F(" -> Node init OK"));
} else {
Serial.print(F(" -> Node init FAILED: ")); Serial.println(state);
while (true);
}
delay(1000);
// 5. Try to join
Serial.println(F("[6] Sending JoinRequest..."));
state = node.activateOTAA();
Serial.print(F(" -> OTAA state: ")); Serial.println(state);
if (state == RADIOLIB_LORAWAN_NEW_SESSION) {
Serial.println(F(" -> Join success!"));
joined = true;
} else {
Serial.println(F(" -> Join failed (RADIOLIB_ERR_NO_JOIN_ACCEPT = -1116)"));
joined = false;
}
checkLoRaMode();
Serial.println(F("=== Setup Complete ===\n"));
}
void checkLoRaMode() {
// Check if the node object exists
if (&node != nullptr) {
Serial.println(F("[Check] LoRaWANNode object exists. Node is configured for LoRaWAN."));
if (joined) {
Serial.println(F("[Check] Node has joined the network. LoRaWAN session active."));
} else {
Serial.println(F("[Check] Node is in LoRaWAN mode but not joined yet."));
}
// Optional: send a dummy payload to verify LoRaWAN behavior
uint8_t testPayload[1] = {0x00};
int16_t state = node.sendReceive(testPayload, sizeof(testPayload));
if (state >= RADIOLIB_ERR_NONE) {
Serial.println(F("[Check] LoRaWAN sendReceive() successful. Node is in LoRaWAN mode."));
} else {
Serial.println(F("[Check] LoRaWAN sendReceive() returned error. Node may not be joined yet."));
}
} else {
Serial.println(F("[Check] No LoRaWANNode object found. Node may be in raw LoRa mode."));
}
}
void loop() {
if (joined) {
Serial.println(F("[Loop] Sending uplink..."));
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);
int16_t state = node.sendReceive(uplinkPayload, sizeof(uplinkPayload));
if (state < RADIOLIB_ERR_NONE) {
Serial.print(F(" -> Error in sendReceive: "));
Serial.println(state);
} else if (state > 0) {
Serial.println(F(" -> Downlink received!"));
} else {
Serial.println(F(" -> No downlink received"));
}
Serial.print(F("Next uplink in "));
Serial.print(uplinkIntervalSeconds);
Serial.println(F(" seconds\n"));
} else {
Serial.println(F("[Loop] Node not joined, skipping uplink."));
}
delay(uplinkIntervalSeconds * 1000UL);
}