LoRaWAN节点模块

1. 产品简介

这是一款简单易用的双模远距离无线通信模块,专为户外物联网应用设计,提供稳定可靠、低功耗的长距离通信解决方案。基于LoRa调制技术,模块专为US915频段设计,适用于北美和其他使用该频段的地区。其主要特点如下:

公里级远距离传输

模块提供城区1.5公里、开阔地带4.5公里的有效传输距离,适用于户外物联网项目。注:实际传输距离会受到天气、车流量、建筑密度等环境因素影响。

双模灵活配置(LoRa/LoRaWAN)

支持LoRa点对点(P2P)直连与LoRaWAN组网两种通信模式,灵活配置,满足不同应用需求。

  • 在LoRa模式下,模块可以实现一对一、一对多、多对一及桥接通信;

  • 在LoRaWAN模式下,模块支持A类和C类工作模式,作为数据采集节点连接网关,转发数据至TTN、ChirpStack等物联网云平台。

简单易用,快速部署

内置LoRa/LoRaWAN协议栈,无需底层开发,支持Arduino IDE、Mind+和MakeCode图形化编程,降低开发和上手难度。此外,模块提供标准I2C和UART通信接口,兼容大部分流行主控,例如Micro:bit、Arduino UNO和ESP32等。便于快速集成至现有物联网项目,提高项目部署效率。

户外IoT通信解决方案

户外物联网场景痛点 传统方案 本产品解决方案
部署成本高 需布线/中继设备,部署复杂且成本高 完全无线部署且成本低
传输距离短 WiFi<100m,且网络不稳定 公里级稳定传输
设备续航短 4G/WiFi通信耗电量高 LoRa/LoRaWAN通信耗电量低

适用于长距离、低功耗的物联网通信场景,如农场环境监测、气象站数据采集、工业监测、花园种植监测等项目。

2. 产品特性

  • 兼容3.3V和5V电平
  • 支持UART和I2C两种通讯方式
  • 板载PCB天线,模块一体化设计
  • 城区1.5公里/开阔地带4.5公里有效覆盖
  • 适用北美和其他使用US915频段的地区
  • 支持LoRa一对一、一对多、多对一和桥接通信
  • 支持ABP和OTAA两种LoRaWAN入网方式
  • 主控兼容性广,支持Micro:bit、Arduino UNO和ESP32等其他主控
  • 简单易用,支持Arduino IDE、Mind+以及MakeCode图形化编程

3. 应用场景

  • 农作物生长监测
  • 大棚温湿度监测
  • 生态区环境监测
  • 蜜蜂蜂箱自动监测
  • LoRaWAN气象站
  • 花园种植项目
  • 户外物联网教学

4. 功能指示图

引脚名称 引脚全称 引脚功能
T/D UATR_TX/I2C_SDA TX,数据发送引脚/SDA,数据传输引脚
R/C UATR_RX/I2C_SCL RX,数据接收引脚/SCL,I2C时钟引脚
- DGND 电源负极,连接主控的GND数字地
+ VCC 电源正极,DC 3.3V~5V(需与主控系统电平一致)
指示灯名称 指示灯全称 指示灯功能
PWR Power 红色电源指示灯,电源输入时常亮
ACT Active 绿色状态指示灯,分别提示三种状态:1、发送入网包时闪烁1秒;2、入网成功时常亮5秒;3、发送数据或接收数据时闪烁300ms

注意:拨码开关默认为 I2C 模式,可以在 I2C 和 UART 之间切换。切换后重启模块。

5. 技术规格

基本参数

供电电压 DC 3.3V~5V
通讯方式 I2C/UART
供电/通讯接口 PH2.0-4P
安装孔径 3.0mm
安装孔间距 35mm
产品尺寸 42x62mm
产品净重 10g

LoRa参数

射频芯片 SX1262
工作频率 915MHz
支持地区 北美及其他适用US915频段的地区
调制方式 LoRa调制
扩频因子 7~12
最大发射功率 +22dBm
接收灵敏度 -137dBm(SF=12/BW=125kHz)

6. 产品尺寸图

7. LoRa点对点(P2P)使用教程

7.1.1 硬件准备

7.1.2 软件准备

7.1.3 一发一收应用例程

在LoRa通信模式下,每个节点设备需设置自定义地址(范围1~255):

地址 说明
0 非法地址(不可用)
1~244 可重复使用的有效地址,比如将2个节点的地址都设置为3
255 广播地址(发送至255时全网段设备均可接收)

故本节例程介绍:适用两个FireBeetle 2 ESP32-E主控各扩展一个节点模块(地址分别为1和2),通过差异化地址配置实现温湿度传感器的定向长距离数据传输。

硬件连接:

  • 发送端:

  • 接收端:

示例代码:

发送端程序:设置节点地址为1,向地址为2的节点发送数据

#include <DFRobot_LWNode.h>
#include <dht11.h>
dht11 DHT;
#define DHT11_PIN 4
#define FREQ  914900000   
DFRobot_LWNode_IIC node(1); //设置节点地址为1

