LoRa 是什麼?
LoRa 長距離通訊是 IoT 領域最重要的 LPWAN(低功耗廣域網路)技術之一。LoRa 以極低的功耗提供數公里級的通訊距離,使其成為智慧城市、農業監控、工業感測網路等場景的首選方案。

從上圖可以看到,LoRa 在通訊距離上遙遙領先 WiFi 和 BLE,同時功耗極低,一顆電池可工作數年。代價是傳輸速率低(0.3~50 kbps),但對 IoT 感測器來說已經足夠。
LoRa 技術原理
LoRa 的核心是 CSS(Chirp Spread Spectrum,線性調頻展頻) 調變技術:
- Chirp:頻率隨時間線性變化的訊號(向上 = up-chirp,向下 = down-chirp)
- 展頻增益:訊號在寬頻譜上擴散,對抗干擾和都卜勒效應
- SF(Spreading Factor):展頻因子(7~12),SF 越高 → 距離越遠、速率越慢
- BW(Bandwidth):頻寬(125/250/500 kHz),BW 越高 → 速率越快、靈敏度越低
LoRa 調變的關鍵參數關係:
符碼率 Rs = BW / 2^SF
位元率 Rb = SF × Rs × (4 / (4 + CR))
範例(SF=12, BW=125kHz, CR=1):
Rs = 125000 / 4096 ≈ 30.5 symbols/s
Rb = 12 × 30.5 × 0.8 ≈ 293 bps
LoRa 封包格式
LoRa 封包由三個部分組成:
- Preamble(前導碼):一串連續的 up-chirp,接收端用於檢測訊號到來並同步時脈。長度可設定(6~65535 symbols),預設 8 個 symbols。
- SFD(Start Frame Delimiter):固定模式的 down-chirp,標示前導碼結束和資料開始。
- PHDR(實體層標頭)+ PHDR_CRC:包含 Payload 長度、編碼率、CRC 啟用等資訊(僅在隱式模式下可省略)
- Payload:實際資料(最大 255 bytes)
- Payload CRC:16-bit CRC 錯誤檢測
LoRaWAN 通訊協定
LoRa 是實體層調變技術,LoRaWAN 是建立在其上的 MAC 層通訊協定,由 LoRa Alliance 標準化。
裝置類型
| Class | 說明 | 下行時機 | 功耗 |
|---|---|---|---|
| Class A | 所有 LoRaWAN 裝置必備 | 上行後開啟 RX1/RX2 視窗 | 最低 |
| Class B | 增加 Beacon 定期接收視窗 | Beacon 時間槽 | 中等 |
| Class C | 持續監聽下行 | 隨時 | 最高 |
實務上 90% 的 IoT 感測器使用 Class A:裝置發送上行資料 → 開啟 RX1(1 秒後)和 RX2(2 秒後)視窗接收伺服器回應 → 回到睡眠。
OTAA 啟用流程
裝置加入 LoRaWAN 網路有兩種方式:OTAA(Over-The-Air Activation)和 ABP(Activation By Personalization)。OTAA 是推薦方式:
- Join Request:裝置廣播 Join Request,包含 DevEUI(裝置唯一 ID)、AppEUI(應用唯一 ID)、DevNonce(隨機數)
- Gateway 轉發:LoRa Gateway 收到後透過 TCP/IP 轉發到 Network Server
- Network Server 驗證:檢查 DevNonce 是否重複,用 AppKey 計算 MIC 驗證完整性
- Join Accept:Server 回傳 AppNonce、NetID、DevAddr、RX 參數等,使用 AppKey 加密
- 裝置解密:裝置用 AppKey 解密 Join Accept,取得 DevAddr 和 Session Keys(NwkSKey + AppSKey)
ESP32 + SX1278 硬體接線
| SX1278 | ESP32 | 說明 |
|---|---|---|
| 3.3V | 3.3V | 電源(注意電流 > 100mA) |
| GND | GND | 共地 |
| NSS | GPIO 5 | SPI Chip Select |
| SCK | GPIO 18 | SPI 時脈 |
| MOSI | GPIO 23 | SPI 資料輸入 |
| MISO | GPIO 19 | SPI 資料輸出 |
| DIO0 | GPIO 2 | 中斷(封包接收完成) |
| RST | GPIO 14 | 重置(低電位觸發) |
Arduino 程式碼:LoRa 點對點通訊
使用 LoRa.h 函式庫(基於 SX1278),最簡單的發送與接收範例:
// ESP32 LoRa 發送端(Sender)
#include
#include
// SPI 腳位定義(ESP32 預設 VSPI)
#define SS 5
#define RST 14
#define DIO0 2
void setup() {
Serial.begin(115200);
LoRa.setPins(SS, RST, DIO0);
if (!LoRa.begin(915E6)) { // 頻率:915 MHz(北美)/ 868 MHz(歐盟)/ 923 MHz(亞洲)
Serial.println("LoRa 初始化失敗");
while (1);
}
LoRa.setSpreadingFactor(12); // SF12:最遠距離
LoRa.setSignalBandwidth(125E3); // BW 125 kHz
LoRa.setCodingRate4(5); // CR = 4/5
LoRa.setTxPower(20); // 發射功率 20 dBm(最大值)
Serial.println("LoRa Sender 啟動");
}
void loop() {
float temp = 25.0 + random(-50, 50) / 10.0;
float hum = 60.0 + random(-30, 30) / 10.0;
LoRa.beginPacket();
LoRa.print("TEMP:");
LoRa.print(temp, 1);
LoRa.print(",HUM:");
LoRa.print(hum, 1);
LoRa.endPacket();
Serial.printf("已發送:T=%.1f H=%.1f\n", temp, hum);
delay(60000); // 每分鐘發送一次
}
// ESP32 LoRa 接收端(Receiver)
#include
void setup() {
Serial.begin(115200);
LoRa.setPins(5, 14, 2);
if (!LoRa.begin(915E6)) {
Serial.println("LoRa 初始化失敗");
while (1);
}
LoRa.setSpreadingFactor(12);
LoRa.setSignalBandwidth(125E3);
LoRa.setCodingRate4(5);
Serial.println("LoRa Receiver 啟動,等待資料...");
}
void loop() {
int packetSize = LoRa.parsePacket();
if (packetSize) {
String data = "";
while (LoRa.available()) {
data += (char)LoRa.read();
}
int rssi = LoRa.packetRssi();
float snr = LoRa.packetSnr();
Serial.printf("收到: %s | RSSI: %d dBm | SNR: %.1f dB\n",
data.c_str(), rssi, snr);
}
}
使用 LoRaWAN 協定(MCCI LoRaWAN Library)
若使用 LoRaWAN 協定(需註冊 TTN / ChirpStack),程式碼如下:
// ESP32 LoRaWAN Class A 範例(MCCI LoRaWAN 函式庫)
#include
#include <hal/hal.h>
#include
// OTTA 憑證(來自 TTN Console)
static const u1_t PROGMEM APPEUI[8] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
static const u1_t PROGMEM DEVEUI[8] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
static const u1_t PROGMEM APPKEY[16] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
void os_getArtEui (u1_t* buf) { memcpy_P(buf, APPEUI, 8); }
void os_getDevEui (u1_t* buf) { memcpy_P(buf, DEVEUI, 8); }
void os_getDevKey (u1_t* buf) { memcpy_P(buf, APPKEY, 16); }
// SPI 腳位
const lmic_pinmap lmic_pins = {
.nss = 5,
.rxtx = LMIC_UNUSED_PIN,
.rst = 14,
.dio = {2, LMIC_UNUSED_PIN, LMIC_UNUSED_PIN},
};
static uint8_t txData[] = "Hello LoRaWAN!";
static osjob_t sendjob;
void do_send(osjob_t* j) {
if (LMIC.opmode & OP_TXRXPEND) {
Serial.println("上一個傳送還未完成");
} else {
LMIC_setTxData2(1, txData, sizeof(txData)-1, 0);
Serial.println("傳送中...");
}
os_setTimedCallback(&sendjob, os_getTime() + sec2osticks(60), do_send);
}
void onEvent(ev_t ev) {
switch (ev) {
case EV_JOINED:
Serial.println("已加入 LoRaWAN 網路");
LMIC_setLinkCheckMode(0);
break;
case EV_TXCOMPLETE:
Serial.println("傳送完成");
if (LMIC.dataLen) {
Serial.printf("收到下行: %s\n", LMIC.frame + LMIC.dataBeg);
}
break;
default:
break;
}
}
void setup() {
Serial.begin(115200);
LMIC_reset();
LMIC_startJoining();
do_send(&sendjob);
}
void loop() {
os_runloop_once();
}
LoRa 參數調校指南
| 場景 | SF | BW | CR | TP (dBm) | 範圍 | 空傳時間 |
|---|---|---|---|---|---|---|
| 極遠距離 | 12 | 125 | 4/5 | 20 | ~15 km | ~2.3s (51 bytes) |
| 平衡 | 9 | 125 | 4/5 | 17 | ~5 km | ~0.3s |
| 高速 | 7 | 250 | 4/8 | 14 | ~1 km | ~0.04s |
天線設計注意事項
- 匹配阻抗:SX1278 輸出阻抗 50Ω,天線也須 50Ω
- 天線長度:λ/4 單極天線最簡單(915MHz → ~8.2cm,868MHz → ~8.6cm)
- 地平面:單極天線需要接地平面,PCB 上預留足夠面積
- SWR 測試:使用網路分析儀調整匹配網路(L/C 元件)
- 法規限制:各國對 ISM 頻段發射功率有不同規定(台灣 915MHz ≤ 1W EIRP)
LoRa vs 其他 IoT 通訊技術
| 特性 | LoRa/LoRaWAN | NB-IoT | Sigfox | WiFi | BLE |
|---|---|---|---|---|---|
| 頻段 | Sub-GHz ISM | LTE 授權頻段 | Sub-GHz ISM | 2.4/5 GHz | 2.4 GHz |
| 範圍(市區) | 2~5 km | 1~3 km | 3~10 km | ~50 m | ~100 m |
| 資料速率 | 0.3~50 kbps | ~200 kbps | ~100 bps | Mbps~Gbps | ~2 Mbps |
| 電池壽命 | ~10 年 | ~5 年 | ~10 年 | 數天~數週 | 數月 |
| 雙向 | ✓(受限) | ✓ | ✗(上行為主) | ✓ | ✓ |
| 建置成本 | 低(自建 Gateway) | 高(需 SIM) | 中(年費) | 低 | 低 |
| 適合場景 | 感測器網路 | 車聯網、電表 | 極簡感測器 | 串流、網頁 | 穿戴裝置 |
實務經驗:LoRa 通訊距離測試
// LoRa 距離測試 — 持續發送 RSSI 封包
void loop() {
LoRa.beginPacket();
LoRa.print("RSSI_TEST");
LoRa.endPacket();
delay(5000);
// 每秒檢查是否收到回應
if (LoRa.parsePacket()) {
Serial.printf("收到回應 | RSSI: %d SNR: %.1f\n",
LoRa.packetRssi(), LoRa.packetSnr());
}
}
實測結果(SF12, BW125, 20dBm, 空曠環境):
- 500m:RSSI -85~-95 dBm,SNR 8~12 dB(穩定連線)
- 1km:RSSI -100~-110 dBm,SNR 5~8 dB(偶爾掉封包)
- 2km:RSSI -115~-125 dBm,SNR 0~3 dB(需重傳機制)
- 5km:RSSI -130 dBm 以下,僅視距可見時可收到
總結
LoRa 以極低的功耗和遠距離通訊能力,成為 IoT 感測器網路的首選方案。ESP32 + SX1278 的組合提供了完整的 LoRa 節點實作路徑,從簡單的點對點通訊到 LoRaWAN 協定都能勝任。
選擇建議:
- 簡單原型:使用 LoRa.h 函式庫做點對點通訊
- 正式部署:使用 MCCI LoRaWAN 函式庫 + TTN / ChirpStack
- 高容量場景:LoRaWAN Class B/C + 多 Gateway 部署
文章評論