2017年9月12日 星期二

MQTT bridged LoRa networks with MicroPython on ESP32

Wei Lin
2017/09/12

緣由


  前一陣子做了 MQTT 的實驗,最近又開始接觸 LoRa,有天想到可以把這兩項技術結合在一起,採用 蜂巢網路的模式,透過 MQTT 串聯與整合 分散在各地區的 LoRa networks。

   為了以後可能的需要,就花了一個週末的時間先把這個模型做出來,如果以後我需要佈署自己的 LoRa 網路時就可以派上用場。

  目前只有做出這個模型,沒有經過壓力測試。我手上只有四個 LoRa transceivers,所以只能用這樣兩組 gateway + node 的組成來測試。

  不 follow LoRaWAN 的規範,純粹個人實驗。

GitHub repo.



LoRa 的優點

    LoRa 最近很熱門,因為它具有 範圍大,低耗能,成本低的特點:

  • 長距: 涵蓋面積大,只需要少數 gateways 即可涵蓋頗大的地理範圍。
  • 低耗能: 靈敏度可以到 -148dbm ,可以用較低的能量傳遞較遠的距離。
  • 末端節點成本低: 單一 channel 的 transceiver 並不算貴。
  • 平行作業: 使用無線電廣播,訊號可同時傳達 多個點。



出發點與目的

    其實我比較注重 如何建構 M2M (machine to machine) 的溝通機制,主要是想利用 LoRa 低成本、低耗能的優勢,用大範圍無線通訊 作為 M2M event system 中,事件推播的機制。



LoRa 的缺點

    但是如果要在城市中佈署 LoRa 網路,也是會遇到很多缺點與困難,例如:

  • 制高點得之不易: 制高點相對稀少 且可能有額外成本。
  • gateway 設備並不是很便宜:
    • 市面上的 LoRa gateway 通常具有同時多 channels 收發訊號的功能,價格由數千元至上萬元不等,實在不算便宜。
  • 整體資料throughput 不大,因為:
    • 障礙
      • 在都市叢林中會受到障礙與干擾的影響,傳輸速率受限。
    • 環境吵雜 訊號碰撞
      • 涵蓋範圍越大,表示其中的 nodes 越多,訊號碰撞的機率越高,整體有效的資料傳輸量較容易受到限制。
      • 訊號涵蓋範圍大,如果主要是為了 downlink 的用途的話 那就太棒了,因為發送的訊息可以同時送達範圍內所有的 nodes。但如果主要的用途是要從廣大地區收集資料回來,也就是以 uplink 為主的用途,那麼 涵蓋範圍越大,nodes 數量越多 越容易發生訊號碰撞的情況。
    • 傳輸速度不高
      • 為了要傳比較遠端距離,傳輸速度不能太快,這算是 傳輸距離遠 的代價。



想法

    主要的想法是:

  • 採用 GSM 蜂巢網路的模式

    • 城市中 建物障礙多,line of sight 難得,LoRa 訊號的傳輸功率開大的話,影響範圍更大,涵蓋的 node 數量會較多,容易會有更多的訊號碰撞。
    • 不如採用 GSM 蜂巢網路的模式,功率開小一點,gateway 多一點,每個 gateway 因為功率較小,涵蓋範圍也較小,範圍內的 node 數量少,訊號碰撞的機率就會跟著比較低,傳輸速率可以提高;而且 每個 gateway 的涵蓋範圍雖然不大,但因為數量多, 所以整體涵蓋範圍也不小,也比較容易消除訊號的死角,反而比較適合在城市之中佈署。
  • 以 MQTT 作為傳遞資料的 backbone
    • MQTT 因為採用 publish / subscribe 的模式,可以做到廣播的效果,也可以針對性地傳遞資料給指定的對象,相當彈性且高效能,可以做為 在各 gateways 之間傳遞資料的backbone。
    • 一個 gateway 其實就是一個 MQTT client,可以收發 MQTT 訊息。
  • gateway as woker
    • 以 Celery 的觀點來看,一個 gateway 也是一個 worker,我們可以透過 MQTT 傳達 message 給各個 gateways,指揮它們做特定的工作。各個 gateway 之間也可以藉此機制互相溝通與合作。