void setup( void ) {
    Serial.begin(115200);
    delay(5000);
    node.begin(/*communication IIC*/&Wire,/*debug UART*/&Serial);
    const uint32_t loraConfig[] = {FREQ, DBM16, 125000, 12}; //配置LoRa通信参数
    while(!node.setFreq(loraConfig[0])  || 
          !node.setEIRP(loraConfig[1])  || 
          !node.setBW(loraConfig[2])    || 
          !node.setSF(loraConfig[3])    || 
          !node.start()) {
        Serial.println("LoRa init failed");
        delay(2000);
    }
}

void loop( void ){
    DHT.read(DHT11_PIN);  //获取DHT11温湿度传感器数据
    Serial.print(DHT.humidity,1);
    Serial.print(",\t");
    Serial.println(DHT.temperature,1);
    String DHT11_DATE=String(DHT.humidity)+"%"+"  "+String(DHT.temperature) + "℃";
    delay(2000);
    node.sendPacket(2, DHT11_DATE);  //发送温湿度数据给地址为2的节点
    node.sleep(5000);
}

接收端程序:节点地址为2的设备烧录以下代码

#include <DFRobot_LWNode.h>
#define FREQ  914900000   
DFRobot_LWNode_IIC node(2);//设置节点地址为2

void rxCBFunc(uint8_t from, void *buffer, uint16_t size, int8_t rssi, int8_t snr){
    char *p = (char *)buffer;
    Serial.print("recv from: ");
    Serial.println(from, HEX);
    Serial.print("recv data: ");
    for(uint8_t i = 0; i < size; i++){
        Serial.print(p[i]);
    }
    Serial.println();
    Serial.println("Text:");
    Serial.println((char *)buffer);
    Serial.print("rssi=");Serial.println(rssi);
    Serial.print("snr=");Serial.println(snr);
}

void setup( void ){
    Serial.begin(115200);
    delay(5000);
    node.begin(/*communication IIC*/&Wire,/*debug UART*/&Serial);
    const uint32_t config[] = {FREQ, DBM16, 125000, 12};   //配置LoRa通信参数
    while(!node.setFreq(config[0])    || 
          !node.setEIRP(config[1])   || 
          !node.setBW(config[2])     || 
          !node.setSF(config[3])     || 
          !node.start()) {
        Serial.println("LoRa init failed, retrying...");
        delay(2000);
    }
    node.setRxCB(rxCBFunc);
}

void loop( void ){
    node.sleep(5000);
}

**运行结果:**通信成功,发送端和接收端的串口打印信息如下

7.1.4 一发两收应用例程

关于节点的一对多通信模式,可分为两种类型:

  1. 单发多收模式:一个节点发送数据,多个节点同时接收。
  2. 单收多发模式:一个节点接收数据,多个节点同时发送。

本实例演示的是第一种单发多收模式:将地址为1的节点设置为发送端,地址为2的两个节点(节点2和节点3)作为接收端,实现"一发两收"的通信场景。

硬件连接:

这里采用的是UART通讯方式。

  • 发送端:

  • 接收端(第一组和第二组都为以下连接方式):

示例代码:

发送端程序:设置节点地址为1,向地址为2的节点发送温湿度传感器的数据

#include <DFRobot_LWNode.h>
#include <dht11.h>
dht11 DHT;
#define DHT11_PIN 4
#define FREQ  914900000
DFRobot_LWNode_UART node(1); //设置节点地址为1

void setup( void ) {
    Serial.begin(115200);
    Serial1.begin(9600, SERIAL_8N1, /*rx =*/D6, /*tx =*/D7);
    delay(5000);
    node.begin(/*communication UART*/&Serial1,/*debug UART*/&Serial);
     const uint32_t config[] = {FREQ, DBM16, 125000, 12};   //配置LoRa通信参数
    while(!node.setFreq(config[0])    || 
          !node.setEIRP(config[1])   || 
          !node.setBW(config[2])     || 
          !node.setSF(config[3])     || 
          !node.start()) {
        Serial.println("LoRa init failed, retrying...");
        delay(2000);
    }
}

void loop( void ){
    DHT.read(DHT11_PIN);  //获取DHT11温湿度传感器数据
    Serial.print(DHT.humidity,1);
    Serial.print(",\t");
    Serial.println(DHT.temperature,1);
    String DHT11_DATE=String(DHT.humidity)+"%"+"  "+String(DHT.temperature) + "℃";
    delay(2000);
    node.sendPacket(2, DHT11_DATE);  //发送温湿度数据给地址为2的节点
    node.sleep(5000);
}

接收端第一组和第二组使用以下程序(注意设置不同的串口):节点地址为2,接收来自节点地址为1的数据。

#include <DFRobot_LWNode.h>
#define FREQ  914900000
DFRobot_LWNode_UART node(2);//设置节点地址为2

