剛完成 nRF24L01 無線傳送溫濕度,遠端則在接收後呈現在 LCD 屏幕上的實作,剛好最近在淘X買了兩個由安信可製造的 LoRa-01 SX1278,也來瞭解一下 LoRa 的基本知識,以及如何使用 Arduino 連接後,進行資料的傳送與接收。本實作繼續使用AHT10的溫濕度感測器,將測得的值傳送給另一個 Lo-Ra接收設備,在 LCD1602 顯示溫濕度值。
LoRa技術可用於將雙向信息傳輸到長距離而不會消耗很多功率,通常可達到15-20km的距離,根據 thethingsnetwork.org 聲稱它可以使用 25mW 的功率傳輸距離達到 766 公里,前提是節點與網關之間沒有障礙的最佳通訊品質時測得的。LoRa使用世界各地都可使用的未許可頻率。這些是最廣泛使用的頻率:
我購買的 LoRa 擴頻無線模組,是安信可採用 SX1278 開發的遠程調制解調器,用於超長距離擴頻通信,抗干擾性強,能夠最大限度降低電流消耗。引出的接腳跟 NRF24L01 模組一樣,如果想要遠距離傳輸數據,可以直接替換NRF24L01,只要更改一下程式即可,不需要更改硬體設計。
LoRa本身也有缺點,為了以低功耗傳輸,其頻寬帶很小,最大帶寬約為5.5 kbps,這意味著只能發送少量數據。無法通過此技術發送音頻或視頻,它僅適用於傳輸較少的信息(例如傳感器值)。
SX1278特點:
如為下載程式庫(Library)安裝方法請參考另一篇文章:Arduino筆記:安裝 Arduino IDE 程式庫(Library)。
◾ begin(frequency);
以指定的頻率進行 Lora 物件初始化。frequency 頻率以 Hz 為單位,可使用433E6(亞洲),868E6(歐洲) 915E6(北美)三種頻率。
◾ beginPacket(implicitHeader);
開始循序發送封包。implicitHeader(選項)true 啟用隱式頭模式,false啟用顯式頭模式(預設)
◾ endPacket();
結束循序發送封包。
◾ available();
回傳可以讀取的 Byte 數。
◾ parsePacket(size);
檢查是否已經收到封包。size為選項,假使大於 0 ,啟用 implicit header 模式,並使用指定的 size 字節,預設為 explicit header 模式。
回傳值為封包的長度,或傳回 0 表示沒有收到封包。
◾ packetRssi();
回傳最後接收封包的平均 RSSI(Received Signal Strength Indicator),接收信號强度指示。
如無法根據上圖連接引腳,可以使用下表來確保正確連接。
發射端:
註:由於找不到 LoRa-01 SPI介面的 Fritzing圖,改以 16 Pin 引腳示意。
接收端:
註:由於找不到 LoRa-01 SPI介面的 Fritzing圖,改以 16 Pin 引腳示意。
在接收端,原本每次讀取不到資料後,會 delay 1秒鐘,但結果呈現接收頻率不規則的情況,有時會多達10幾秒才收到 1 筆資料,。將 delay(1000); 這行當作註解後,接收資料變得比較順利,但仍有會遺失封包的情況。以下是傳送端送出資料的串列埠視窗:
以下是傳送端送出資料的串列埠視窗:
[LoRa技術]
LoRa(Long Range)是Semtech開發的LPWAN(Low-Power Wide-Area Network,低功率廣域網路)協定,是依chirp展頻(CSS)技術衍生的展頻調變技術為基礎[1]。是由法國格勒諾布爾的Cycleo公司所發展,後來被LoRa Alliance的創立成員Semtech所收購。[維基百科]LoRa技術可用於將雙向信息傳輸到長距離而不會消耗很多功率,通常可達到15-20km的距離,根據 thethingsnetwork.org 聲稱它可以使用 25mW 的功率傳輸距離達到 766 公里,前提是節點與網關之間沒有障礙的最佳通訊品質時測得的。LoRa使用世界各地都可使用的未許可頻率。這些是最廣泛使用的頻率:
- 歐洲868 MHz
- 北美915 MHz
- 亞洲433 MHz頻段
我購買的 LoRa 擴頻無線模組,是安信可採用 SX1278 開發的遠程調制解調器,用於超長距離擴頻通信,抗干擾性強,能夠最大限度降低電流消耗。引出的接腳跟 NRF24L01 模組一樣,如果想要遠距離傳輸數據,可以直接替換NRF24L01,只要更改一下程式即可,不需要更改硬體設計。
LoRa本身也有缺點,為了以低功耗傳輸,其頻寬帶很小,最大帶寬約為5.5 kbps,這意味著只能發送少量數據。無法通過此技術發送音頻或視頻,它僅適用於傳輸較少的信息(例如傳感器值)。
SX1278特點:
- LoRa擴頻調製技術
- 超遠通信距離15KM
- +20dBm-100mW電壓變化時恆定的射頻功率輸出
- 高靈敏度:低至-148dBm
- 半雙工SPI通訊
- 可編程比特率高達300kbps
- 支持FSK、GFSK、MSK、GMSK、LoRa§及OOK調製方式
- 127dB的RSSI動態範圍
- 自動射頻信號檢測,CAD模式和超高速AFC
- 帶有CRC、高達256字節的數據包引擎
- 小體積雙列郵票孔貼片封裝
- 帶屏蔽殼
- 彈簧天線(Ra-01)或IPEX外接天線(Ra-02)
[安裝程式庫Library]
除了硬體的連接外,還需要 arduino-LoRa 程式庫,才能驅動或管理這個無線射頻模組的接收與發射。本實作需要安裝以下程式庫:如為下載程式庫(Library)安裝方法請參考另一篇文章:Arduino筆記:安裝 Arduino IDE 程式庫(Library)。
[材料]
- Arduino UNO x2
- LoRa-01 SX1278 x2
- LCD1602液晶顯示器
- I2C/介面 LCD1602轉接板 PCF8574
- 麵包板 x2
- AHT10 溫濕度感測器 x1
- 排線 n 條
[arduino-LoRa 程式庫]
arduino-LoRa 程式庫控制 SX1728 LoRa 物件的方法如下:◾ begin(frequency);
以指定的頻率進行 Lora 物件初始化。frequency 頻率以 Hz 為單位,可使用433E6(亞洲),868E6(歐洲) 915E6(北美)三種頻率。
◾ beginPacket(implicitHeader);
開始循序發送封包。implicitHeader(選項)true 啟用隱式頭模式,false啟用顯式頭模式(預設)
◾ endPacket();
結束循序發送封包。
◾ available();
回傳可以讀取的 Byte 數。
◾ parsePacket(size);
檢查是否已經收到封包。size為選項,假使大於 0 ,啟用 implicit header 模式,並使用指定的 size 字節,預設為 explicit header 模式。
回傳值為封包的長度,或傳回 0 表示沒有收到封包。
◾ packetRssi();
回傳最後接收封包的平均 RSSI(Received Signal Strength Indicator),接收信號强度指示。
[接線圖]
LoRa模組原有16個引腳,其中有 6 個是 GPIO 引腳使用,範圍從 DIO0 到 DIO5,4 個由接地引腳使用。該模組工作在 3.3V 電壓,因此 LoRa 上的 3.3V 腳連接到Arduino UNO 板上的3.3v 引腳。修改後的 SPI 模組,接腳跟 nRF24L01 一樣,如下圖:如無法根據上圖連接引腳,可以使用下表來確保正確連接。
發射端:
| Arduino Uno | LoRa SX1278模組 | AHT10 |
|---|---|---|
| GND | GND | GND |
| 3.3V | 3.3 | - |
| 5V | - | VCC |
| D2 | G0/DIO0 | - |
| D9 | RST | - |
| D10 | EN/NSS | - |
| D11 | MOSI | - |
| D12 | MISO | - |
| D13 | SCK | - |
| A5 | - | SCL |
| A4 | - | SDA |
註:由於找不到 LoRa-01 SPI介面的 Fritzing圖,改以 16 Pin 引腳示意。
接收端:
| Arduino Uno | nRF24L01 | LCD1602 |
|---|---|---|
| GND | GND | GND |
| 3.3V | 3.3 | - |
| 5V | - | VCC |
| D2 | G0/DIO0 | - |
| D9 | RST | - |
| D10 | EN/NSS | - |
| D11 | MOSI | - |
| D12 | MISO | - |
| D13 | SCK | - |
| SCL | - | SCL |
| SDA | - | SDA |
註:由於找不到 LoRa-01 SPI介面的 Fritzing圖,改以 16 Pin 引腳示意。
[傳送端程式]
連接 Arduino 和 LoRa SPI 模組連接後,從 AHT10 傳感器讀取得的溫濕度值,透過 LoRa 送到遠端的 Lora,每秒傳送一筆資料。#include <SPI.h>
#include <LoRa.h>
#include <AHT10.h>
AHT10 myAHT10(AHT10_ADDRESS_0X38);
float temp = 0;
float humidity = 0;
void setup() {
Serial.begin(9600);
Serial.println("LoRa Sender");
if (!LoRa.begin(433E6))
{
Serial.println("Starting LoRa failed!");
while(1);
}
while (myAHT10.begin() != true) {
Serial.println(F("AHT10 not connected..."));
delay(5000);
}
Serial.println(F("AHT10 initial OK"));
}
void loop() {
// 讀取 AHT10 的溫濕度
temp = myAHT10.readTemperature(); //讀取 AHT10 溫度
humidity = myAHT10.readHumidity(); //讀取 AHT10 濕度
Serial.print("Temperatura: ");
Serial.println(temp);
Serial.print(" Humidity: ");
Serial.println(humidity);
String msg = String(temp)+" "+String(humidity);
Serial.print("Sending message :");
Serial.println(msg);
LoRa.beginPacket();
LoRa.print(msg);
LoRa.endPacket();
delay(1000); // 每1秒鐘送一次資料
}
[接收端程式]
從 Ro-Ra 接收到資料後,由 Arduino UNO 顯示在 LCD 1602 屏幕上。#include <SPI.h>
#include <LoRa.h>
#include <string.h>
#include <LiquidCrystal_I2C.h> // 引用 LiquidCrystal_I2C Library
LiquidCrystal_I2C lcd(0x27,16,2); // 設定 LCD 位址為 0x27,有 16 個字元 2 列
void setup() {
Serial.begin(9600);
Serial.println("LoRa Receiver");
if (!LoRa.begin(433E6)) {
Serial.println("Starting LoRa failed!");
while (1);
}
lcd.init(); // 初始化 lcd
lcd.backlight(); // 設定背板為亮
}
void loop() {
String str="";
String tempc="";
String humidity="";
int packetSize = LoRa.parsePacket();
if (packetSize) {
Serial.print("Received packet '");
// 讀取封包
while (LoRa.available()) {
str=str+((char)LoRa.read());
}
tempc = str.substring(0,5);
humidity = str.substring(6,12);
Serial.print(str);
Serial.print(" ");
// Serial.print(tempc);
// Serial.print(" ");
// Serial.print(humidity);
Serial.print("' with RSSI ");
Serial.println(LoRa.packetRssi());
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("Temp");
lcd.setCursor(9, 0);
lcd.print(tempc);
lcd.print(" C");
lcd.setCursor(0, 1);
lcd.print("Humidity");
lcd.setCursor(9, 1);
lcd.print(humidity);
lcd.print(" %");
}
// delay(1000);
}
[實作結果]
在接收端,原本每次讀取不到資料後,會 delay 1秒鐘,但結果呈現接收頻率不規則的情況,有時會多達10幾秒才收到 1 筆資料,。將 delay(1000); 這行當作註解後,接收資料變得比較順利,但仍有會遺失封包的情況。以下是傳送端送出資料的串列埠視窗:
以下是傳送端送出資料的串列埠視窗:





