文章程式碼顯示

2019年1月12日 星期六

《進階※應用篇》寫程式Arduino教學 - 08:Lora 長距無線傳輸 SX1278 1W 433MHZ 基礎

先前使用過 RF 與 uart 無線傳輸後,一直想碰碰更長距離的傳輸
畢竟先前使用的無線傳輸其功率較小
頂多傳個 100m 就是極限了
甚至使用 RF 433MHz 只能無線傳輸個 5~6 米 ,而且拐個彎遇到水泥牆就斷線了
這讓我覺得很不便,如果不能長距離傳輸我何必弄的這麼麻煩呢?

Lora 是這幾年才出現的無線傳輸協議
其號稱可以傳輸到 km 等級的
於是我就到沒屋頂拍賣買了一組來玩玩

我購買的 Lora 模組規格為以下


商品型號:E32 (433T30D). (舊型號 E32 433-TTL-1W)

規格:

LoRa IC:SX1278
頻率:內定433MHZ (範圍 410 - 441 MHZ)
功率:30dbm (1W)
參考距離:8Km
發射電流:610mA (@30dbm)
接收電流:20mA
休眠電流:5uA
接收感度:-147dbm (空速 0.3 kbps)
通訊方式:展頻
價格 :單個 500 NT (需一次買兩個成一對)

以上的訊息是我從賣家的購買資訊中複製過來的
有興趣的可以在沒屋頂找找,很容易就能找到我是購買哪一家的
順到一提,我是搭配 6db 天線使用

剛買來的時候遇到了一些坑,所以就寫了這篇文分享一下最後的心得
先說結論,在空速 0.3kbps (也就是較慢的傳輸速率) 的情況下
直線距離可傳輸約 2.3 km 左右 (中間有隔許多建築物)
雖然不到賣家敘述的 8km (依賣家所述,8 km 要在空曠處才可以達到)
但這樣的傳輸距離我已經很滿意了

正文開始

剛買來這個 SX1278 Lora 模組的時候,需要先使用廠商自帶的軟體進行一下設定
因為我是成對買的,本來以為可以直接使用
但搞來搞去後發現廠商出廠時預設模組為 "廣播模式"(後述) 導致我一直失敗
後來設定為 "點對點模式"(後述) 就成功了

首先我們看看軟體的介面
與模組的溝通需額外使用一個 FT232 透過 Uart 讓電腦與模組進行連線
需注意的是,SX1278 模組的 I/O 可接受電壓為 3.3~3.7V
所以我在 FT232 的 Tx 端額外加上分壓電組降至約 3.4V 後才連接至 SX1278
電路圖我就省略不給了

硬體確定連接正確並打開該溝通的軟體後,選好 COM Port
先點選打開串口,接著點選讀取參數
若成功連接上 SX1278 的話就會跳出參數讀取成功的視窗

於參數設定模式(休眠模式)時 : SX1278  的 M0 與 M1 短接,並且使用 10K 歐姆的上拉電阻至 SX1278 的 Vcc


我們來看看有什麼東西可以進行設置



波特率 : 即為 FT232 <-> SX1278 之間的 Baudrate ,預設為 9600

奇偶校驗 : 這邊不用動,就選 8N1 就行了

空中速率 : 最快可以達到 19.2 Kbps ,理論上來說速度越快傳輸的距離會越短,且可能有數據丟失的狀況會發生。在我的應用中我想測試這個模組能傳輸的最遠極限距離為多少,所以我選擇最慢的 0.3 kbps

發射功率 : 我選最大的 30dbm

前向糾錯 : 這就是 Lora 協議一個很特殊的地方,基本上這是要打開的。至於是什麼意思,隨意 Google 一下就有,在這我就不多說了

傳輸方式 : SX1278 的傳輸方式分為兩種

第一為透傳模式(也就是廣播模式) : 這個模式可以使多個 SX1278 模組成為一個網路,只要所有 SX1278 的頻率通道都設置為相同,在該通道(波段)的所有 SX1278 都可以收到訊息

第二為定點模式(也就是點對點傳輸,或更簡易理解為特定的兩個 SX1278 之間的傳輸) : 由於我就只有買兩個 SX1278 ,所以我實際上就是需要點對點傳輸