void rxCBFunc(uint8_t from, void *buffer, uint16_t size, int8_t rssi, int8_t snr){
    char *p = (char *)buffer;
    Serial.print("recv from: ");
    Serial.println(from, HEX);
    Serial.print("recv data: ");
    for(uint8_t i = 0; i < size; i++){
        Serial.print(p[i]);
    }
    Serial.println();
    Serial.print("rssi=");Serial.println(rssi);
    Serial.print("snr=");Serial.println(snr);
}

void setup( void ){
    Serial.begin(115200);
    Serial1.begin(9600, SERIAL_8N1, /*rx =*/D6, /*tx =*/D7);
    delay(5000);
    node.begin(/*communication UART*/&Serial1,/*debug UART*/&Serial);
    const uint32_t config[] = {FREQ, DBM16, 125000, 12};   //配置LoRa通信参数
    while(!node.setFreq(config[0])    || 
          !node.setEIRP(config[1])   || 
          !node.setBW(config[2])     || 
          !node.setSF(config[3])     || 
          !node.start()) {
        Serial.println("LoRa init failed, retrying...");
        delay(2000);
    }
    node.setRxCB(rxCBFunc);
}

void loop( void ){
    node.sleep(5000);
}

运行结果:
发送端串口打印信息:

接收端第一组串口打印信息:

接收端第二组串口打印信息:

7.1.5 两发一收应用例程

本实例演示的是第二种单收多发模式:将地址为1和2的节点设置为发送端,地址为3的节点作为接收端,实现"两发一收"的通信场景。

硬件连接:

  • 发送端:

  • 接收端:

示例代码:

发送端第一组程序:设置节点地址为1,向地址为3的节点发送温湿度传感器的数据

#include <DFRobot_LWNode.h>
#include <dht11.h>
dht11 DHT;
#define DHT11_PIN 4
#define FREQ  914900000
DFRobot_LWNode_UART node(1); //设置节点地址为1

void setup( void ) {
    Serial.begin(115200);
    Serial1.begin(9600, SERIAL_8N1, /*rx =*/D6, /*tx =*/D7);
    delay(5000);
    node.begin(/*communication UART*/&Serial1,/*debug UART*/&Serial);
    const uint32_t loraConfig[] = {FREQ, DBM16, 125000, 12}; //配置LoRa通信参数
    while(!node.setFreq(loraConfig[0])  || 
          !node.setEIRP(loraConfig[1])  || 
          !node.setBW(loraConfig[2])    || 
          !node.setSF(loraConfig[3])    || 
          !node.start()) {
        Serial.println("LoRa init failed");
        delay(2000);
    }
}

void loop( void ){
    DHT.read(DHT11_PIN);  //获取DHT11温湿度传感器数据
    Serial.print(DHT.humidity,1);
    Serial.print(",\t");
    Serial.println(DHT.temperature,1);
    String DHT11_DATE=String(DHT.humidity)+"%"+"  "+String(DHT.temperature) + "℃";
    delay(2000);
    node.sendPacket(3, DHT11_DATE);  //发送温湿度数据给地址为3的节点
    node.sleep(5000);
}

发送端第二组程序:设置节点地址为2,向地址为3的节点发送紫外线传感器的数据。

#include <DFRobot_LWNode.h>
#define FREQ  914900000
#include "DFRobot_LTR390UV.h"
DFRobot_LTR390UV ltr390(/*addr = */LTR390UV_DEVICE_ADDR, /*pWire = */&Wire);
DFRobot_LWNode_UART node(2);

void setup( void ) {
    Serial.begin(115200);
    Serial1.begin(9600, SERIAL_8N1, /*rx =*/D6, /*tx =*/D7);
    delay(5000);
    node.begin(/*communication UART*/&Serial1,/*debug UART*/&Serial);
    const uint32_t loraConfig[] = {FREQ, DBM16, 125000, 12}; //配置LoRa通信参数
    while(!node.setFreq(loraConfig[0])  || 
          !node.setEIRP(loraConfig[1])  || 
          !node.setBW(loraConfig[2])    || 
          !node.setSF(loraConfig[3])    || 
          !node.start()) {
        Serial.println("LoRa init failed");
        delay(2000);
    }
    
    while(ltr390.begin() != 0){
    Serial.println(" Sensor initialize failed!!");
    delay(1000);
  }
  Serial.println(" Sensor  initialize success!!");
  ltr390.setALSOrUVSMeasRate(ltr390.e18bit,ltr390.e100ms);//18位数据,采样时间100ms 
  ltr390.setALSOrUVSGain(ltr390.eGain3);//3倍增益
  ltr390.setMode(ltr390.eUVSMode);//设置测量紫外线模式 
}

void loop( void ){
    uint32_t uv = 0;
    uv = ltr390.readOriginalData();//获取紫外线数据原始数据
    Serial.println(uv);
    String ltr390_DATE = String(uv);
    delay(2000);
    node.sendPacket(3, ltr390_DATE);  //发送紫外线传感器的数据给地址为3的节点
    node.sleep(5000);
}

接收端程序:将接收端的节点地址设置为3,并处于接收消息状态。

#include <DFRobot_LWNode.h>
#define FREQ  914900000
DFRobot_LWNode_UART node(3);//设置节点地址为3

