環(huán)境監(jiān)測對于人類來說至關(guān)重要,空氣質(zhì)量、土壤構(gòu)成、環(huán)境噪音、溫濕度等對我們的農(nóng)業(yè)發(fā)展、城市建設(shè)、日常生活都會造成影響。以溫濕度為例:溫濕度高低會影響農(nóng)作物的生長、影響工程建設(shè)進度、影響設(shè)備運作,如果我們能夠精確地監(jiān)測溫濕度數(shù)據(jù)、及時作出調(diào)整,就能促進整個行業(yè)的高效運行。
基于這樣的需求考慮,“如何搭建一個良好的環(huán)境監(jiān)測系統(tǒng)”成為了我們需要思考的核心問題。
通常來說,搭建一個良好的環(huán)境監(jiān)測系統(tǒng),最關(guān)鍵的是要建立實時的環(huán)境監(jiān)測預(yù)警系統(tǒng),并保存完整的歷史數(shù)據(jù)。以產(chǎn)品測試行業(yè)為例,當環(huán)境不利于產(chǎn)品測試時,只有及時預(yù)警,才能采取有效措施調(diào)節(jié)室內(nèi)環(huán)境,從而避免監(jiān)測系統(tǒng)損壞。同時也可以根據(jù)保存下來的實時數(shù)據(jù)進行具體分析。
由此可以知道,我們需要的是一套傳輸距離遠、功耗低、還能實時保存數(shù)據(jù)的環(huán)境監(jiān)測系統(tǒng)。
基于瑞科慧聯(lián)(RAK)的模塊化產(chǎn)品 WisBlock 以及軟件平臺 RUI 3 搭建出來的 LoRaWAN?無線環(huán)境監(jiān)測預(yù)警系統(tǒng),恰好符合這一點。WisBlock + RUI3 的環(huán)境監(jiān)測預(yù)警系統(tǒng)可以做到全天 24 小時全面準確地進行環(huán)境監(jiān)測。該系統(tǒng)也被廣泛地應(yīng)用在實驗室溫濕度環(huán)境監(jiān)測、辦公區(qū)環(huán)境監(jiān)測、商超冰柜溫度監(jiān)測、農(nóng)場大棚溫濕度檢測等多個領(lǐng)域。
今天我就帶大家一起學習快速地搭建這套 LoRa?無線溫濕度監(jiān)測系統(tǒng)。
搭建前的準備
硬件準備
- WisBlock Base(本示例使用 RAK5005-O)
- WisBlock Core(本示例使用 RAK4631)
- WisBlock Sensor(本示例使用 RAK1906)
- LoRa?天線(本示例使用 CN470頻段)
- 網(wǎng)關(guān)(本示例使用 RAK7268網(wǎng)關(guān))
注意:要保持網(wǎng)關(guān)與傳感器所屬的頻段相同,本案例我使用的頻段均為 CN470。
軟件準備
硬件安裝
- 將 LoRa?天線接口對準并放置在 RAK4631 模塊的 LoRa?天線接口搭接處,輕輕按壓 LoRa?天線接口,完成安裝。
- 將 RAK4631 模塊上的連接器插頭對準 RAK5005-O CUP 插槽上的連接器插座。保持連接器間平行,并將其輕放在插座連接器相應(yīng)的搭接處。
- 將傳感器模塊 RAK1906 上的連接器插頭對準 RAK5005-O 插槽的連接器插座。保持連接器間平行,將其輕放在插座連接器相應(yīng)的搭接處。
- 組裝過程示意圖如下:
軟件配置
在 Arduino IDE中添加 RAK4631-R 開發(fā)板
1、打開 Arduino IDE,進入“文件 > 首選項”
打開 Arduino IDE
2、單擊圖中圖標,修改“附加開發(fā)板管理器網(wǎng)址”選項,將 RAK4631-R WisBlock Core 添加中 Arduino 開發(fā)板管理器中。
在 Arduino IDE上修改“附加開發(fā)板管理器網(wǎng)址”
3、現(xiàn)在復(fù)制下方 URL并粘貼至下圖所示區(qū)域。如果已存在其他鏈接,將上述鏈接粘貼至新的一行。完成后,單擊“好”。
https://raw.githubusercontent.com/RAKWireless/RAKwireless-Arduino-BSP-Index/main/package_rakwireless.com_rui_index.json?
在Arduino IDE上粘貼復(fù)制好的URL
4、重啟 Arduino IDE。進入“工具 > 開發(fā)板:“RAK4631” > 開發(fā)板管理器”。
重啟Arduino IDE并執(zhí)行操作
5、在搜索框中輸入“RAK”,窗口會自動出現(xiàn)可用的 RAKwireless WisBlock Core Boards,選擇“RAKwireless RUI nRF Boards”并安裝。
選擇并安裝 RAKwireless RUI nRF Boards
6、BSP 安裝完成后,根據(jù)圖中路徑選擇 RAKwireless WisBlock Core模塊。
選擇 RAKwireless WisBlock Core 模塊
7、代碼燒錄
/**
@file Environment_Monitoring ino
@author rakwireless com
@brief This sketch demonstrate how to get environment data from BME680
and send the data to lora gateway
@version 0 1
@date 2020-07-28
@copyright Copyright (c) 2020
**/
#include
#include
#include // Click to install library: http://librarymanager/All#Adafruit_BME680
Adafruit_BME680 bme;
/*************************************
LoRaWAN band setting:
RAK_REGION_EU433
RAK_REGION_CN470
RAK_REGION_RU864
RAK_REGION_IN865
RAK_REGION_EU868
RAK_REGION_US915
RAK_REGION_AU915
RAK_REGION_KR920
RAK_REGION_AS923
*************************************/
#define OTAA_BAND (RAK_REGION_CN470)
#define OTAA_DEVEUI {0x20, 0x17, 0x06, 0x15, 0x0E, 0x00, 0x00, 0x15}
#define OTAA_APPEUI {0x20, 0x17, 0x06, 0x00, 0x00, 0x00, 0x00, 0x00}
#define OTAA_APPKEY {0x11, 0x22, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0x00, 0xAA, 0xBB, 0xCC, 0xDD, 0xEE, 0xFF}
// Might need adjustments
#define SEALEVELPRESSURE_HPA (1010.0)
uint8_t buffer[13]="";
void bme680_get()
{
Serial.print("Temperature = ");
Serial.print(bme.temperature);
Serial.println(" C");
Serial.print("Pressure = ");
Serial.print(bme.pressure / 100.0);
Serial.println(" hPa");
Serial.print("Humidity = ");
Serial.print(bme.humidity);
Serial.println(" %");
Serial.print("Gas = ");
Serial.print(bme.gas_resistance / 1000.0);
Serial.println(" KOhms");
Serial.println();
uint16_t t = bme.temperature * 100;
uint32_t pre = bme.pressure / 100.0 * 100;
uint16_t h = bme.humidity * 100;
uint32_t gas = bme.gas_resistance;
uint32_t i = 0;
//result: T=28.25C, RH=50.00%, P=958.57hPa, G=100406 Ohms
buffer[i++] = 0x01;
buffer[i++] = (uint8_t)(t >> 8);
buffer[i++] = (uint8_t)t;
buffer[i++] = (uint8_t)(h >> 8);
buffer[i++] = (uint8_t)h;
buffer[i++] = (uint8_t)((pre & 0xFF000000) >> 24);
buffer[i++] = (uint8_t)((pre & 0x00FF0000) >> 16);
buffer[i++] = (uint8_t)((pre & 0x0000FF00) >> 8);
buffer[i++] = (uint8_t)(pre & 0x000000FF);
buffer[i++] = (uint8_t)((gas & 0xFF000000) >> 24);
buffer[i++] = (uint8_t)((gas & 0x00FF0000) >> 16);
buffer[i++] = (uint8_t)((gas & 0x0000FF00) >> 8);
buffer[i++] = (uint8_t)(gas & 0x000000FF);
/** Send the data package */
if (api.lorawan.send(sizeof(buffer), (uint8_t *)buffer, 2, true, 1))
{
Serial.println("Sending is requested");
}
else
{
Serial.println("Sending failed");
}
}
void init_bme680()
{
Wire.begin();
if (!bme.begin(0x76)) {
Serial.println("Could not find a valid BME680 sensor, check wiring!");
return;
}
// Set up oversampling and filter initialization
bme.setTemperatureOversampling(BME680_OS_8X);
bme.setHumidityOversampling(BME680_OS_2X);
bme.setPressureOversampling(BME680_OS_4X);
bme.setIIRFilterSize(BME680_FILTER_SIZE_3);
bme.setGasHeater(320, 150); // 320*C for 150 ms
}
void lora_init()
{
// OTAA Device EUI MSB first
uint8_t node_device_eui[8] = OTAA_DEVEUI;
// OTAA Application EUI MSB first
uint8_t node_app_eui[8] = OTAA_APPEUI;
// OTAA Application Key MSB first
uint8_t node_app_key[16] = OTAA_APPKEY;
if (!api.lorawan.appeui.set(node_app_eui, 8)) {
Serial.printf("LoRaWan OTAA - set application EUI is incorrect! \r\n");
return;
}
if (!api.lorawan.appkey.set(node_app_key, 16)) {
Serial.printf("LoRaWan OTAA - set application key is incorrect! \r\n");
return;
}
if (!api.lorawan.deui.set(node_device_eui, 8)) {
Serial.printf("LoRaWan OTAA - set device EUI is incorrect! \r\n");
return;
}
if (!api.lorawan.band.set(OTAA_BAND)) {
Serial.printf("LoRaWan OTAA - set band is incorrect! \r\n");
return;
}
if (!api.lorawan.deviceClass.set(RAK_LORA_CLASS_A)) {
Serial.printf("LoRaWan OTAA - set device class is incorrect! \r\n");
return;
}
if (!api.lorawan.njm.set(RAK_LORA_OTAA)) // Set the network join mode to OTAA
{
Serial.printf
("LoRaWan OTAA - set network join mode is incorrect! \r\n");
return;
}
if (!api.lorawan.join()) // Join to Gateway
{
Serial.printf("LoRaWan OTAA - join fail! \r\n");
return;
}
/** Wait for Join success */
while (api.lorawan.njs.get() == 0) {
Serial.print("Wait for LoRaWAN join...");
api.lorawan.join();
delay(10000);
}
if (!api.lorawan.adr.set(true)) {
Serial.printf
("LoRaWan OTAA - set adaptive data rate is incorrect! \r\n");
return;
}
if (!api.lorawan.rety.set(1)) {
Serial.printf("LoRaWan OTAA - set retry times is incorrect! \r\n");
return;
}
if (!api.lorawan.cfm.set(1)) {
Serial.printf("LoRaWan OTAA - set confirm mode is incorrect! \r\n");
return;
}
/** Check LoRaWan Status*/
Serial.printf("Duty cycle is %s\r\n", api.lorawan.dcs.get()? "ON" : "OFF"); // Check Duty Cycle status
Serial.printf("Packet is %s\r\n", api.lorawan.cfm.get()? "CONFIRMED" : "UNCONFIRMED"); // Check Confirm status
uint8_t assigned_dev_addr[4] = { 0 };
api.lorawan.daddr.get(assigned_dev_addr, 4);
Serial.printf("Device Address is %02X%02X%02X%02X\r\n", assigned_dev_addr[0], assigned_dev_addr[1], assigned_dev_addr[2], assigned_dev_addr[3]); // Check Device Address
Serial.println("");
}
void setup()
{
//Initialize the built in LED
pinMode(LED_BUILTIN, OUTPUT);
digitalWrite(LED_BUILTIN, LOW);
// Initialize Serial for debug output
Serial.begin(115200);
time_t serial_timeout = millis();
while (!Serial)
{
if ((millis() - serial_timeout) < 5000)
{
delay(100);
digitalWrite(LED_BUILTIN, !digitalRead(LED_BUILTIN));
}
else
{
break;
}
}
delay(1000);
Serial.println("=====================================");
Serial.println("Welcome to RAK4630 LoRaWan!!!");
lora_init();
init_bme680();
}
void loop()
{
if (! bme.performReading()) {
Serial.println("Failed to perform reading :(");
return;
}
bme680_get();
delay(10000);
}
連接傳感器節(jié)點至 TTN
本節(jié)為將傳感器節(jié)點連接至 TTN(The Things Network)平臺的操作過程。
登錄到 TTN 平臺
登錄TTN網(wǎng)站,將會看到以下頁面:
TTN 網(wǎng)站的控制臺頁面
創(chuàng)建新的應(yīng)用程序
進入添加 Application 界面,注冊相關(guān)信息后,單擊頁面底部的“Create application”。
添加應(yīng)用
進入應(yīng)用程序概述頁面,單擊右下角“Add end devices”,在 TTN平臺注冊新設(shè)備。
應(yīng)用程序概述頁面
注冊新設(shè)備
在“Register end device”頁面中,單擊“Manually”頁簽。
配置 Frequency plan、LoRaWAN version、Regional Parameters version,并添加設(shè)備 DevEUI、AppEUI、AppKey。
注冊設(shè)備
設(shè)備頻段應(yīng)與網(wǎng)關(guān)頻段相同。
DevEUI、AppEUI、AppKey請在傳感器示例代碼中獲取,切記需要刪除各個數(shù)字前的“0x”以及“,”。
獲取 DevEUI、AppEUI、AppKey
單擊"Register and device",完成設(shè)備注冊,注冊結(jié)果將匯總?cè)缦聢D所示。
設(shè)備信息
重啟設(shè)備后,設(shè)備自動入網(wǎng)并定時向服務(wù)器傳輸實時監(jiān)測數(shù)據(jù)。單擊See all activity→,查看傳輸數(shù)據(jù)。
環(huán)境監(jiān)測數(shù)據(jù)獲取
添加 Datacake集成到 TTN
具體可參考:https://docs.datacake.de/lorawan/lns/thethingsindustries
在 Datacake中配置設(shè)備
在這里,我假設(shè)已經(jīng)設(shè)置 Datacake帳戶,創(chuàng)建好了應(yīng)用程序,并準備添加設(shè)備。如果大家沒有創(chuàng)建好賬戶,可以通過Datacake 文檔了解創(chuàng)建步驟。
在 Datacake 應(yīng)用程序中,單擊“設(shè)備”以查看設(shè)備的概述。單擊“添加設(shè)備”按鈕開始。
在下一個屏幕中,選擇LoRaWAN New device并點擊“Next”
選擇New product并寫入Product Name
然后,向下滾動窗口,直到看到該部分。在此處選擇“TTN V3”,選擇它,然后單擊“下一步”按鈕。
在下一步中,我們必須輸入節(jié)點的 Dev EUI 和名稱。Dev EUI 必須與之前在 TTN V3應(yīng)用程序中選擇的節(jié)點匹配。輸入信息后,再次點擊“下一步”按鈕。
根據(jù)我們在 Datacake上的帳戶,以及已經(jīng)注冊的設(shè)備數(shù)量,在不同的支付選項之間進行選擇。完成此處選擇后,按“添加1個設(shè)備”按鈕。
現(xiàn)在,可以在 Datacake的概述屏幕中看到新設(shè)備。
在 Datacake 中為傳感器節(jié)點創(chuàng)建數(shù)據(jù)解析器和數(shù)據(jù)字段
要完成設(shè)備的配置,請在概述中單擊它。在下一個窗口中,選擇 。Configuration
在配置中,向下滾動,直到看到該部分。在這里,必須要輸入我們的自定義有效負載解碼器才能獲取到達的數(shù)據(jù)。正如圖中所示,解碼器返回一個嵌套的 JSON 數(shù)組,其中每個 JSON 條目都有兩個字段。之后會轉(zhuǎn)發(fā)到可視化界面,就能讓傳感器進行數(shù)據(jù)傳輸了。Payload Decoderfieldvaluefieldvalue
為了使事情變得更容易,我準備了一個有效負載解碼器,它將會與此示例配合使用,而且它也可以輕松擴展與我們其他的WisBlock 解決方案一起使用。
為了節(jié)省時間,我將代碼放在這里。使用以下內(nèi)容覆蓋示例負載解碼器:
function Decoder(payload, port) {
if(payload[0] === 0x01) {
return [
{
field: "TEMPERATURE",
value: (payload[1] << 8 | payload[2]) / 100
},
{
field: "HUMIDITY",
value: (payload[3] << 8 | + payload[4]) / 100
},
{
field: "PRESSURE",
value: (payload[8] | (payload[7] << 8) | (payload[6] << 16) | (payload[5] << 24)) / 100
},
{
field: "GAS",
value: payload[12] | (payload[11] << 8) | (payload[10] << 16) | (payload[9] << 24)
},
];
}
}
現(xiàn)在,我們檢查解碼器是否正常工作。向下滾動并點擊“保存”按鈕以更新解碼器。
然后,一直向上滾動并選擇選項卡。如果此時設(shè)備處于聯(lián)機狀態(tài)并且已發(fā)送數(shù)據(jù),那么就可以 .DebugDebug Log。
如果這有效,接下來就要做更多的工作了。Datacake 使用字段為可視化查找正確的數(shù)據(jù),但必須要先定義所有字段。
返回到配置選項卡并向下滾動,直到看到該部分。到達那里后,單擊添加字段按鈕。Fields
在窗口中,選擇數(shù)據(jù)類型、字段名稱和單位。Add Field
注意:這里必須與負載解碼器中分配的字段名稱匹配。因此,對于“溫度”,正確的字段名稱是“溫度”。Identifier。
輸入所有信息后,點擊“添加字段”按鈕。
必須重復(fù)此步驟,直到定義了將包含傳感器數(shù)據(jù)的所有四個字段。最后,應(yīng)該如下所示:Fields
到這里,我們就完成所有的準備工作。現(xiàn)在,我們用一些漂亮的圖表來顯示數(shù)據(jù)。
設(shè)置儀表板以可視化傳入的傳感器數(shù)據(jù)
返回設(shè)備概述并打開選項卡。目前,它是空的。需要添加新的微件,單擊右側(cè)的小編輯圖標。Dashboard
現(xiàn)在,我們會看到一個添加小部件按鈕。單擊它開始。
在下一個屏幕中,會看到一系列不同的可視化選項。我選擇了這里。Chart
下一個窗口有四個選項卡。從選項卡開始。就可以在此處輸入圖表標題。Basic
在Field選項卡中,選擇Temperature
現(xiàn)在,它將顯示帶有溫度數(shù)據(jù)的第一個小部件。我們可以使用微件右下角的小箭頭調(diào)整大小。
對其他字段重復(fù)這些步驟后,就可以看到包含接收數(shù)據(jù)的圖表。主要要單擊旁邊的黃色圖標保存你的操作,然后返回主儀表板視圖。HumidityPressureAir QualityUnsaved changes
現(xiàn)在,來自環(huán)境傳感器的數(shù)據(jù)以一個很好的可視化效果呈現(xiàn)出來了,我們可以從任何地方訪問和查看。
添加Rules
這里我們可以對由設(shè)備測量值引起的事件執(zhí)行操作。它們允許設(shè)置不同的觸發(fā)器和警報,例如:
1、通過電子郵件或短信發(fā)送通知消息
2、通過網(wǎng)絡(luò)掛鉤調(diào)用外部服務(wù)
3、將下行鏈路發(fā)送到 LoRa?設(shè)備
這里可以從工作區(qū)的側(cè)邊欄菜單創(chuàng)建和訪問規(guī)則。與設(shè)備相關(guān)的規(guī)則(一個或多個條件引用設(shè)備)還會顯示在設(shè)備的“規(guī)則”選項卡中。
通過單擊右上角的“添加規(guī)則”按鈕創(chuàng)建第一個規(guī)則。
我們在這里通過設(shè)置溫度的告警值通過郵件的方式提醒
當溫度高于 26℃ 時,Datacake將會通過郵件的方式通知,而且顯示當前的溫度
希望這個教程能夠?qū)Υ蠹矣兴鶐椭绻蠹矣腥魏螁栴},也可以留言告訴我們。
-
環(huán)境監(jiān)測系統(tǒng)
+關(guān)注
關(guān)注
0文章
40瀏覽量
9975 -
LoRa
+關(guān)注
關(guān)注
348文章
1656瀏覽量
231626
發(fā)布評論請先 登錄
相關(guān)推薦
評論