4. 使用OTAA模式接入终端设备

任务目标

本案例将实现一个基于OTAA(Over-The-Air Activation)模式的LoRaWAN终端设备接入流程。终端设备通过发送Join Request报文完成网络接入认证,在获得Join Accept后即可进行上下行数据传输。案例使用Arduino框架配合LoRaWAN库,模拟真实终端设备的入网过程。

环境依赖

  • 硬件:LoRaWAN开发板(如Heltec LoRa 32、CubeCell等),需支持SX126x/SX127x射频芯片
  • 软件:Arduino IDE(≥1.8.10),安装MCCI LoRaWAN LMIC库(v4.x)
  • 网络参数:需准备可用的OTAA入网参数(AppEUI、DevEUI、AppKey),可从LoRaWAN网络服务器(如ChirpStack、TTN)获取

完整实现代码

#include <lmic.h>
#include <hal/hal.h>
#include <SPI.h>

// OTAA入网参数(示例值,需替换为实际参数)
static const u1_t PROGMEM APPEUI[8] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
static const u1_t PROGMEM DEVEUI[8] = { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08 };
static const u1_t PROGMEM APPKEY[16] = { 0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF, 0x00 };

// LoRaWAN频段配置(此处使用CN470,可根据实际修改)
#define CFG_CN470 1
#define CFG_sx126x 1

// LMIC回调函数
void os_getArtEui (u1_t* buf) { memcpy_P(buf, APPEUI, 8); }
void os_getDevEui (u1_t* buf) { memcpy_P(buf, DEVEUI, 8); }
void os_getDevKey (u1_t* buf) { memcpy_P(buf, APPKEY, 16); }

// 事件处理
static void eventHandler (ev_t ev) {
    switch (ev) {
        case EV_JOINING:
            Serial.println("正在入网...");
            break;
        case EV_JOINED:
            Serial.println("入网成功!");
            // 禁用ADR以简化调试
            LMIC_setLinkCheckMode(0);
            break;
        case EV_JOIN_FAILED:
            Serial.println("入网失败,请检查参数");
            break;
        case EV_TXCOMPLETE:
            Serial.println("数据发送完成");
            // 发送完成后进入休眠(此处仅演示,实际可安排下次发送)
            break;
        case EV_RXCOMPLETE:
            Serial.println("收到下行数据");
            break;
        default:
            break;
    }
}

void setup() {
    Serial.begin(115200);
    while (!Serial);
    
    // LMIC初始化
    os_init();
    LMIC_reset();
    LMIC_setClockError(MAX_CLOCK_ERROR * 1 / 100);
    
    // 设置OTAA入网参数
    LMIC_setSession(0, 0, 0, 0);
    LMIC_setupChannel(0, 470300000, DR_RANGE_MAP(DR_SF12, DR_SF7), 0);
    LMIC_setupChannel(1, 470500000, DR_RANGE_MAP(DR_SF12, DR_SF7), 0);
    LMIC_setupChannel(2, 470700000, DR_RANGE_MAP(DR_SF12, DR_SF7), 0);
    
    // 启动入网
    LMIC_startJoining();
    Serial.println("OTAA入网流程已启动");
}

void loop() {
    os_runloop_once();
    
    // 入网成功后,每30秒发送一次数据
    static unsigned long lastSend = 0;
    if (LMIC.devaddr != 0 && millis() - lastSend > 30000) {
        lastSend = millis();
        uint8_t payload[] = { 0x01, 0x02, 0x03 };
        LMIC_setTxData2(1, payload, sizeof(payload), 0);
        Serial.println("发送上行数据");
    }
}

运行与验证

  1. 将上述代码中的APPEUI、DEVEUI、APPKEY替换为网络服务器分配的实际参数
  2. 根据开发板型号调整引脚定义(若使用非默认引脚,需在hal配置中修改)
  3. 编译并烧录到开发板,打开串口监视器(波特率115200)
  4. 观察串口输出:应依次看到“OTAA入网流程已启动”→“正在入网...”→“入网成功!”

通过判定标准:串口输出“入网成功!”且网络服务器后台能看到设备处于在线状态;随后每30秒能看到一次上行数据记录,服务器下发数据时设备能收到并打印“收到下行数据”。若输出“入网失败”,请检查三组参数是否与服务器一致,以及频段配置是否匹配。

常见问题

  • 入网超时:确认设备与网关距离在信号覆盖范围内,检查频段配置(CN470需确认信道频率与服务器一致)
  • 编译错误:确认已安装MCCI LoRaWAN LMIC库,并在编译前根据开发板选择正确的射频芯片宏定义(CFG_sx126x或CFG_sx1276)
  • 参数格式:AppEUI和DevEUI在服务器端通常以MSB顺序显示,代码中需按LSB顺序填入(即字节序反转)