void rxCBFunc(uint8_t from, void *buffer, uint16_t size, int8_t rssi, int8_t snr){
    char *p = (char *)buffer;
    Serial.print("recv from: ");
    Serial.println(from, HEX);
    Serial.print("recv data: ");
    for(uint8_t i = 0; i < size; i++){
        Serial.print(p[i]);
    }
    Serial.println();
    Serial.println("Text:");
    Serial.println((char *)buffer);
    Serial.print("rssi=");Serial.println(rssi);
    Serial.print("snr=");Serial.println(snr);
}

void setup( void ){
    Serial.begin(115200);
    Serial1.begin(9600, SERIAL_8N1, /*rx =*/D6, /*tx =*/D7);
    delay(5000);
    node.begin(/*communication UART*/&Serial1,/*debug UART*/&Serial);
    const uint32_t loraConfig[] = {FREQ, DBM16, 125000, 12}; //配置LoRa通信参数
    while(!node.setFreq(loraConfig[0])  || 
          !node.setEIRP(loraConfig[1])  || 
          !node.setBW(loraConfig[2])    || 
          !node.setSF(loraConfig[3])    || 
          !node.start()) {
        Serial.println("LoRa init failed");
        delay(2000);
    }
    node.setRxCB(rxCBFunc);
}

void loop( void ){
    node.sleep(5000);
}

运行结果:

发送端第一组串口打印信息:

发送端第二组串口打印信息:

接收端串口打印信息:可以接收来自发送端第一组和第二组的数据

7.1.6 数据搭桥应用例程

前面介绍了节点数据的接收和发送,除了这样的玩法之外,节点还可以通过数据搭桥来实现更远距离的通信。

在本节例程中,将3个节点分别记作节点A、节点B、节点C,设备地址分别设置为1、2、3,来实现数据搭桥A→B→C,即将节点A的数据转给节点B,再由中间设备节点B转发给节点C,这样超过通信距离的节点C可以接收到来自节点A的数据,相当于扩展了通信距离。

硬件连接:

  • 节点A:

  • 节点B和节点C均采用以下连接方式:

示例代码:

节点A程序:设置节点地址为1,向地址为2的节点B发送温湿度传感器的数据。

#include <DFRobot_LWNode.h>
#include <dht11.h>
dht11 DHT;
#define DHT11_PIN 4
#define FREQ  914900000
DFRobot_LWNode_UART node(1); //设置节点地址为1

void setup( void ) {
    Serial.begin(115200);
    Serial1.begin(9600, SERIAL_8N1, /*rx =*/D6, /*tx =*/D7);
    delay(5000);
    node.begin(/*communication UART*/&Serial1,/*debug UART*/&Serial);
    const uint32_t loraConfig[] = {FREQ, DBM16, 125000, 12}; //配置LoRa通信参数
    while(!node.setFreq(loraConfig[0])  || 
          !node.setEIRP(loraConfig[1])  || 
          !node.setBW(loraConfig[2])    || 
          !node.setSF(loraConfig[3])    || 
          !node.start()) {
        Serial.println("LoRa init failed");
        delay(2000);
    }
}

void loop( void ){
    DHT.read(DHT11_PIN);  //获取DHT11温湿度传感器数据
    Serial.print(DHT.humidity,1);
    Serial.print(",\t");
    Serial.println(DHT.temperature,1);
    String DHT11_DATE=String(DHT.humidity)+"%"+"  "+String(DHT.temperature) + "℃";
    delay(2000);
    node.sendPacket(2, DHT11_DATE);  //发送温湿度数据给地址为2的节点
    node.sleep(1000);
}

节点B程序:设置节点地址为2,接收来自节点A的数据,然后向地址为3的节点C发送该数据。

#include <DFRobot_LWNode.h>
#define FREQ  914900000
DFRobot_LWNode_UART node(2);//设置节点地址为2
char p[36];

void rxCBFunc(uint8_t from, void *buffer, uint16_t size, int8_t rssi, int8_t snr){
    memcpy(p,buffer,size); //内存拷贝,把buffer的数据给copy到p数组里面
    Serial.print("recv from: ");
    Serial.println(from, HEX);
    Serial.print("recv data: ");
    for(uint8_t i = 0; i < size; i++){
        Serial.print(p[i]);
    }
    Serial.println();
    Serial.print("rssi=");Serial.println(rssi);
    Serial.print("snr=");Serial.println(snr);
}

void setup( void ){
    Serial.begin(115200);
    Serial1.begin(9600, SERIAL_8N1, /*rx =*/D6, /*tx =*/D7);
    delay(5000);
    node.begin(/*communication UART*/&Serial1,/*debug UART*/&Serial);
    const uint32_t loraConfig[] = {FREQ, DBM16, 125000, 12}; //配置LoRa通信参数
    while(!node.setFreq(loraConfig[0])  || 
          !node.setEIRP(loraConfig[1])  || 
          !node.setBW(loraConfig[2])    || 
          !node.setSF(loraConfig[3])    || 
          !node.start()) {
        Serial.println("LoRa init failed");
        delay(2000);
    }
    node.setRxCB(rxCBFunc);
}