請問實測距離可以多遠?
回覆刪除我沒實測最遠的距離,測試的情境僅10多公尺,收發正常,改天找機會再測試最遠距離。
刪除Arduino Uno 邏輯電壓是5V,Ra-01邏輯運作電壓是1.8~3.7V,恐怕Ra-01已經內傷了!
回覆刪除兩個之間最好要加上邏輯電位轉換器。
Arduino也有提供3.3V的電壓,我接的是3.3V的Pin腳,謝謝提醒與說明。
刪除您可能會錯意了!
刪除SPI那一些 I/O(NSS、RST、MISO、DIO0..等等),從Arduino送出來的邏輯1是5V,不過Ra-01的邏輯1的運作電壓只有到3.7V,我才說有可能Ra-01已經內傷。
所以我認為文章後面寫接收端接收不到的問題,有很大的機會是Ra-01已經故障了,訊號送的怪怪的!
您好,我依您的程式發現接收端不能單獨顯示溫溼度,應該改成下面方式,可正常顯示
回覆刪除感謝您網站讓我受益良多
int packetSize = LoRa.parsePacket();
if (packetSize) {
Serial.print("Received packet '");
// 讀取封包
while (LoRa.available()) {
String LoRaData = LoRa.readString();
Serial.print(LoRaData);
tempc = LoRaData.substring(0,5);
humidity = LoRaData.substring(6,12);
}
Serial.print(" ");
Serial.print(tempc);
Serial.print(" ");
Serial.print(humidity);
Serial.print("' with RSSI ");
Serial.println(LoRa.packetRssi());
張貼留言