Hint : 廠商出廠預設值為透傳模式,這也是我一開始為什麼卡很久無法成功的原因。設置為定點模式後就解決了




傳輸的規格

1. 目標地址(也就是接收方的模塊地址),以上圖舉例,若我們想要使用另外一個 SX1278 傳輸數據到上圖中的 SX1278 ,則我們就要在發送端先發送 0xea 再發送 0x01

2. 只發送目標地址是不夠的,我們還要接著發送目標信道(也就是上圖中的頻率信道,白話文就是"波段")

同樣以上圖舉例,若頻率信道為 13 ,則表示我們使用的波段為 410Mhz + 13*1Mhz = 423 Mhz 。將其轉換為十六進制為 0x0D

3. 最後我們再接著發送數據


總結舉例  : 若我們要將數據 "0xAA" 這個值發送到上圖的 SX1278 模組 (地址:ea01,通道:13) 則我們要連續發送 「四個數值」,分別為

0xea, 0x01, 0x0D, 0xAA

這樣上圖中的 SX1278  就會收到 0xAA 的數據





以下我給出一個發送端很簡單的 Arduino 程式碼(傳送接收方的地址 + 頻段 + 1byte的數據(0xAA))

#define LED 13
#define AUX 2

/* 含接收方的地址 + 頻段 + 1byte的數據(0xAA) */
/* 若此處宣告為 char 陣列,則使用 Serial.print 函數來發送 */
/* 若此處宣告為 byte 陣列,則使用 Serial.write 函數來發送 */
const char data[] = {0xEA,0x01,0x0D,0xAA};
//const byte data[] = {0xEA,0x01,0x0D,0xAA};

// ===== 等待 Lora 晶片不繁忙 =====
void waitAUX(){
  while(!digitalRead(AUX));
  delay(10);
}

// ===== 傳送資料 =====
void sendDataByHexArray (const char* data, int dataSIZE){
  waitAUX();  
  for(int i = 0; i < dataSIZE; i++){
    Serial.print(data[i]);
    //Serial.write(data[i]);
    delay(2);
  }
  Serial.flush();  
  waitAUX();
}

void setup() {
  Serial.begin(9600);
  pinMode(LED,OUTPUT);
}

void loop() {
  pinMode(LED,!digitalRead(LED));
  sendDataByHexArray (data, ( sizeof(data)/sizeof(data[0]) ) );
  delay(2000); //適時的delay
}


接收端

#define LED 13

byte incomingByte = 0;

void setup() {
  Serial.begin(9600);
  pinMode(LED,OUTPUT);
}

void loop() {
  if (Serial.available() > 0) {
    incomingByte = Serial.read(); //接收到數據0xAA    
    Serial.print(incomingByte); //此函數預設會在Arduino IDE 的監看埠視窗列印出十進制,故得 "170"
    digitalWrite(LED,!digitalRead(LED));
    Serial.flush();
  }    
}


注意,因我直接使用 Arduino 的 pin0 & pin1 接腳作為與 SX1278 的通訊接腳
所以你會發現,接收端的 Serial.print(incomingByte); 語句實際上會讓接收端的 SX1278 再發射出數據

只不過因為格式不符,所以只是白發送而已

較好的方式是使用 SoftwareSerial.h (使用 I/O 腳位模擬 Uart 通訊),來與 SX1278 溝通會更好一些 (於下篇文章中使用)


補充 : SX1278 與 Arduino 之間的硬體接線

1. SX1278 與 Arduino 的 Rx 與 Tx 對接,並且需注意 SX1278 的 I/O 限制電壓為 3.3~3.7v ,所以由 Arduino Tx 送出來的數據需要分壓後才能餵進  SX1278

2.  於參數設定模式(休眠模式)時 : SX1278  的 M0 與 M1 短接,並且使用 10K 歐姆的上拉電阻至 SX1278 的 Vcc

3. 於工作模式時 : SX1278  的 M0 與 M1 短接並直接接至 GND

4. Aux 需連接到 Arduino 的某個接腳,並且設置為 INPUT Mode 。藉由 Aux 可以判斷 SX1278 是否忙碌中




我的 Youtube 頻道,一定要訂閱
我將定期推出程式語言的新手教學影片




↓↓↓ 連結到部落格方針與索引 ↓↓↓

Blog 使用方針與索引