void loop( void ){
    node.sleep(5000);
    node.sendPacket(3, p); //将接收到的消息转发给地址为3的节点
}

节点C程序:节点地址设置为3,并处于接收消息状态,接收来自节点B的数据。

#include <DFRobot_LWNode.h>
#define FREQ  914900000
DFRobot_LWNode_UART node(3);//设置节点地址为3

void rxCBFunc(uint8_t from, void *buffer, uint16_t size, int8_t rssi, int8_t snr){
    char *p = (char *)buffer;
    Serial.print("recv from: ");
    Serial.println(from, HEX);
    Serial.print("recv data: ");
    for(uint8_t i = 0; i < size; i++){
        Serial.print(p[i]);
    }
    Serial.println();
    Serial.print("rssi=");Serial.println(rssi);
    Serial.print("snr=");Serial.println(snr);
}

void setup( void ){
    Serial.begin(115200);
    Serial1.begin(9600, SERIAL_8N1, /*rx =*/D6, /*tx =*/D7);
    delay(5000);
    node.begin(/*communication UART*/&Serial1,/*debug UART*/&Serial);
    const uint32_t loraConfig[] = {FREQ, DBM16, 125000, 12}; //配置LoRa通信参数
    while(!node.setFreq(loraConfig[0])  || 
          !node.setEIRP(loraConfig[1])  || 
          !node.setBW(loraConfig[2])    || 
          !node.setSF(loraConfig[3])    || 
          !node.start()) {
        Serial.println("LoRa init failed");
        delay(2000);
    }
    node.setRxCB(rxCBFunc);
}

void loop( void ){
    node.sleep(5000);
}

运行结果:

节点A串口打印信息:

节点B串口打印信息:接收到节点A的数据,并转发出去

节点C串口打印信息:接收到了节点B的数据。

8. LoRaWAN使用教程

8.1 FireBeetle ESP32-E主板使用教程

8.1.1 硬件准备

8.1.2 软件准备

8.1.3 硬件连接

I2C通讯示例(以下例程中均采用这种连接方式)

管脚连接说明:

  • 节点模块:SDA引脚---(连接)---主控:21/SDA
  • 节点模块:SCL引脚---(连接)---主控:22/SCL
  • 节点模块:- 引脚---(连接)---主控:GND
  • 节点模块:+引脚---(连接)---主控:3V3

UART通讯示例

管脚连接说明:

  • 节点模块:TX 引脚---(连接)---主控:14/D6
  • 节点模块:RX 引脚---(连接)---主控:13/D7
  • 节点模块:- 引脚---(连接)---主控:GND
  • 节点模块:+引脚---(连接)---主控:3V3

8.1.3.1 OTAA入网

**注意:**使用该例程前,需要在网关端选择手动添加设备时选择OTAA模式入网。

例程1:OTAA入网并发送数据到网关

示例代码:

#include "DFRobot_LWNode.h"
#define REGION US915     
#define DATARATE  DR3
#define SUBBAND   2    
const char _APPEUI[]={"DFDFDFDF00000000"} ;
const char _APPKEY[]={"0102030405060708090A0B0C0D0E0F10"};
uint8_t _DEVEUI[16]={0x0};
DFRobot_LWNode_IIC node(_APPEUI,_APPKEY);

void setup(void){
    Serial.begin(115200);
    node.begin(/*communication IIC*/&Wire,/*debug UART*/&Serial);
    while(!node.setRegion(REGION)){
        delay(2000);
        Serial.println("REGION set fail");
    }
    if(!node.setAppEUI(_APPEUI)){
        Serial.println("AppEUI set fail");
    }
    if(!node.setAppKEY(_APPKEY)){
        Serial.println("AppKEY set fail");
    }
    if(!node.setDevType(CLASS_C)){
        Serial.println("DevType set fail");
    }
    while (!node.setDataRate(DATARATE)) {
        delay(2000);
        Serial.println("DataRate set fail");
    }
    while (!node.setEIRP(DBM16)) {
        delay(2000);
        Serial.println("EIRP set fail");
    }
    while(!node.setSubBand(SUBBAND)){
        Serial.println("SubBand set fail");
    }
    while(!node.enableADR(false)){
        delay(2000);
        Serial.println("ADR set fail");
    }
    while(!node.setPacketType(UNCONFIRMED_PACKET)){
        delay(2000);
        Serial.println("Packet type set fail");
    }
    if(node.getDevEUI(_DEVEUI)){
        Serial.print("deveui:");
        for(uint8_t i=0;i<8;i++){
          Serial.print(_DEVEUI[i],HEX);
        }
        Serial.println();
    }
   
    if(node.join()){
        Serial.println("JOIN......");    //入网
    }
    while(!node.isJoined()){   
      delay(5000);
    }   
}

void loop(){
   node.sendPacket("hello");  ////发送消息给网关
   node.sleep(10 * 1000);

   uint8_t buf[3]={1,2,3};
   node.sendPacket(buf,3)
   node.sleep(10 * 1000);
}

