环境监测对于人类来说至关重要,空气质量、土壤构成、环境噪音、温湿度等对我们的农业发展、城市建设、日常生活都会造成影响。以温湿度为例:温湿度高低会影响农作物的生长、影响工程建设进度、影响设备运作,如果我们能够精确地监测温湿度数据、及时作出调整,就能促进整个行业的高效运行。
基于这样的需求考虑,“如何搭建一个良好的环境监测系统”成为了我们需要思考的核心问题。
通常来说,搭建一个良好的环境监测系统,最关键的是要建立实时的环境监测预警系统,并保存完整的历史数据。以产品测试行业为例,当环境不利于产品测试时,只有及时预警,才能采取有效措施调节室内环境,从而避免监测系统损坏。同时也可以根据保存下来的实时数据进行具体分析。
由此可以知道,我们需要的是一套传输距离远、功耗低、还能实时保存数据的环境监测系统。
基于瑞科慧联(RAK)的模块化产品 WisBlock 以及软件平台 RUI 3 搭建出来的 LoRaWAN®无线环境监测预警系统,恰好符合这一点。WisBlock + RUI3 的环境监测预警系统可以做到全天 24 小时全面准确地进行环境监测。该系统也被广泛地应用在实验室温湿度环境监测、办公区环境监测、商超冰柜温度监测、农场大棚温湿度检测等多个领域。
今天我就带大家一起学习快速地搭建这套 LoRa®无线温湿度监测系统。
搭建前的准备
硬件准备
- WisBlock Base(本示例使用 RAK5005-O)
- WisBlock Core(本示例使用 RAK4631)
- WisBlock Sensor(本示例使用 RAK1906)
- LoRa®天线(本示例使用 CN470频段)
- 网关(本示例使用 RAK7268网关)
注意:要保持网关与传感器所属的频段相同,本案例我使用的频段均为 CN470。
软件准备
硬件安装
- 将 LoRa®天线接口对准并放置在 RAK4631 模块的 LoRa®天线接口搭接处,轻轻按压 LoRa®天线接口,完成安装。
- 将 RAK4631 模块上的连接器插头对准 RAK5005-O CUP 插槽上的连接器插座。保持连接器间平行,并将其轻放在插座连接器相应的搭接处。
- 将传感器模块 RAK1906 上的连接器插头对准 RAK5005-O 插槽的连接器插座。保持连接器间平行,将其轻放在插座连接器相应的搭接处。
- 组装过程示意图如下:
软件配置
在 Arduino IDE中添加 RAK4631-R 开发板
1、打开 Arduino IDE,进入“文件 > 首选项”
打开 Arduino IDE
2、单击图中图标,修改“附加开发板管理器网址”选项,将 RAK4631-R WisBlock Core 添加中 Arduino 开发板管理器中。
在 Arduino IDE上修改“附加开发板管理器网址”
3、现在复制下方 URL并粘贴至下图所示区域。如果已存在其他链接,将上述链接粘贴至新的一行。完成后,单击“好”。
https://raw.githubusercontent.com/RAKWireless/RAKwireless-Arduino-BSP-Index/main/package_rakwireless.com_rui_index.json
在Arduino IDE上粘贴复制好的URL
4、重启 Arduino IDE。进入“工具 > 开发板:“RAK4631” > 开发板管理器”。
重启Arduino IDE并执行操作
5、在搜索框中输入“RAK”,窗口会自动出现可用的 RAKwireless WisBlock Core Boards,选择“RAKwireless RUI nRF Boards”并安装。
选择并安装 RAKwireless RUI nRF Boards
6、BSP 安装完成后,根据图中路径选择 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);
}
连接传感器节点至 TTN
本节为将传感器节点连接至 TTN(The Things Network)平台的操作过程。
登录到 TTN 平台
登录TTN网站,将会看到以下页面:
TTN 网站的控制台页面
创建新的应用程序
进入添加 Application 界面,注册相关信息后,单击页面底部的“Create application”。
添加应用
进入应用程序概述页面,单击右下角“Add end devices”,在 TTN平台注册新设备。
应用程序概述页面
注册新设备
在“Register end device”页面中,单击“Manually”页签。
配置 Frequency plan、LoRaWAN version、Regional Parameters version,并添加设备 DevEUI、AppEUI、AppKey。
注册设备
设备频段应与网关频段相同。
DevEUI、AppEUI、AppKey请在传感器示例代码中获取,切记需要删除各个数字前的“0x”以及“,”。
获取 DevEUI、AppEUI、AppKey
单击"Register and device",完成设备注册,注册结果将汇总如下图所示。
设备信息
重启设备后,设备自动入网并定时向服务器传输实时监测数据。单击See all activity→,查看传输数据。
环境监测数据获取
添加 Datacake集成到 TTN
具体可参考:https://docs.datacake.de/lorawan/lns/thethingsindustries
在 Datacake中配置设备
在这里,我假设已经设置 Datacake帐户,创建好了应用程序,并准备添加设备。如果大家没有创建好账户,可以通过Datacake 文档了解创建步骤。
在 Datacake 应用程序中,单击“设备”以查看设备的概述。单击“添加设备”按钮开始。
在下一个屏幕中,选择LoRaWAN New device并点击“Next”
选择New product并写入Product Name
然后,向下滚动窗口,直到看到该部分。在此处选择“TTN V3”,选择它,然后单击“下一步”按钮。
在下一步中,我们必须输入节点的 Dev EUI 和名称。Dev EUI 必须与之前在 TTN V3应用程序中选择的节点匹配。输入信息后,再次点击“下一步”按钮。
根据我们在 Datacake上的帐户,以及已经注册的设备数量,在不同的支付选项之间进行选择。完成此处选择后,按“添加1个设备”按钮。
现在,可以在 Datacake的概述屏幕中看到新设备。
在 Datacake 中为传感器节点创建数据解析器和数据字段
要完成设备的配置,请在概述中单击它。在下一个窗口中,选择 。Configuration
在配置中,向下滚动,直到看到该部分。在这里,必须要输入我们的自定义有效负载解码器才能获取到达的数据。正如图中所示,解码器返回一个嵌套的 JSON 数组,其中每个 JSON 条目都有两个字段。之后会转发到可视化界面,就能让传感器进行数据传输了。Payload Decoderfieldvaluefieldvalue
为了使事情变得更容易,我准备了一个有效负载解码器,它将会与此示例配合使用,而且它也可以轻松扩展与我们其他的WisBlock 解决方案一起使用。
为了节省时间,我将代码放在这里。使用以下内容覆盖示例负载解码器:
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)
},
];
}
}
现在,我们检查解码器是否正常工作。向下滚动并点击“保存”按钮以更新解码器。
然后,一直向上滚动并选择选项卡。如果此时设备处于联机状态并且已发送数据,那么就可以 .DebugDebug Log。
如果这有效,接下来就要做更多的工作了。Datacake 使用字段为可视化查找正确的数据,但必须要先定义所有字段。
返回到配置选项卡并向下滚动,直到看到该部分。到达那里后,单击添加字段按钮。Fields
在窗口中,选择数据类型、字段名称和单位。Add Field
注意:这里必须与负载解码器中分配的字段名称匹配。因此,对于“温度”,正确的字段名称是“温度”。Identifier。
输入所有信息后,点击“添加字段”按钮。
必须重复此步骤,直到定义了将包含传感器数据的所有四个字段。最后,应该如下所示:Fields
到这里,我们就完成所有的准备工作。现在,我们用一些漂亮的图表来显示数据。
设置仪表板以可视化传入的传感器数据
返回设备概述并打开选项卡。目前,它是空的。需要添加新的微件,单击右侧的小编辑图标。Dashboard
现在,我们会看到一个添加小部件按钮。单击它开始。
在下一个屏幕中,会看到一系列不同的可视化选项。我选择了这里。Chart
下一个窗口有四个选项卡。从选项卡开始。就可以在此处输入图表标题。Basic
在Field选项卡中,选择Temperature
现在,它将显示带有温度数据的第一个小部件。我们可以使用微件右下角的小箭头调整大小。
对其他字段重复这些步骤后,就可以看到包含接收数据的图表。主要要单击旁边的黄色图标保存你的操作,然后返回主仪表板视图。HumidityPressureAir QualityUnsaved changes
现在,来自环境传感器的数据以一个很好的可视化效果呈现出来了,我们可以从任何地方访问和查看。
添加Rules
这里我们可以对由设备测量值引起的事件执行操作。它们允许设置不同的触发器和警报,例如:
1、通过电子邮件或短信发送通知消息
2、通过网络挂钩调用外部服务
3、将下行链路发送到 LoRa®设备
这里可以从工作区的侧边栏菜单创建和访问规则。与设备相关的规则(一个或多个条件引用设备)还会显示在设备的“规则”选项卡中。
通过单击右上角的“添加规则”按钮创建第一个规则。
我们在这里通过设置温度的告警值通过邮件的方式提醒
当温度高于 26℃ 时,Datacake将会通过邮件的方式通知,而且显示当前的温度
希望这个教程能够对大家有所帮助,如果大家有任何问题,也可以留言告诉我们。
-
环境监测系统
+关注
关注
0文章
40浏览量
9984 -
LoRa
+关注
关注
349文章
1689浏览量
231938
发布评论请先 登录
相关推荐
评论