剛完成 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());
張貼留言