运行结果:

节点端:串口打印显示入网成功,并且间隔10秒发送数据给网关。

例程2:OTAA 入网后通过轮询方式从网关接收数据

示例代码:

#include "DFRobot_LWNode.h"
#define REGION US915     
#define DATARATE  DR3
#define SUBBAND   2 
const char _APPEUI[]={"DFDFDFDF00000000"} ;
const char _APPKEY[]={"0102030405060708090A0B0C0D0E0F10"};
uint8_t _DEVEUI[8]={0x0};
uint8_t buf[256]={0x0};

DFRobot_LWNode_IIC node(_APPEUI,_APPKEY);

void setup(void){
    Serial.begin(115200);
    node.begin(/*communication IIC*/&Wire,/*debug UART*/&Serial);
    while(!node.setRegion(REGION)){
        delay(2000);
        Serial.println("REGION set fail");
    }
    while(!node.setDevType(CLASS_C)){
        delay(2000);
        Serial.println("DevType set fail");
    }
    while(!node.setSubBand(SUBBAND)){
        delay(2000);
        Serial.println("SubBand set fail");
    }
    if(node.join()){
        Serial.println("JOIN......");   //入网
    }
    while(!node.isJoined()){
        delay(5000);
    }
    Serial.println("join success");
}

void loop(){
  uint8_t len = node.readData(buf);  //读取缓冲区是否接到数据
  if(len > 0){ 
    Serial.print("\nreceive ");Serial.print(len,HEX);Serial.println(" bytes  \nHEX:");  
    for(uint8_t i = 0;i<len;i++){
       Serial.print(buf[i],HEX);  
    }
    Serial.println();
    Serial.println("Text:");  
    Serial.println((char *)buf);
  }
  delay(500);
}

运行结果:

节点端:串口信息打印join success,然后节点进入轮询读取缓冲区是否接收到数据状态

8.1.3.2 ABP入网

**注意:**使用该例程前,需要在网关端选择手动添加设备时选择ABP模式入网。

例程1:ABP入网并向网关发送数据

示例代码:

#include "DFRobot_LWNode.h"
const char NWKSKEY[]={"87888888888888888888888888888888"};
const char APPSKEY[]={"89888888888888888888888888888888"};
uint32_t devAddr = 0xDF000011;
uint8_t _DEVEUI[16]={0x0};
#define REGION US915     
#define DATARATE  DR3
#define SUBBAND   2 
DFRobot_LWNode_IIC node(devAddr, NWKSKEY, APPSKEY);

void setup(void) {
    Serial.begin(115200);
    node.begin(/*communication IIC*/&Wire,/*debug UART*/&Serial);
    while(!node.setRegion(REGION)){
        delay(2000);
        Serial.println("REGION set fail");
    }
    if (!node.setAppSKey(APPSKEY)) {
      Serial.println("APPSKEY set fail");
    }
    if (!node.setNwkSKey(NWKSKEY)) {
      Serial.println("NWKSKEY set fail");
    }
    if (!node.setDevAddr(devAddr)) {
      Serial.println("devAddr set fail");
    }
    while (!node.setDataRate(DATARATE)) {
        delay(2000);
        Serial.println("DataRate set fail");
    }
    while (!node.setEIRP(DBM16)) {
        delay(2000);
        Serial.println("EIRP set fail");
    }
    while(!node.setSubBand(SUBBAND)) {
        delay(2000);
        Serial.println("SubBand set fail");
    }
    while(!node.enableADR(false)) {
        delay(2000);
        Serial.println("ADR set fail");
    }
    while(!node.setPacketType(UNCONFIRMED_PACKET)) {
        delay(2000);
        Serial.println("Packet type set fail");
    }
    if (node.getDevEUI(_DEVEUI)) {
      Serial.print("deveui:");
      for (uint8_t i = 0; i < 8; i++) {
          Serial.print(_DEVEUI[i], HEX);
      }
      Serial.println();
    }
}

void loop() {
  node.sendPacket("hello");//发送消息给网关
  node.sleep(10 * 1000);

  uint8_t buf[3] = {1, 2, 3};
  node.sendPacket(buf, 3);
  node.sleep(10 * 1000);
}

运行结果:

节点端:串口打印显示入网成功,并且间隔10秒发送数据给网关。

例程2:OTAA 入网后通过轮询方式从网关接收数据

示例代码:

#include "DFRobot_LWNode.h"
const char NWKSKEY[]={"87888888888888888888888888888888"} ;
const char APPSKEY[]={"89888888888888888888888888888888"};
uint32_t devAddr = 0xDF000011;
uint8_t _DEVEUI[16]={0x0};
uint8_t buf[256];
#define REGION US915     
#define DATARATE  DR3
#define SUBBAND   2 
DFRobot_LWNode_IIC node(devAddr,NWKSKEY,APPSKEY);

