使用 Arduino MKR WAN 1300 和 Grove 湿度传感器搭建 LoRaWAN 水探测器
使用湿度传感器连接到 Arduino MKR WAN 1300 板测量湿度并将数据发送至 The Things Network。
在使用支持 Arduino 的 Grove 入门套件和 Grove 语音识别器后,我现在有许多 Grove 模块。同时,在最近研究了 Arduino MKR WAN 1300 之后,我渴望进一步探索它的更多应用。于是,我很高兴地发现 MKR 连接器载体 (176-3646) 可以让我轻松地将 Grove 传感器和 MKR Wan 1300 组合使用。
将 Grove 传感器连接至 MKR WAN 133
首先,我将 MKR Arduino MKR WAN 1300 插入连接器载体,再连接到 Grove 接近传感器中。我将示例编程上传到 Arduino 上,并用手在传感器上方挥动,然后在 Arduino IDE 的串行监控器中看到了感应结果。
随后,我尝试了其他不同的传感器,并决定探索湿度传感器 (174-3236) 的应用。这看起来很合理,因为我所在的约克郡空气湿度较大,我认为它可以用来检测应保持干燥的地点的湿度变化。
连接到The Things Network
我已将 MKR WAN 1300 连接至 The Things Network (TTN),并在上一篇博客文章中对此进行了概述。将传感器设置为向 TTN 发送数据的过程非常简单,而将发送的数据设置为实用格式又是另一回事。我依照 Gonzalo Casas GitHub 的步骤在 MKR WAN 1300 上编写了“hello world”初始程序,同时还编写了将数值发送到串行监控器的 Grove 湿度传感器示例程序。
我可以看到数据被发送至 TTN,然而并没有达到预期的目标,因此我开始尝试解决此问题。
将数据以字节形式发送
The Things Network 使用 LoRaWAN,它是一种类似于 WiFi 或 Bluetooth 的无线通信标准,属于低功耗广域网络 (LPWAN)。它通过尽可能提高发送和接收数据的效率来节省带宽和传输时间。这样还能达到节能的效果,尤其适用于电池供电设备。这意味着数据编码应当以尽可能缩短传输时间为目标。因此在传输之前,应将数据转换为字节,而不是以 ASCII 字符的形式发送,同时应当尽可能减少字节的数量。于是我需要先将传感器生成的数据转换为字节,然后再进行传输。
为此,我首先需要将程序中的 modem.print
行更改为 modem.write。在阅读了 MKR Wan 参考资料之后,我明确地认识到 modem.write
以字节或一系列字节的形式发送数据,而 print 函数(这正是我的错误所在)则发送表示数字位数的字符。
将 modem.print
更改为 modem.write
之后,我可以看到发送字节成功,但是我可以通过将数据压缩为单字节来做出进一步的改进。字节的最大值为 255,但根据数据表,Grove 传感器生成的输出值如下:
我将传感器浸入一杯水中,以此来测试实际使用时可能发生的情况。我得到的读数刚刚超过 600。用钥匙或螺丝刀使触点短路后,读数大约为 800。这意味着,如果我将该值除以 3,那么在最潮湿的环境下读数将不超过 255。在这种情况下,我不需要太精确(即 950 的湿度),因为 300 足以满足我的需求。将来我可以轻松编辑,将该数值除以 3.5 或 4,以确保单字节不超过最大值 255。
最终程序
我的程序现在如下所示:
#include <MKRWAN.h>
LoRaModem modem;
#include "arduino_secrets.h"
// Please enter your sensitive data in the arduino_secrets.h tab
String appEui = SECRET_APP_EUI;
String appKey = SECRET_APP_KEY;
int sensorPin = A0;
int sensorValue = 0;
void setup() {
// put your setup code here, to run once:
Serial.begin(115200);
while (!Serial);
// change this to your regional band (eg. US915, AS923, ...)
if (!modem.begin(EU868)) {
Serial.println("Failed to start module");
while (1) {}
};
Serial.print("Your module version is: ");
Serial.println(modem.version());
Serial.print("Your device EUI is: ");
Serial.println(modem.deviceEUI());
int connected = modem.joinOTAA(appEui, appKey);
if (!connected) {
Serial.println("Something went wrong; are you indoors? Move near a window and retry");
while (1) {}
}
// Set poll interval to 60 secs.
modem.minPollInterval(60);
// NOTE: independently of this setting the modem will
// not send more than one message every 2 minutes,
// this is enforced by firmware and can not be changed.
}
void loop() {
// read the value from the sensor:
sensorValue = analogRead(sensorPin);
// scale the reading and fit into 1 byte
int scaledValue = sensorValue / 3;
byte payload = scaledValue;
Serial.print("Sensor reading = " );
Serial.println(sensorValue);
Serial.print("Scaled value = " );
Serial.println(scaledValue);
delay(1000);
modem.beginPacket();
modem.write(payload);
int err = modem.endPacket(false);
if (err > 0) {
Serial.println("Data Sent");
} else {
Serial.println("Error");
}
delay(100000 * 60);
}
运行程序时必须已安装 MKR WAN 库,我已经在有关 MKR WAN 1300 的博客文章中介绍了如何进行这一操作。
Grove 湿度检测仪是一款模拟传感器,因此运行时不需要库。
您还需要在以上程序所在的同一文件夹中创建一个名为 arduino_secrights.h 的文件,其中包含以下内容:
// Replace with keys obtained from TheThingsNetwork console
#define SECRET_APP_EUI "xxxxxxxxxxxxxxxx"
#define SECRET_APP_KEY "xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"
接着您可以编辑以上内容,将 x 替换为应用程序 EUI 和应用程序密钥,密钥可以在 TTN 控制台的“设备”页面找到。
在 The Things Network 控制台中添加解码器
当数据到达 The Things Network 后,需要将字节值转换回具有意义的数字。这是通过 TTN 端的解码器实现的。该解码器位于 TTN 控制台“应用”部分的“有效负载格式”页面中。它使用 Javascript 语言,下列解码器读取传感器发送的字节并将其转换回整数:
function Decoder(bytes, port) {
var decoded = {};
decoded.moisture = bytes[0];
return decoded;
}
调试
程序包含写入到串行监控器的行,目的是帮助调试。该行将显示传感器的整数输出,然后将数值除以 3,以便与 TTN 数据窗口中的显示值进行对比。这样将能够轻松监测到生成的任何异常值,例如当数值超过 255 时。
结论
如果我只需要一台水灾探测器,那么我可以在本项目中使用 Grove 水位传感器 (174-3242) ,但是湿度检测器具有更高的灵活性。除了真正的水灾之外,我还可以用它来检测遛狗之前屋后土壤的湿度,或者在夏天用来检测植物何时需要浇水。
我还打算研究一些在湿度过高(或者过低)时发送短信或 Tweet 提醒的编程方法。
评论