1. Introduction
This is an easy-to-use, dual-mode long-distance wireless communication module designed for outdoor IoT applications, providing stable, reliable, and low-power long-range communication solutions. Based on LoRa modulation technology, the module is designed for the US915 frequency band, suitable for use in North America and other regions using this frequency. The main features are as follows:
Kilometer-Range Long-Distance Transmission
The module provides effective transmission distances of 1.5 kilometers in urban areas and 4.5 kilometers in open areas, making it suitable for outdoor IoT applications.
Note: Actual transmission distance may be affected by environmental factors such as weather, traffic, and building density.
Dual-Mode Flexible Configuration (LoRa/LoRaWAN)
Supports two communication modes: LoRa point-to-point (P2P) direct connection and LoRaWAN networking, providing flexible configuration to meet various application needs.
l In LoRa mode, the module supports one-to-one, one-to-many, many-to-one, and bridge communication;
l In LoRaWAN mode, the module supports both Class A and Class C operation modes, acting as a data acquisition node that connects to a gateway and forwards data to IoT cloud platforms such as TTN, ChirpStack, etc.
Simple to Use, Quick Deployment
With an integrated LoRa/LoRaWAN protocol stack, no lower-level development is required. The module supports Arduino IDE, Mind+, and MakeCode graphical programming, reducing development complexity. Additionally, it provides standard I2C and UART communication interfaces, compatible with popular microcontrollers such as Micro:bit, Arduino UNO, ESP32, and other development boards. This enables quick integration into existing IoT projects and greatly improves project deployment efficiency.
Outdoor IoT communication solutions
Outdoor IoT Scene Pain Points | Traditional Solutions | This Product's Solution |
---|---|---|
High Deployment Cost | Requires wiring/intermediate devices, complex and high cost | Fully wireless deployment, low cost |
Short Transmission Range | WiFi < 100m, unstable network | Stable kilometer-range transmission |
Short Device Battery Life | 4G/WiFi communication consumes a lot of power | Low power consumption with LoRa/LoRaWAN communication |
Suitable for long-distance, low-power IoT communication scenarios, such as farm environmental monitoring, weather station data collection, industrial monitoring, garden planting monitoring, and more.
2. Features
- Compatible with 3.3V and 5V logic levels
- Supports both UART and I2C communication methods
- Onboard PCB antenna, integrated module design
- Effective coverage: 1.5km in urban areas / 4.5km in open areas
- Suitable for North America and other regions using the US915 frequency band
- Supports LoRa one-to-one, one-to-many, many-to-one, and bridge communication
- Supports ABP and OTAA LoRaWAN activation modes
- Wide compatibility with microcontrollers: Micro:bit, Arduino UNO, ESP32, and other development boards
- Simple to use, supports Arduino IDE, Mind+, and MakeCode graphical programming
3. Applications
- Crop growth monitoring
- Greenhouse temperature and humidity monitoring
- Ecological area environmental monitoring
- Beehive automatic monitoring
- LoRaWAN weather stations
- Garden planting projects
- Outdoor IoT education
4. Function indication
Name | Full Name | Function |
---|---|---|
T/D | UART_TX/I2C_SDA | UART transmit pin (TX) / I2C data line (SDA) |
R/C | UART_RX/I2C_SCL | UART receive pin (RX) / I2C clock line (SCL) |
- | DGND | Digital ground, connects to the GND of the host controller |
+ | VCC | PPower supply input, DC 3.3V~5V (must match the host system voltage level) |
PWR | Power | Red power indicator, remains on when power is supplied |
ACT | Active | Green status indicator: |
1. Blinks for 1 second when transmitting a network join request. | ||
2. Remains on for 5 seconds when the network join is successful. | ||
3. Blinks for 300ms during data transmission or reception. |
Note: The DIP switch defaults to I2C mode and can switch between I2C and UART. Restart the module after switching.
5. Specification
Basic Parameters
Power Supply Voltage | DC 3.3V~5V |
---|---|
Communication Mode | I2C/UART |
Power/Communication Interface | PH2.0-4P |
Mounting Hole Diameter | 3.0mm |
Mounting Hole Spacing | 35mm |
Product Dimensions | 42x62mm |
Net Weight | 10g |
LoRa Parameters
RF Chip | SX1262 |
---|---|
Operating Frequency | 915MHz |
Supported Regions | North America and other regions using the US915 band |
Modulation Method | LoRa modulation |
Spreading Factor | 7~12 |
Maximum Transmit Power | +22dBm |
Receiver Sensitivity | -137dBm (SF=12/BW=125kHz) |
6. Dimensions
7.1.1 Hardware Preparation
- FireBeetle 2 ESP32-E (SKU: DFR0654) ×3
- Gravity: LoRaWAN Node Module (US915)(DFR1115-915) ×3
- Gravity: DHT11 Temperature and Humidity Sensor (SKU: DFR0067) ×1
- Gravity: UV Sensor (SKU: SEN0540) ×1
- PH2.0-4P Cable ×3
- USB Data Cable ×3
7.1.2 Software Preparation
- Download Arduino IDE: Click to Download Arduino IDE
- Install SDK: Visit the FireBeetle 2 ESP32-E WIKI page for SDK installation instructions
- Download Arduino Library: Click to download DFRobot_LWNode Library and refer to the guide: How to Install a Library?
7.1.3 Transmit-Receive Application Example
In LoRa communication mode, each node device needs to set a custom address (range 1~255):
Address | Description |
---|---|
0 | Invalid address (not usable) |
1~244 | Valid reusable addresses, e.g., set two nodes to address 3 |
255 | Broadcast address (when sending to 255, all devices in the network can receive) |
Therefore, this example demonstrates: two FireBeetle 2 ESP32-E main controllers, each expanding one node module (addresses 1 and 2 respectively), achieving long-distance, directional data transmission from the temperature and humidity sensor via differentiated address configurations.
Hardware Connection:
- Transmitter:
- Receiver:
Example Code:
Transmitter Program: Set node address to 1, send data to node with address 2.
#include <DFRobot_LWNode.h>
#include <dht11.h>
dht11 DHT;
#define DHT11_PIN 4
#define FREQ 914900000
DFRobot_LWNode_IIC node(1); // Set node address to 1
void setup( void ) {
Serial.begin(115200);
delay(5000);
node.begin(/*communication IIC*/&Wire,/*debug UART*/&Serial);
const uint32_t loraConfig[] = {FREQ, DBM22, 125000, 12}; // Configure LoRa communication parameters
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); // Get data from DHT11 temperature and humidity sensor
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); // Send temperature and humidity data to node with address 2
node.sleep(5000);
}
Receiver Program: Node with address 2 should burn the following code.
#include <DFRobot_LWNode.h>
#define FREQ 914900000
DFRobot_LWNode_IIC node(2); // Set node address to 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, DBM22, 125000, 12}; // Configure LoRa communication parameters
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);
}
Results: Communication successful, the serial output from both the transmitter and receiver is as follows:
7.1.4 One-to-Many Communication Example
There are two types of one-to-many communication modes for nodes:
- Single Transmit, Multiple Receive Mode: One node sends data, and multiple nodes receive simultaneously.
- Single Receive, Multiple Transmit Mode: One node receives data, and multiple nodes transmit simultaneously.
This example demonstrates the first type, Single Transmit, Multiple Receive Mode: Node with address 1 is set as the transmitter, and nodes with address 2 and 3 are set as receivers, realizing the "one-to-many" communication scenario.
Hardware Connection:
Here, UART communication is used.
- Transmitter:
- Receiver (The connection method for both the first and second groups is as follows):
Example Code:
Transmitter Program: Set node address to 1, send temperature and humidity sensor data to node with address 2.
#include <DFRobot_LWNode.h>
#include <dht11.h>
dht11 DHT;
#define DHT11_PIN 4
#define FREQ 914900000
DFRobot_LWNode_UART node(1); // Set node address to 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, DBM22, 125000, 12}; // Configure LoRa communication parameters
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); // Get data from DHT11 temperature and humidity sensor
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); // Send temperature and humidity data to node with address 2
node.sleep(5000);
}
The first and second groups of receivers both use the following program (note: set different serial ports): set the node address to 2 to receive data from the node with address 1.
#include <DFRobot_LWNode.h>
#define FREQ 914900000
DFRobot_LWNode_UART node(2); // Set node address to 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, DBM22, 125000, 12}; // Configure LoRa communication parameters
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);
}
Result:
Serial output from the transmitter:
Serial output from the first group of receivers:
Serial output from the second group of receivers:
7.1.5 Two-to-One Communication Example
This example demonstrates the second type of one-to-many communication mode: setting nodes with addresses 1 and 2 as transmitters, and the node with address 3 as the receiver, achieving a "two-to-one" communication scenario.
Hardware Connections:
- Transmitter:
- Receiver:
Example Code:
Transmitter Group 1 Program: Sets the node address to 1 and sends temperature and humidity data to the node with address 3.
#include <DFRobot_LWNode.h>
#include <dht11.h>
dht11 DHT;
#define DHT11_PIN 4
#define FREQ 914900000
DFRobot_LWNode_UART node(1); // Set node address to 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, DBM22, 125000, 12}; // Configure LoRa communication parameters
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); // Read data from the DHT11 temperature and humidity sensor
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); // Send temperature and humidity data to the node with address 3
node.sleep(5000);
}
Transmitter Group 2 Program: Sets the node address to 2 and sends UV sensor data to the node with address 3.
#include <DFRobot_LWNode.h>
#define FREQ 914900000
// Initialize LoRa and UV sensor
#include "DFRobot_LTR390UV.h"
DFRobot_LTR390UV ltr390(/*addr = */LTR390UV_DEVICE_ADDR, /*pWire = */&Wire);
DFRobot_LWNode_UART node(2); // Set node address to 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, DBM22, 125000, 12}; // LoRa communication parameters
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);
}
// Initialize UV sensor
while(ltr390.begin() != 0){
Serial.println(" Sensor initialize failed!!");
delay(1000);
}
Serial.println(" Sensor initialize success!!");
// Configure UV sensor
ltr390.setALSOrUVSMeasRate(ltr390.e18bit, ltr390.e100ms); // 18-bit data, 100ms sampling
ltr390.setALSOrUVSGain(ltr390.eGain3); // 3x gain
ltr390.setMode(ltr390.eUVSMode); // Set to UV measurement mode
}
void loop(void) {
// Read UV sensor data
uint32_t uv = ltr390.readOriginalData(); // Get raw UV sensor data
Serial.print("UV data: ");
Serial.println(uv);
// Prepare and send UV data to node with address 3
String ltr390_DATE = String(uv);
node.sendPacket(3, ltr390_DATE);
// Sleep to conserve power (adjust if needed)
node.sleep(5000);
}
Receiver Program: Set the receiver node address to 3 and keep it in message receiving mode.
#include <DFRobot_LWNode.h>
#define FREQ 914900000
DFRobot_LWNode_UART node(3); // Set node address to 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, DBM22, 125000, 12}; // Configure LoRa communication parameters
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);
}
Result:
Serial output of transmitter Group 1:
Serial Output of Transmitter Group 2:
Serial Output of Receiver: Data received from Transmitter Group 1 and Group 2.
7.1.6 Data Relay Application Example
In addition to direct data transmission and reception, nodes also support data relay to extend communication range.
In this example, three nodes (A, B, and C) with addresses 1, 2, and 3 are used to demonstrate the A→B→C data relay process. Node A sends data to Node B, which then forwards it to Node C. This allows Node C, which is outside the direct communication range of Node A, to receive data from Node A.
Hardware Connection:
- Node A:
- Both Node B and Node C use the following connection method:
Example Code:
Node A Program: Set the node address to 1 and send temperature and humidity sensor data to Node B with address 2.
#include <DFRobot_LWNode.h>
#include <dht11.h>
dht11 DHT;
#define DHT11_PIN 4
#define FREQ 914900000
DFRobot_LWNode_UART node(1); // Set node address to 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, DBM22, 125000, 12}; // Configure LoRa communication parameters
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); // Read temperature and humidity data from the DHT11 sensor
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); // Send temperature and humidity data to Node B with address 2
node.sleep(1000);
}
Node B Program: Set the node address to 2, receive data from Node A, and forward it to Node C with address 3.
#include <DFRobot_LWNode.h>
#define FREQ 914900000
DFRobot_LWNode_UART node(2); // Set node address to 2
char p[36];
void rxCBFunc(uint8_t from, void *buffer, uint16_t size, int8_t rssi, int8_t snr){
memcpy(p,buffer,size); // Memory copy, copy the data from buffer to the p array
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, DBM22, 125000, 12}; // Configure LoRa communication parameters
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); // Forward the received message to the node with address 3
}
Node C Program: Set the node address to 3 and keep it in message receiving mode to receive data from Node B.
#include <DFRobot_LWNode.h>
#define FREQ 914900000
DFRobot_LWNode_UART node(3);// Set the node address to 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, DBM22, 125000, 12}; /// Configure LoRa communication parameters
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);
}
Result:
Serial Output of Node A:
Serial Output of Node B: Received data from Node A and forwarded it.
Serial Output of Node C: Received data from Node B.
8. LoRaWAN Tutorial
8.1 FireBeetle ESP32-E Tutorial
8.1.1 Hardware Preparation
- FireBeetle 2 ESP32-E (SKU: DFR0654) ×1
- Gravity: LoRaWAN Node Module(US915)(DFR1115-915) ×1
- PH2.0-4P Cable ×1
- USB Data Cable ×1
8.1.2 Software Preparation
- Download Arduino IDE: Click to Download Arduino IDE
- Install SDK: Visit the FireBeetle 2 ESP32-E WIKI Page to find the SDK installation tutorial.
- Download Arduino Library: Click to download the DFRobot_LWNode Library and refer to this link for guidance: How to Install a Library?
8.1.3 Hardware Connection
I2C Communication Example (This connection method is used in all the following examples)
Pin Connection Description:
- Node Module: SDA Pin --- (Connects to) --- Main Controller: 21/SDA
- Node Module: SCL Pin --- (Connects to) --- Main Controller: 22/SCL
- Node Module: - Pin --- (Connects to) --- Main Controller: GND
- Node Module: + Pin --- (Connects to) --- Main Controller: 3V3
UART Communication Example
Pin Connection Description:
- Node Module: TX Pin --- (Connects to) --- Main Controller: 14/D6
- Node Module: RX Pin --- (Connects to) --- Main Controller: 13/D7
- Node Module: - Pin --- (Connects to) --- Main Controller: GND
- Node Module: + Pin --- (Connects to) --- Main Controller: 3V3
8.1.3.1 OTAA Network Joining
Note: Before using this example, ensure that the gateway is set to manual device addition mode and configured to allow OTAA for device registration.
Example 1: OTAA Network Joining and Sending Data to the Gateway
Sample Code:
#include "DFRobot_LWNode.h"
#define REGION US915
#define DATARATE DR3
#define SUBBAND 2
// OTAA credentials (replace these with your actual values)
const char _APPEUI[]={"DFDFDFDF00000000"} ;
const char _APPKEY[]={"0102030405060708090A0B0C0D0E0F10"};
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");
}
String deveui = node.getDevEUI();
Serial.print("DEVEUI: ");
Serial.println(deveui);
Serial.print("DATARATE: ");
Serial.println(node.getDataRate());
Serial.print("EIRP: ");
Serial.println(node.getEIRP());
//Attempt to join LoRaWAN network
if(node.join()){
Serial.println("JOIN......");
}
while(!node.isJoined()){
delay(5000);
}
}
void loop(){
node.sendPacket("hello"); // Send text message 'hello' to LoRaWAN gateway
node.sleep(10 * 1000);
uint8_t buf[3]={1,2,3}; // Send binary message {1, 2, 3} to LoRaWAN gateway
node.sendPacket(buf,3);
node.sleep(10 * 1000);
}
Result:
On the node side: The serial monitor prints a message indicating successful network joining, and the node sends data to the gateway every 10 seconds.
Example 2: Receiving Data from the Gateway via Polling after OTAA Network Joining
Sample Code:
#include "DFRobot_LWNode.h"
#define REGION US915
#define DATARATE DR3
#define SUBBAND 2
// OTAA credentials (replace these with your actual values)
const char _APPEUI[]={"DFDFDFDF00000000"} ;
const char _APPKEY[]={"0102030405060708090A0B0C0D0E0F10"};
uint8_t buf[256]={0x0}; // Buffer to store received data
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");
}
String deveui = node.getDevEUI();
Serial.print("DEVEUI: ");
Serial.println(deveui);
// Attempt to join the LoRaWAN network
if(node.join()){
Serial.println("JOIN......");
}
while(!node.isJoined()){
delay(5000);
}
Serial.println("join success");
}
void loop(){
uint8_t len = node.readData(buf); // Read data from the LoRaWAN downlink buffer
// If data is received, print it in both hexadecimal and text formats
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);
}
Result:
On the node side: The serial monitor prints "join success", and the node enters a polling state to check whether data is received in the buffer.
8.1.3.2 ABP Network Joining
Note: Before using this example, ensure that the gateway is set to manual device addition mode and configured to allow ABP for device registration.
Example 1: ABP Network Joining and Sending Data to the Gateway
Sample Code:
#include "DFRobot_LWNode.h"
// ABP credentials (replace these with your actual values)
const char NWKSKEY[]={"87888888888888888888888888888888"};
const char APPSKEY[]={"89888888888888888888888888888888"};
uint32_t devAddr = 0xDF000011;
#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");
}
node.start(); // Start LoRaWAN communication in ABP mode
String deveui = node.getDevEUI();
Serial.print("DEVEUI: ");
Serial.println(deveui);
Serial.print("DATARATE: ");
Serial.println(node.getDataRate());
Serial.print("EIRP: ");
Serial.println(node.getEIRP());
}
void loop() {
node.sendPacket("hello"); // Send a text message "hello" to the LoRaWAN gateway
node.sleep(10 * 1000);
uint8_t buf[3] = {1, 2, 3}; // Send a binary message {1, 2, 3} to the LoRaWAN gateway
node.sendPacket(buf, 3);
node.sleep(10 * 1000);
}
Result:
On the node side: The serial monitor shows that the node sends data to the gateway every 10 seconds.
Example 2: Receiving Data from the Gateway via Polling after ABP Network Joining
Sample Code:
#include "DFRobot_LWNode.h"
// ABP credentials (replace these with your actual values)
const char NWKSKEY[]={"87888888888888888888888888888888"} ;
const char APPSKEY[]={"89888888888888888888888888888888"};
uint32_t devAddr = 0xDF000011;
uint8_t buf[256]; // Buffer to store received data
#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");
}
String deveui = node.getDevEUI();
Serial.print("DEVEUI: ");
Serial.println(deveui);
// Start LoRaWAN communication in ABP mode
node.start();
Serial.println("join success");
}
void loop(){
uint8_t len = node.readData(buf); // Check if there is data received from the gateway
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); // Print received data in hexadecimal format
}
Serial.println();
Serial.println("Text:"); // Print received data as text
Serial.println((char *)buf);
}
node.sleep(500);
}
Result:
On the node side: The serial monitor displays the message "join success", and the node enters a polling state to check whether data is received from the buffer.
10. API Library
/**
* @fn setRegion
* @brief Sets the LoRaWAN region.
* @param region Region enum value
* @return Returns true if successful, otherwise false
*/
bool setRegion(eRegion_t region);
/**
* @fn setFreq
* @brief Sets the frequency.
* @param freq Frequency value
* @return Returns true if successful, otherwise false
*/
bool setFreq(uint32_t freq);
/**
* @fn setBW
* @brief Sets the bandwidth.
* @param bw Bandwidth value
* @return Returns true if successful, otherwise false
*/
bool setBW(uint32_t bw);
/**
* @fn setSF
* @brief Sets the spreading factor.
* @param sf Spreading factor value
* @return Returns true if successful, otherwise false
*/
bool setSF(uint8_t sf);
/**
* @fn setRxCB
* @brief Sets the receive callback function. This function is called when the gateway sends data to the node.
* @param callback Pointer to the callback function
*/
void setRxCB(rxCB *callback);
/**
* @fn setRxCB
* @brief Sets the receive callback function for a specific case.
* @param callback Pointer to the callback function
*/
void setRxCB(rxCB3 *callback);
/**
* @fn setAppEUI
* @brief Sets the Application EUI.
* @param appeui Application EUI
* @return Returns true if successful, otherwise false
*/
bool setAppEUI(const char *appeui);
/**
* @fn setAppKEY
* @brief Sets the Application Key.
* @param appkey Application Key
* @return Returns true if successful, otherwise false
*/
bool setAppKEY(const char *appkey);
/**
* @fn setDevType
* @brief Sets the device type.
* @param classType Device class enum value
* @return Returns true if successful, otherwise false
*/
bool setDevType(eDeviceClass_t classType);
/**
* @fn setDataRate
* @brief Sets the data rate.
* @param dataRate Data rate enum value
* @return Returns true if successful, otherwise false
*/
bool setDataRate(eDataRate_t dataRate);
/**
* @fn setEIRP
* @brief Sets the transmission power.
* @param EIRP Transmission power value
* @return Returns true if successful, otherwise false
*/
bool setEIRP(uint8_t EIRP);
/**
* @fn setSubBand
* @brief Sets the sub-band.
* @param subBand Sub-band value
* @return Returns true if successful, otherwise false
*/
bool setSubBand(uint8_t subBand);
/**
* @fn enableADR
* @brief Enables or disables Adaptive Data Rate (ADR).
* @param adr If true, enables ADR; if false, disables ADR
* @return Returns true if successful, otherwise false
*/
bool enableADR(bool adr);
/**
* @fn setDevAddr
* @brief Sets the device address.
* @param devAddr Device address
* @return Returns true if successful, otherwise false
*/
bool setDevAddr(const uint32_t devAddr);
/**
* @fn setAppSKey
* @brief Sets the Application Session Key.
* @param appSKey Application Session Key
* @return Returns true if successful, otherwise false
*/
bool setAppSKey(const char *appSKey);
/**
* @fn setNwkSKey
* @brief Sets the Network Session Key.
* @param nwkSKey Network Session Key
* @return Returns true if successful, otherwise false
*/
bool setNwkSKey(const char *nwkSKey);
/**
* @fn join
* @brief Initiates the LoRaWAN join procedure. The device automatically attempts to join the network.
* @return Returns true if successfully initiated, otherwise false
*/
bool join();
/**
* @fn start
* @brief Starts the device's operation.
* @return Returns true if successful, otherwise false
*/
bool start();
/**
* @fn setLoRaAddr
* @brief Sets the LoRa address.
* @param addr LoRa address
* @return Returns true if successful, otherwise false
*/
bool setLoRaAddr(uint8_t addr);
/**
* @fn isJoined
* @brief Checks if the device is already joined to the network.
* @return Returns true if joined, otherwise false
*/
bool isJoined();
/**
* @fn sendPacket
* @brief Sends a data packet.
* @param v Value to be sent
* @return Returns true if successful, otherwise 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 Sends a data packet to a specific address.
* @param addr Destination address
* @param v Value to be sent
* @return Returns true if successful, otherwise 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 Sends a string data packet.
* @param data String data to be sent
* @return Returns true if successful, otherwise false
*/
bool sendPacket(String data);
/**
* @fn sendPacket
* @brief Sends a string data packet to a specific address.
* @param addr Destination address
* @param data String data to be sent
* @return Returns true if successful, otherwise false
*/
bool sendPacket(uint8_t addr, String data);
/**
* @fn sendATCmd
* @brief Sends a generic AT command.
* @param cmd Preformatted AT command without \r\n
* @return The response to the AT command
*/
String sendATCmd(String cmd);
/**
* @fn sendATCmdTest
* @brief Sends a test AT command.
* @param cmd Test AT command
* @return The response to the test AT command
*/
String sendATCmdTest(char *cmd);
/**
* @fn setPacketType
* @brief Sets the packet type.
* @param type Packet type (CONFIRMED_PACKET or UNCONFIRMED_PACKET)
* @return Returns true if successful, otherwise false
*/
bool setPacketType(ePacketType_t type = UNCONFIRMED_PACKET);
/**
* @fn getDevEUI
* @brief Retrieves the device EUI.
* @return The device EUI as a string
*/
String getDevEUI();
/**
* @fn getNetID
* @brief Retrieves the network ID.
* @return 3-byte network ID information
*/
uint32_t getNetID();
/**
* @fn getDevAddr
* @brief Retrieves the device address. In OTAA mode, this address is assigned by the gateway.
* @return 4-byte device address information
*/
uint32_t getDevAddr();
/**
* @fn getDataRate
* @brief Retrieves the current data rate.
* @return The current data rate
*/
uint8_t getDataRate();
/**
* @fn getEIRP
* @brief Retrieves the current transmission power.
* @return The current transmission power
*/
uint8_t getEIRP();
/**
* @fn getRSSI
* @brief Retrieves the Received Signal Strength Indicator (RSSI).
* @return The RSSI value
*/
int16_t getRSSI();
/**
* @fn getSNR
* @brief Retrieves the Signal-to-Noise Ratio (SNR).
* @return The SNR value
*/
int8_t getSNR();
/**
* @fn atTest
* @brief Executes an AT test command.
* @return The result of the test command
*/
bool atTest();
11. Product Compatibility
This product is theoretically compatible with all 3.3V and 5V Arduino mainboards. The table below lists the testing status of this product on various mainboards.
Mainboard Name | Functioning Normally | Function Abnormal | Not Verified |
---|---|---|---|
Arduino Uno | √ | ||
Arduino MEGA2560 | √ | ||
Arduino Leonardo | √ | ||
FireBeetle-ESP8266 | √ | ||
FireBeetle-ESP32 | √ | ||
FireBeetle 2 ESP32-E | √ | ||
micro:bit | √ |
12. Downloads
13. FAQ
Q: Why does switching the DIP switch to change the communication mode not work?
A: After switching the communication mode while the module is powered on, you need to power cycle (reboot) the module for the change to take effect.
Q: What is the communication range of the module?
Stable Communication Range Maximum Communication Range EU868 Version 1.2 km (urban)/4 km (open area) 1.4 km (urban)/4.4 km (open area) US915 Version 1.5 km (urban)/4.5 km (open area) 2 km (urban)/4.7 km (open area) The above test data is for reference only. Communication range is significantly affected by environmental factors (such as traffic density, weather conditions, and base station interference). The actual range should be confirmed through real-world deployment.
For more questions and interesting applications, you can visit the forum for reference or posting.