void setup(void){
    Serial.begin(115200);
    delay(5000);
    node.begin(/*communication IIC*/&Wire,/*debug UART*/&Serial);
    while(!node.setRegion(REGION)){
        delay(2000);
        Serial.println("REGION set fail");
    }
    while(!node.setDevType(CLASS_C)){
        delay(2000);
        Serial.println("DevType set fail");
    }
		Serial.println("join success");
}

void loop(){
    uint8_t len = node.readData(buf);  //读取缓冲区是否接到数据
    
    if(len > 0){
        Serial.print("\nreceive ");Serial.print(len);Serial.println(" bytes  \nHEX:");  
        for(uint8_t i = 0; i < len; i++){
            Serial.print(buf[i],HEX);  
        }
        Serial.println();
        Serial.println("Text:");
        Serial.println((char *)buf);
    }
    node.sleep(500);
}

运行结果:

节点端:串口打印消息join success,然后节点进入轮询读取缓冲区是否接收到数据状态。

10. API函数库

  /**
   * @fn setRegion
   * @brief 设置 LoRaWAN 区域。
   * @param region 区域枚举值
   * @return 如果成功则返回 true,否则返回 false
   */
  bool setRegion(eRegion_t region);
  
  /**
   * @fn setFreq
   * @brief 设置频率。
   * @param freq 频率值
   * @return 如果成功则返回 true,否则返回 false
   */
  bool setFreq(uint32_t freq);
  
  /**
   * @fn setBW
   * @brief 设置带宽。
   * @param bw 带宽值
   * @return 如果成功则返回 true,否则返回 false
   */
  bool setBW(uint32_t bw);
  
  /**
   * @fn setSF
   * @brief 设置扩频因子。
   * @param sf 扩频因子值
   * @return 如果成功则返回 true,否则返回 false
   */
  bool setSF(uint8_t sf);
  
  /**
   * @fn setRxCB
   * @brief 设置接收回调函数。当网关向节点发送数据时会调用此函数。
   * @param callback 回调函数指针
   */
  void setRxCB(rxCB *callback);
  
  /**
   * @fn setRxCB
   * @brief 为特定情况设置接收回调函数。
   * @param callback 回调函数指针
   */
  void setRxCB(rxCB3 *callback);
  
  /**
   * @fn setAppEUI
   * @brief 设置应用 EUI。
   * @param appeui 应用 EUI
   * @return 如果成功则返回 true,否则返回 false
   */
  bool setAppEUI(const char *appeui);
  
  /**
   * @fn setAppKEY
   * @brief 设置应用密钥。
   * @param appkey 应用密钥
   * @return 如果成功则返回 true,否则返回 false
   */
  bool setAppKEY(const char *appkey);
  
  /**
   * @fn setDevType
   * @brief 设置设备类型。
   * @param classType 设备类别枚举值
   * @return 如果成功则返回 true,否则返回 false
   */
  bool setDevType(eDeviceClass_t classType);
  
  /**
   * @fn setDataRate
   * @brief 设置数据速率。
   * @param dataRate 数据速率枚举值
   * @return 如果成功则返回 true,否则返回 false
   */
  bool setDataRate(eDataRate_t dataRate);
  
  /**
   * @fn setEIRP
   * @brief 设置发射功率。
   * @param EIRP 发射功率值
   * @return 如果成功则返回 true,否则返回 false
   */
  bool setEIRP(uint8_t EIRP);
  
  /**
   * @fn setSubBand
   * @brief 设置子频段。
   * @param subBand 子频段值
   * @return 如果成功则返回 true,否则返回 false
   */
  bool setSubBand(uint8_t subBand);
  
  /**
   * @fn enableADR
   * @brief 启用或禁用自适应数据速率(ADR)。
   * @param adr 如果为 true,则启用 ADR;如果为 false,则禁用 ADR
   * @return 如果成功则返回 true,否则返回 false
   */
  bool enableADR(bool adr);
  
  /**
   * @fn setDevAddr
   * @brief 设置设备地址。
   * @param devAddr 设备地址
   * @return 如果成功则返回 true,否则返回 false
   */
  bool setDevAddr(const uint32_t devAddr);
  
  /**
   * @fn setAppSKey
   * @brief 设置应用会话密钥。
   * @param appSKey 应用会话密钥
   * @return 如果成功则返回 true,否则返回 false
   */
  bool setAppSKey(const char *appSKey);
  
  /**
   * @fn setNwkSKey
   * @brief 设置网络会话密钥。
   * @param nwkSKey 网络会话密钥
   * @return 如果成功则返回 true,否则返回 false
   */
  bool setNwkSKey(const char *nwkSKey);
  
  /**
   * @fn join
   * @brief 启动 LoRaWAN 加入过程。设备将自动尝试加入网络。
   * @return 如果成功启动则返回 true,否则返回 false
   */
  bool join();
  
  /**
   * @fn start
   * @brief 启动设备操作。
   * @return 如果成功则返回 true,否则返回 false
   */
  bool start();
  
  /**
   * @fn setLoRaAddr
   * @brief 设置 LoRa 地址。
   * @param addr LoRa 地址
   * @return 如果成功则返回 true,否则返回 false
   */
  bool setLoRaAddr(uint8_t addr);
  
  /**
   * @fn isJoined
   * @brief 检查设备是否已经加入网络。
   * @return 如果已加入则返回 true,否则返回 false
   */
  bool isJoined();
  
  /**
   * @fn sendPacket
   * @brief 发送数据包。
   * @param v 要发送的值
   * @return 如果成功则返回 true,否则返回 false
   */
  bool sendPacket(double v);
  bool sendPacket(int32_t v);
  bool sendPacket(uint32_t v);
  bool sendPacket(void *buffer, uint8_t size);
  
  /**
   * @fn sendPacket
   * @brief 向特定地址发送数据包。
   * @param addr 目标地址
   * @param v 要发送的值
   * @return 如果成功则返回 true,否则返回 false
   */
  bool sendPacket(uint8_t addr, double v);
  bool sendPacket(uint8_t addr, int32_t v);
  bool sendPacket(uint8_t addr, uint32_t v);
  bool sendPacket(uint8_t addr, void *buffer, uint8_t size);
  
  /**
   * @fn sendPacket
   * @brief 发送字符串数据包。
   * @param data 要发送的字符串数据
   * @return 如果成功则返回 true,否则返回 false
   */
  bool sendPacket(String data);
    
  /**
   * @fn sendPacket
   * @brief 向特定地址发送字符串数据包。
   * @param addr 目标地址
   * @param data 要发送的字符串数据
   * @return 如果成功则返回 true,否则返回 false
   */
  bool sendPacket(uint8_t addr, String data);
  
  /**
   * @fn sendATCmd
   * @brief 发送通用 AT 命令。
   * @param cmd 预格式化的 AT 命令,不包含 \r\n
   * @return AT 命令的响应
   */
  String sendATCmd(String cmd);
  
  /**
   * @fn sendATCmdTest
   * @brief 发送测试 AT 命令。
   * @param cmd 测试 AT 命令
   * @return 测试 AT 命令的响应
   */
  String sendATCmdTest(char *cmd);
  
  /**
   * @fn setPacketType
   * @brief 设置数据包类型。
   * @param type 数据包类型(CONFIRMED_PACKET 或 UNCONFIRMED_PACKET)
   * @return 如果成功则返回 true,否则返回 false
   */
  bool setPacketType(ePacketType_t type = UNCONFIRMED_PACKET);
  
  /**
   * @fn getDevEUI
   * @brief 获取设备 EUI。
   * @return 设备 EUI 字符串
   */
  String getDevEUI();
  
  /**
   * @fn getNetID
   * @brief 获取网络 ID。
   * @return 3 字节网络 ID 信息
   */
  uint32_t getNetID();
  
  /**
   * @fn getDevAddr
   * @brief 获取设备地址。在 OTAA 模式下,此地址由网关分配。
   * @return 4 字节设备地址信息
   */
  uint32_t getDevAddr();
  
  /**
   * @fn getDataRate
   * @brief 获取当前数据速率。
   * @return 当前数据速率
   */
  uint8_t getDataRate();
  
  /**
   * @fn getEIRP
   * @brief 获取当前发射功率。
   * @return 当前发射功率
   */
  uint8_t getEIRP();
  
  /**
   * @fn getRSSI
   * @brief 获取接收信号强度指示(RSSI)。
   * @return RSSI 值
   */
  int16_t getRSSI();
  
  /**
   * @fn getSNR
   * @brief 获取信噪比(SNR)。
   * @return SNR 值
   */
  int8_t getSNR();
  
  /**
   * @fn atTest
   * @brief 执行 AT 测试命令。
   * @return 测试命令的结果
   */
  bool atTest();

