大概是大一放暑假,因为在宿舍养了一棵多肉,第一次萌生了希望有一套自动浇水的装置的想法,当时也只是想想。
在事隔若干年后,因为做菜的葱蒜总是用不完,在窗边弄了两个泡沫箱种着,又因为懒得浇水,试着就把智能灌溉系统给实现了。
整套系统基于 arduino,结合 点灯·blinker 的平台加持,实现在线控制和数据显示,好处是编程简单、模块丰富,控制电路图如下:
目录
一、第一天
1.1 硬件准备
1.2 软件准备
二、第二天
2.1 设计一个浇水按钮
2.2 设置自动浇水开关
2.3 显示实时湿度和历史图表
三、第三天
3.1 实物连接
3.2 设备外壳
3.3 湿度传感器
后记
一、第一天
1.1 硬件准备
买材料,等快递,完。
板子我用的是 D1 mini,优点是小巧,带ESP8266芯片,可以物联网。
其它主要部件有:土壤湿度传感器、5V一路继电器、小水泵、配套水管。
零散的部件:杜邦线、micro数据线(旧安卓数据线,用于D1板子烧录和供电)、废旧塑料瓶等…
主控板子
土壤湿度传感器
电磁继电器
水泵和管子
1.2 软件准备
下载并安装 Arduino IDE,安装开发版的库(具体操作自行搜)。实际上程序我也是第一天写好的,实现自动浇水的关键代码(篇幅有限,只给出关键代码,需融会贯通,下同):
- // 设置湿度临界值
- int auto_moisture = 100;
- void setup() {
- // D1 控制继电器
- pinMode(D1, OUTPUT);
- // A0 读取湿度
- pinMode(A0, INPUT);
- }
- void loop() {
- // 读取湿度模拟值,转化成表现值
- int moisture = 1024 - analogRead(A0);
- // 如果湿度小于阈值则启动水泵
- if (moisture != 0 && moisture < auto_moisture) {
- digitalWrite(D1, HIGH);
- // 浇水持续时间
- delay(5000);
- digitalWrite(D1, LOW);
- }
- }
复制代码
以上代码从A0口读取土壤湿度传感器的模拟值,根据设定阈值,自动启动水泵浇水的过程。
注意这里读取的并不是真正的湿度值,而是 0~1024 范围的模拟电信号,湿度越大值越小;我为了更易于人类理解,把它和1024相减,使湿度越大表现值越大。
二、第二天
以上代码实现了本地控制,但我们肯定不满足于此。下一步是试其联网,远程控制、在线显示数据,这也是我用带WIFI板子的目的。物联网部分,我使用 blinker 的方案。
blinker 是一套物联网设备开发部署方案,核心是制定了设备和设备间、设备和客户端间通信及交互标准。用户可自己拖拽布局设备控制界面,自由打造你的物联网设备。
官网文档:https://diandeng.tech/doc/getting-start-8266
下载安装 blinker APP,新建设备,获取秘钥。IDE 安装 blinker Arduino 库,示例代码,配置WIFI、秘钥,这些官网文档都有,不赘述。
2.1 设计一个浇水按钮
APP 中新建一个按钮,数据健名「btn-water」;新建一个数据控件,键名「num-water」。
添加浇水按钮
结合以下代码,就能在自动浇水的基础上,实现远程手动浇水的功能。按一下开关水泵启动 5 秒,如果管子较长,这个值可以稍微设大一些。浇水完成后计数器 +1 并返回浇水的次数。
- #define BLINKER_WIFI
- #include <Blinker.h>
- char auth[] = "你的token";
- char ssid[] = "热点名";
- char pswd[] = "热点密码";
- // 新建组件对象
- BlinkerButton BtnWater("btn-water");
- BlinkerNumber NumWater("num-water");
- // 手动浇水计数
- int counter = 0;
- // 设置湿度临界值
- int auto_moisture = 100;
- void setup() {
- // D1 控制继电器
- pinMode(D1, OUTPUT);
- // A0 读取湿度
- pinMode(A0, INPUT);
- // 初始化 blinker
- Blinker.begin(auth, ssid, pswd);
- // 绑定按钮事件
- BtnWater.attach(BtnWater_callback);
- }
- void loop() {
- Blinker.run();
- // 读取湿度模拟值,转化成表现值
- int moisture = 1024 - analogRead(A0);
- // 如果湿度小于阈值则启动水泵
- if (moisture != 0 && moisture < auto_moisture) {
- digitalWrite(D1, HIGH);
- // 浇水持续时间
- Blinker.delay(5000);
- digitalWrite(D1, LOW);
- }
- }
- // 按下浇水按钮
- void BtnWater_callback(const String & state) {
- if (state == "tap" && digitalRead(D1) == 0) {
- digitalWrite(D1, HIGH);
- Blinker.delay(5000);
- digitalWrite(D1, LOW);
- counter++;
- // 发送计数
- NumWater.print(counter);
- }
- }
复制代码
2.2 设置自动浇水开关
如果我不想自动浇水,怎么办?我们可以在设置一个自动浇水开关,设置为打开时,执行检测湿度自动浇水的代码。
- //……此处省略部分非关键代码
- // 新建组件对象
- BlinkerButton BtnAuto("btn-auto");
- // 自动浇水默认开关
- bool auto_water = false;
- //……此处省略部分非关键代码
- void loop() {
- Blinker.run();
- // 读取湿度模拟值,转化成表现值
- int moisture = 1024 - analogRead(A0);
- // 如果湿度小于阈值则启动水泵
- if (auto_water && moisture != 0 && moisture < auto_moisture) {
- digitalWrite(D1, HIGH);
- // 浇水持续时间
- Blinker.delay(5000);
- digitalWrite(D1, LOW);
- }
- // 自动浇水开关
- void BtnAuto_callback(const String & state) {
- if (state == "on") {
- auto_water = true;
- } else {
- auto_water = false;
- }
- }
复制代码
2.3 显示实时湿度和历史图表
怎样湿度实时显示在 APP 上呢?方法和 2.1 中显示计数是一样的,APP中新建数据控件,代码中绑定控件。
- //……此处省略部分非关键代码
- // 新建组件对象
- BlinkerNumber NumMoisture("num-moisture");
- void setup() {
- //……此处省略部分非关键代码
- // 历史数据图表
- // Blinker.attachDataStorage(func, time, times);
- // func, 对应的回调函数
- // time, 对应数据采集时间-默认60 s, 最少60 s
- // times, 对应采集次数后上传到云端-默认2次, 最多不超过4次
- Blinker.attachDataStorage(dataStorage, 60 , 2);
- }
- // 设备需要上传数据到云端时会调用对应的回调函数
- void dataStorage() {
- int moisture = 1024 - analogRead(MOIST);
- Blinker.dataStorage("moisture", moisture);
- }
复制代码
但这里我们还需要加入心跳包,以便在一打开设备页面的时候就返回数据,后面每 30~60s 会定期返回一次心跳包。
- void setup() {
- //……此处省略部分非关键代码
- // 心跳绑定
- Blinker.attachHeartbeat(heartbeat);
- }
- // 发送实时数据
- void heartbeat() {
- NumMoisture.print(1024 - analogRead(MOIST));
- // 以下是返回开关状态
- btnSwitch(BtnAuto, STRING_format(auto_water ? "on" : "off"));
- }
复制代码
三、第三天
3.1 实物连接
下面是我制作实物的一些经验。把基本部件按以下线路连接,另外我们还需要储水罐、防水外壳。我用的是潜水泵,放到储水罐中,出水口连接软管到植物处。
3.2 设备外壳
整套装置我是打算放在窗台外的,所以必须考虑防水,外壳我用一个饮料瓶倒立放置。把元件全塞进去,娃哈哈某款饮料瓶口刚刚好。
瓶盖打三个孔,孔直径等于线的直径,引出三根导,分别是主板电源线、湿度传感器导线、水泵电源线。
3.3 湿度传感器
湿度传感器插针和导线焊接,用热缩管做最后的包裹。
这里我的经验之谈是做滴蜡处理,防止洒水的时候渗入到插针处,造成传感器不准。
后记
最后成品的效果,我把装置固定在窗边,用快递袋包裹遮太阳,从窗边引入一根电源线到室内接电源,储水罐用坏了的烧水壶。
手机控制端,当然后面程序上还做了一些升级优化,比如湿度数值取平均数,防止某一次取值偏差,增加浇水微信通知之类的。
整套东西做好了有一段时间,这篇文章陆陆续续写了快四个月。
再次证明了「一鼓作气,再而衰,三而竭」,以至于后面有些细节忘了,代码也是从最终版本中抠出来简化的,有 bug 别怪我 ╮( ̄▽ ̄)╭ ,如果有朋友需要可以完整开源,但我希望你有一点基础,有排错的能力。
感谢点灯提供的平台和库,让物联网开发变得简单、便捷!后面我还做了同时支持APP、天猫精灵、小爱同学(我用小米手环4)控制的氛围彩灯,支持不同闪动模式,后续希望加入读AUX音频信号,随音乐节奏跳动,但也一直拖着没动,有能力和兴趣的朋友可以一起探讨完善。
对了,还有舵机+激光逗猫的玩具,可是没有猫。
Made with love, just for fun!
未经许可禁止转载。