用LoRa實現的物聯網應用,到底好在哪裡?
一、概述
LoRa是semtech公司創建的低功耗局域網無線標準,我們知道,低功耗一般很難覆蓋遠距離,而遠距離一般功耗高,LoRa的名字翻譯就是遠距離無線電(Long Range Radio),它最大特點就是在同樣的功耗條件下比其他無線方式傳播的距離更遠,實現了低功耗和遠距離的統一,它在同樣的功耗下比傳統的無線射頻通信距離擴大3-5倍。
LoRa在物聯網應用中的無線技術有多種,可組成局域網或廣域網路。LoRa網路主要由終端(可內置LoRa模組)、閘道(或稱基站)、Server和雲四部分組成。
LoRaWAN的資料傳輸速率範圍為0.3 kbps至37.5 kbps,為了最大化終端設備電池的壽命和整個網路容量,LoRaWAN網路服務器通過一種速率自我調整(Adaptive Data Rate , ADR)方案來控制資料傳輸速率和每一終端設備的射頻輸出功率。
二、方案設計
本案例將通過LoRa技術實現對機房的環境檢測與控制。
一般情況下,一個企業的機房很少連接網路,即使連接網路了,也要花費不小的費用進行設備和線路的安裝。例如使用寬頻時要走網線,距離短,機房少可能還好,如果機房較多,距離較長,那麼安裝成本和人工成本就會迅速增加。如果安裝無線路由器,方法雖然可行,但是穿透力差,信號有時連接不上,想要增強信號,就要增加設備。
至於NB模組,如果信號良好,會是不錯之選。目前仍然有許多城市或者鄉鎮沒有覆蓋NB-IoT信號。所以NB模組適用於一些大城市。我們要想知道是否覆蓋物聯網信號,就看這個城市是否有共用單車。比如我所在的海南省,除了地級市,其他縣級市基本沒有覆蓋物聯網,因為那裡沒有共用單車。
LoRa有遠距離、低功耗以及低成本等優勢。LoRa的傳輸距離範圍長達15至20公里,低功耗的特性延長了電池使用壽命,免牌照的頻段、基礎設施以及節點/終端的低成本,以上特性都使LoRa的使用成本大幅降低。
所以就機房或者整棟建築大樓這個特定區域來講,採用LoRa技術來實現對機房的環境參數的採集與控制是最節省資源的辦法。它的穿透力適合佈局到整個辦公大樓。從而把它變成智慧建築是可行的。
三、方案實現
首先參考教程基於 TencentOS tiny 的 LoRaWAN 開發入門指南[1] 的介紹完成開發環境搭建,包括 MDK 軟體的安裝及配置、ST-Link 驅動安裝、串口軟體的安裝。
1. 硬體設計
(1)LoRa套件
本方案採用P-NUCLEO-LRWAN3套件,包括閘道和節點,可用於評估LoRaWAN網路。使用該套件,使用者可以輕鬆設置LPWAN網路,説明使用者學習LoRaWAN技術,瞭解如何在自己的應用程式中使用LoRaWAN技術。LoRa閘道套件由ST Nucleo-F746ZG底板和瑞興恒方基於SX1301的LRWAN_GS模組組成。
ST Nucleo LoRa節點套件由LRWAN_NS1擴展板和ST Nucleo-L073底板組成。其中 LRWAN_NS1擴展板集成瑞興恒方的RHF0M003 LoRaWAN模組,並集成了溫濕度感測器HTS221、氣壓感測器LPS22HB、3軸磁力感測器LIS3MDL、6軸姿態感測器LSM6DS3共4個I2C感測器件。
LoRa節點採集的資料通過LoRa閘道將資料上傳到物聯網雲平臺,實現對終端設備的控制和資料監控。
(2)LCD顯示
液晶屏是ST7735R,用於顯示即時採集的資料。例如溫度度,壓強,海拔等,以及控制的狀態指示。採用類比I2C的方式來實現寫指令。
(3)繼電器設計
繼電器模組主要用於220V交流電的開關,實現對電機或電燈的電源控制。電路中採用的是光耦進行電氣隔離,防止回流時對MCU的衝擊。依據這個電路,可以擴展出多路繼電器,實現控制各類設備。
(4)E53模組應用
採用E53 SC1模組,我是從小熊派物聯網開發套件中拿來用的。這個擴展模組集成有LED路燈,光照強度感測器BH1750以及EEPROM晶片24Cxx。我的設計思想是,通過光照強度感測器檢測機房亮暗度來決定是否開啟應急燈的充電或開啟機房燈光,保證應急搶修的需要。同時把相關控制資訊存儲到EEPROM,實現歷史記錄的查詢。以下是模組原理圖:
(5)LoRa節點整體外觀
右邊的兩個黑色按鍵和開發板上的藍色按鍵分別實現LED路燈、繼電器和LCD背光的本地控制。設計思路是脫離網路方便本地控制。
2. 軟體設計
(1)LoRa源碼實現
該套件可以很快實現上雲,通過官方提供的教程LoRa 溫濕度感測器接入指引[2],打通資料連接,隨後就是修改TencentOS tiny源碼中的LoRa案例。
以下是需要要上報雲端的參數,需要注意的是參數的順序要和雲端解析順序一致,否則會解碼失敗而讀到錯誤的資料。
uint16_t report_period = 1;
bool report_power_switch=0;
bool report_motor_fan=0;
float report_pressure=0;
float report_height=0;
float first_pressure=0;
float first_height=0;
extern float pressure_hPa;
extern float temperature_degC;
extern float height;
typedef struct device_data_st {
uint8_t temperature;
uint8_t humidity;
uint16_t period;
unsigned int quantity;
bool power_switch;
bool motor_fan;
float pressure;
float height;
} __PACKED__ dev_data_t;
以下是按鍵任務,功能是進行普通的按鍵掃描,檢測到相應按鍵後進行相應控制,同時把相關的控制狀態通過LCD顯示出來並回饋到雲端。
void key_task(void *arg){
int lcd_back_flag=1;
while(1) {
tos_task_delay(10);
if(HAL_GPIO_ReadPin(KEY1_GPIO_Port,KEY1_Pin)==GPIO_PIN_RESET)
{
tos_task_delay(100);
if(HAL_GPIO_ReadPin(KEY1_GPIO_Port,KEY1_Pin)==GPIO_PIN_RESET)
{
lcd_back_flag=~lcd_back_flag;
if(lcd_back_flag==1)
{
LCD_LED_CLR;//關閉LCD背光
}
else
{
LCD_LED_SET;//開LCD背光
}
}
}
if(HAL_GPIO_ReadPin(KEY2_GPIO_Port,KEY2_Pin)==GPIO_PIN_RESET)
{ tos_task_delay(100);
if(HAL_GPIO_ReadPin(KEY2_GPIO_Port,KEY2_Pin)==GPIO_PIN_RESET)
{
if(report_power_switch==1)
{
report_power_switch=0;
HAL_GPIO_WritePin(LD2_GPIO_Port,LD2_Pin,GPIO_PIN_RESET);
printf("LED OFF: %d\n",report_power_switch);
Gui_DrawFont_GBK16(5,125,RED,BLACK ,(uint8_t*)"LED:OFF");
}
else
{
report_power_switch=1;
HAL_GPIO_WritePin(LD2_GPIO_Port,LD2_Pin,GPIO_PIN_SET);
printf("LED OFF: %d\n",report_power_switch);
Gui_DrawFont_GBK16(5,125,GREEN,BLACK ,(uint8_t*)"LED:ON");
}
}
}
if(HAL_GPIO_ReadPin(KEY3_GPIO_Port,KEY3_Pin)==GPIO_PIN_RESET)
{ tos_task_delay(100);
if(HAL_GPIO_ReadPin(KEY3_GPIO_Port,KEY3_Pin)==GPIO_PIN_RESET)
{
if(report_motor_fan==1)
{
report_motor_fan=0;
HAL_GPIO_WritePin(MOTOR_GPIO_Port,MOTOR_Pin,GPIO_PIN_RESET);
printf("motor_fan OFF: %d\n", report_motor_fan);
Gui_DrawFont_GBK16(5,140,RED,BLACK,(uint8_t*)"Motor:OFF ");
}
else
{
report_motor_fan=1;
HAL_GPIO_WritePin(MOTOR_GPIO_Port,MOTOR_Pin,GPIO_PIN_SET);
printf("motor_fan ON: %d\n", report_motor_fan);
Gui_DrawFont_GBK16(5,140,GREEN,BLACK,(uint8_t*)"Motor:ON ");
}
}
}
}
}
主任務函數,該任務實現LoRa連接到閘道,檢測連接狀態,定時上報資料以及一些需要換算的參數。
void application_entry(void *arg)
{
printf("APP RUNNING...\r\n");
float report_temperature;
int16_t temperature;
int16_t report_humidity;
unsigned int quantity=0;
uint16_t sum1=0;
char temp[]={0};
Lcd_Init();
LCD_LED_SET;
Lcd_Clear(BLACK);
Gui_DrawFont_GBK16(10,5,RED,BLACK ,"TencentOS Tiny");
Gui_DrawFont_GBK16(10,20,YELLOW,BLACK,"LoRa Node NO.1");
LPS22HB_Init();
HTS221_Init();
#ifdef LORA_REPORT Gui_DrawFont_GBK16(5,35,RED,BLACK,"LoRa Linking...");
rhf76_lora_init(HAL_UART_PORT_1);
tos_lora_module_recvcb_register(recv_callback);
if(tos_lora_module_join_otaa("8cf957200000f87e", "8cf957200000f87e9239aaaaad204a72")==-1)
{
Gui_DrawFont_GBK16(5,35,RED,BLACK, " Link GW Error! ");
report_period=60;
}
else
{
Gui_DrawFont_GBK16(5,35,GREEN,BLACK," Link GW OK! ");
}
Gui_DrawFont_GBK16(5,125,RED,BLACK,"LED:OFF ");
Gui_DrawFont_GBK16(5,140,RED,BLACK,"Motor:OFF ");
#endif example_main_one_shot_lps22hb();
first_pressure=pressure_hPa;
first_height=height;
while (1)
{
printf("------LoRawan sensor board data------\n");
Gui_DrawFont_GBK16(5,50,YELLOW,BLACK,"---------------");
example_main_one_shot_lps22hb();
HTS221_Get_Temperature(&temperature);
HTS221_Get_Humidity(&report_humidity);
report_temperature= temperature_degC;
report_height=(height-first_height)*1000;
if(pressure_hPa<0)
report_pressure=-pressure_hPa*100;
else
report_pressure=pressure_hPa*100;
sprintf(temp,"Temp:%2.1f ",report_temperature);
Gui_DrawFont_GBK16(5,65,WHITE,BLACK,temp);
sprintf(temp,"Humi:%2.1f ", report_humidity / 10.0);
Gui_DrawFont_GBK16(5,80,WHITE,BLACK,temp);
sprintf(temp,"Pa:%2.2f ",pressure_hPa);
Gui_DrawFont_GBK16(5,95,WHITE,BLACK,temp);
sprintf(temp,"Height:%d ", (int)report_height);
Gui_DrawFont_GBK16(5,110,WHITE,BLACK,temp);
printf("LPS22HB_pressure[hPa]:%0.2f,height[mm]:%d\r\n", pressure_hPa,(int)report_height);
printf("LPS22HB_temperature [degC]:%0.2f\r\n",report_temperature);
printf("HTS221_temperature : %2.1f\n", temperature/10.0);
printf("HTS221_humidity : %2.1f\n", report_humidity / 10.0);
sum1++;
printf("sum:%d\r\n",sum1);
tos_task_delay(500);
#ifdef LORA_REPORT if(sum1>=report_period)
{
sum1=0;
quantity++;
printf("quantity : %d\n", quantity);
printf("LED_Status : %d\n",report_power_switch);
printf("motor_Status: %d\n",report_motor_fan);
dev_data_wrapper.u.dev_data.temperature = report_temperature;
dev_data_wrapper.u.dev_data.humidity = report_humidity / 10;
dev_data_wrapper.u.dev_data.period = report_period;
dev_data_wrapper.u.dev_data.quantity = quantity;
dev_data_wrapper.u.dev_data.power_switch= report_power_switch;
dev_data_wrapper.u.dev_data.motor_fan = report_motor_fan;
dev_data_wrapper.u.dev_data.pressure = report_pressure;
dev_data_wrapper.u.dev_data.height = report_height;
tos_lora_module_send(dev_data_wrapper.u.serialize, sizeof(dev_data_t));
}
#endif
}
}
(2)雲平臺實現
登陸iotexplorer平臺即可快速創建LoRa項目
(3)微信小程式實現
小程式集成了LoRa設備和NB設備,這樣就可以切換頁面查看並控制不同終端設備。這個小程式是通過官方提供demo進行二次開發的。
四、總結
利用LoRa極強的穿透力,實現對樓層中的機房環境進行監控。它安裝方便,節省了人力物力和財力。所以LoRa物聯網應用于機房或建設智慧建築有先天的優勢。如果使用NB模組,每年都要換卡或者繳費。使用WIFI設備呢,穿透力不夠強,距離沒有LoRa傳輸得遠。
本案例需要增強改進的地方是,檢測機房斷路器通斷,交流接觸器動作等器件的工作狀態。也可以直接和PLC控制器進行通訊,直接讀取PLC採集的資料,然後通過LoRa上傳資料。