11. 产品兼容性

本产品理论上支持所有的3.3V和5V的Arduino主控。以下表格列举了该产品在不同的主控中的测试情况。

主控板名称 功能正常 功能异常 未经验证
Arduino Uno
Arduino MEGA2560
Arduino Leonardo
FireBeetle-ESP8266
FireBeetle-ESP32
FireBeetle 2 ESP32-E
micro:bit

12. 资料下载

DFR1115-915_STP_file .zip

DFR1115-915_2D.pdf

13. 常见问题

  1. 问:拨码开关切换通讯方式后,为什么不起作用?

    答:在模块上电的情况下切换通讯方式之后,需要给模块重新上电才会生效。

  2. 问:模块的通信距离是多少?

    稳定通信距离 极限通信距离
    EU868版本 城区1.2公里/开阔地带4公里 城区1.4公里/开阔地带4.4公里
    US915版本 城区1.5公里/开阔地带4.5公里 城区2公里/开阔地带4.7公里

    以上测试数据仅供参考,通信距离受环境影响很大(车流量、天气情况、基站干扰等因素),实际距离要以实际部署为准。

    14. 更多

还没有客户对此产品有任何问题,欢迎通过qq或者论坛联系我们!

更多问题及有趣的应用,可以 访问论坛 进行查阅或发帖。

DFshopping_car1.png DFRobot商城购买链接