作法與特色

    主要的作法與特色是:

  • 定址
    • 每個 LoRa node 或者 gateway 都有一個 EUI-64 的地址
  • 無主機
    • gateways 們會互相分享與交換資料,並無中央主機來做管理。
  • Routing table 自動產生與更新
    • LoRa node 每次發射訊號的時候,會被依據訊號強度 自動 clustering 並歸屬到最接近的 gateway,由該 gateway 負責回應 ACK 或收發其他 LoRa packet。而且 gateways 之間會隨時互相交換 routing table 資料,LoRa node 可以無隙 roaming。
    • 可以用 RSSI 來做 地理位置定位 (Geolocation)。
  • 兩種傳遞資料的模式
    • 如果 payload 中有註明 目的地 的 EUI,則會藉由 MQTT 將之 route 到離目的地最近的 gateway 才轉而以 LoRa 的訊號發送出去。
      • 一個 LoRa node 可以 "撥號" 並傳遞資料給某一個特定的 LoRa node ,只要指定對方的 EUI 地址即可,payload 會由 gateways 自動做 routing,降低對其他地區不相關的 LoRa nodes 的干擾.
    • 如果 payload 中沒有註明 目的地 的 EUI,則會藉由 MQTT 將 payload 傳送給每一個 gateway,再轉為 LoRa 訊號發射出去給各 network 中的 LoRa nodes,效果等同是做全域的廣播。因此,台中,台北,高雄若各有一個 小型的 LoRa network,可以藉由此 MQTT 平台 串聯並視為單一個 LoRa network。
  • 降低佈署 gateway 的門檻
    • 成本低,每個 gateway 本身的硬體成本 相對低很多, 志願者負擔得起。
所使用的 Gateway (ESP32 + RFM96W)


市面上也有賣這種 整合 ESP32 + SX1278 的模組,
成本可以壓低到三百元以下


    • 不需要設定,只需要連上WiFi 網路,即可成為一個gateway,服務周圍幾百公尺內的 LoRa nodes。
  • 提升資料 throughput
    • 降低碰撞的機率
      • 因為可以依據 目的地的 EUI 位址決定 MQTT route 資料的路線,所以可以避免做全域性的廣播,可以傳遞資料並且避免干擾不相關的其他地區網路。
  • MQTT 與 LoRa 雙向的資料交換
    • 可以由 外部送一個 MQTT message 給 gateway,命令其發送 LoRa 訊號並傳遞資料給特定的 node 。
    • 可以藉由 MQTT 的機制收集 末端節點透過 LoRa 訊號 所傳送出來的資料。



實驗模型說明

  • 由左到右分別是 node2, gateway2, gateway1, node1
  • 使用 SF(Spreading Factor) 隔離:  node2, gateway2 的 SF = 9,node1, gateway1 的 SF = 8。這樣可以模擬兩個距離相當遠,原本無法相通訊息的 LoRa networks。
  • node1, node2 隨機 每隔 2~4 秒傳送一個 packet 給各自的 gateway。
  • node 或 gateway,收到 packet 之後 LED燈會閃一下。
  • gateway 收到 node 所傳來的訊號之後
    • 會透過 MQTT 互相交換網路拓樸資料。
    • 由最接近的 gateway 回應 ACK。
    • 會依據所收到的 payload 中所標註的 目的地 EUI,將 payload forward 給 最接近目的地 的 gateway 做 transmit。
  • 可以由 PC端發送 MQTT message 命令某一個 gateway 傳送 message中夾帶的 payload 給任一指定 EUI位址的 LoRa node。
  • node1 是用 ESP8266 做的,LED燈在上方,有點被擋住,透過電腦螢幕的鏡面反射反而看得比較清楚。


後記
  • 2017/09/15: 
    • 打破界線,將 SF 都設為 8,所以現在四個 device 彼此都會聽到對方的 LoRa 訊號,而兩個 gateways 就必須要能判斷一個訊號是由別的 gateway 還是  node 傳過來的,並且藉由 RSSI 來隨時判斷每個 node 要由哪一個 gateway 負責對應來收發 LoRa 訊號。
  • 最近入手這種 ESP32 + SX1278 LoRa + SSD1306 OLED 整合模組,整體設計相當簡潔,目前的價格大約台幣 300元,以後可能更便宜。

      為了兼容這個模組,特別加了一個 controller_esp_ttgo_lora_oled 的 subclass,並且將有使用到的 SSD1306 driver 含括進來。 雖然腳位定義不同,但已經都封裝在 controller 的子類別 (controller_esp_ttgo_lora_oled ) 中,所以應用的時候使用者可以如常使用 controller 所定義的 interface 即可,不需要去操煩底層實作的細節。





有個 display 還是比較方便一點,也許以後可以做個 LoRa 推文顯示器




參考資料