2017-11-2 14:45:35 [显示全部楼层]
11793浏览
查看: 11793|回复: 1

[项目] 物联网植物土壤湿度通知器

[复制链接]
在植物湿度过低时向你发送短信或拨打电话,还能通过精美的液晶显示屏 (LCD) 提供植物健康的相关信息。
创建日志

简介

DFRobot的妙想家们找到我,想要用他们开发的神奇的土壤湿度传感器和12C LCD1602做一个项目。
认真思考后,我决定创造一个植物监测仪,而DFRobot则为我提供必要的硬件。我决定制作一个仅由Particle Photon物联网开发板驱动的简易盒子。

该装置每隔30分钟就会检测一次土壤的湿度状况,判断其是否过于干燥。如果检测到湿度较低,装置会触发一个事件,然后由IFTTT通过短信、电话或电子邮件通知你土壤缺水。装置上方还配有一个RGB LED灯,其中绿灯表示植物土壤湿度状况良好,蓝色表示植物土壤湿度过低。

物联网植物土壤湿度通知器图2

LCD1602可指示植物土壤湿度状况的好坏。

组件

所需硬件组件:
  • Particle Photon
  • 土壤湿度传感器(兼容Arduino
  • I2C LCD1602液晶模块(兼容Arduino)
  • 散射型RGB LED灯
  • Micro USB连接器
  • Uxcell万能电路板 (4x6 cm)

应用程序与在线服务:
  • Particle云集成开发环境
  • IFTTT Maker 服务

手工工具与制作设备:
  • 焊铁(通用型)
  • Millright数控雕刻机M3


设计

首先,将各个组件以及Micro USB电源连接器连接到Particle Photon上。我加载了一些可在LCD上简略显示湿度的测试代码。代码运行成功后,我开始使用Fusion 360建模。我将此装置的形状设计为矩形棱柱,其正面、顶部以及背面分别配有LCD、LED和Micro USB接口。

物联网植物土壤湿度通知器图1

我还留了一个小洞,土壤湿度传感器可通过此孔布线。至于图案设计,我想以绿色为底,其上绘制一些黄色花卉图案。

制作

我的Fusion 360设计可用于数控雕刻,所以我把所有部件平稳地放在一个平面上,并从加工路径生成Gcode。接下来,我把准备的一张10.5" x 10.5" x 1/4"胶合板,放置于Millright数控机床上,开始切割各个部件。我还对各个部件进行打磨,使其边缘更为平滑,更具美感。


美化

首先,准备材料:经过数控雕刻的胶合板、一罐绿色喷漆、一罐虫胶、一小瓶黄色丙烯酸漆、若干150-400目砂纸、一瓶木胶和一个砂光机。

物联网植物土壤湿度通知器图3

我先依次使用低目数和高目数砂纸彻底打磨各个部件。

物联网植物土壤湿度通知器图4

在所有部件已被充分打磨后,我将底部、侧面和背面粘合在一起。接下来,我为各个部件喷涂了两层虫胶,之后再均匀喷上几层绿漆。

组装

所有部件都喷漆上色后,把电子元件放于外壳内部,并用热胶将其固定。我还通过侧面的小孔将土壤湿度传感器的电线与Photon相连接。
我还专门隔出了一小块区域,以便在装置停用时存放传感器和电线。

物联网植物土壤湿度通知器图5

编程

我在Particle Photon的云集成开发环境中加载了附图,并将其发送到我的Photon。顶部的RGB LED灯闪烁5次,表示Photon已成功启动并连接。编写代码时,我设置的是当湿度低于15%时,Photon会生成一个名为“浇水”的事件,触发IFTTT小程序。


用法

使用此装置时,只需把湿度传感器放入盆栽植物的土壤中,并将Micro USB数据线插入连接器,为装置供电 (5V)。之后,设置好IFTTT小程序,使其在收到Particle Photon服务发送的名为“干燥”的事件时发短信通知我。

物联网植物土壤湿度通知器图6

它会通过电子邮件发送:“您的植物需要浇水!”。此外,装置上的LCD会显示土壤水分的百分比以及植物的健康状况。现在,你再也不用担心植物是否缺水了。

物联网植物土壤湿度通知器图7

连线图

物联网植物土壤湿度通知器图8

代码
  1. //DFRobot.com
  2. //Compatible with the Arduino IDE 1.0
  3. //Library version:1.1
  4. #include <Wire.h>
  5. #include <LiquidCrystal_I2C.h>
  6. #define BLUE_PIN A3
  7. #define GREEN_PIN A4
  8. #define SOIL_SENSOR A1
  9. //#define RESOLUTION 1024 //Use for 10 bit resolution ADC (Arduino)
  10. #define RESOLUTION 4096 //Use for 12 bit resolution ADC (Particle Photon)
  11. #define DEBUG_VALS //Comment if you don't want values published to the Particle Cloud
  12. LiquidCrystal_I2C lcd(0x20,16,2);  // set the LCD address to 0x20(Cooperate with 3 short circuit caps) for a 16 chars and 2 line display
  13. int level;
  14. /*byte one_bar[8] = {
  15.     B00000,
  16.     B00000,
  17.     B00000,
  18.     B00000,
  19.     B00000,
  20.     B00000,
  21.     B00000,
  22.     B11111
  23. };
  24. byte two_bar[8] = {
  25.     B00000,
  26.     B00000,
  27.     B00000,
  28.     B00000,
  29.     B00000,
  30.     B00000,
  31.     B11111,
  32.     B11111
  33. };
  34. byte three_bar[8] = {
  35.     B00000,
  36.     B00000,
  37.     B00000,
  38.     B00000,
  39.     B00000,
  40.     B11111,
  41.     B11111,
  42.     B11111
  43. };
  44. byte four_bar[8] = {
  45.     B00000,
  46.     B00000,
  47.     B00000,
  48.     B00000,
  49.     B11111,
  50.     B11111,
  51.     B11111,
  52.     B11111
  53. };
  54. byte five_bar[8] = {
  55.     B00000,
  56.     B00000,
  57.     B00000,
  58.     B11111,
  59.     B11111,
  60.     B11111,
  61.     B11111,
  62.     B11111
  63. };
  64. byte six_bar[8] = {
  65.     B00000,
  66.     B00000,
  67.     B11111,
  68.     B11111,
  69.     B11111,
  70.     B11111,
  71.     B11111,
  72.     B11111,
  73. };
  74. byte seven_bar[8] = {
  75.     B00000,
  76.     B11111,
  77.     B11111,
  78.     B11111,
  79.     B11111,
  80.     B11111,
  81.     B11111,
  82.     B11111
  83. };
  84. byte eight_bar[8] = {
  85.     B11111,
  86.     B11111,
  87.     B11111,
  88.     B11111,
  89.     B11111,
  90.     B11111,
  91.     B11111,
  92.     B11111
  93. }; */
  94. bool is_spam = false;
  95.    
  96. void debug_values(int raw_value){
  97.     Particle.publish("soil_values_raw", String(raw_value));
  98. }
  99. void setup(){
  100.   
  101.    /*lcd.createChar(0, one_bar);
  102.    lcd.createChar(1, two_bar);
  103.    lcd.createChar(2, three_bar);
  104.    lcd.createChar(3, four_bar);
  105.    lcd.createChar(4, five_bar);
  106.    lcd.createChar(5, six_bar);
  107.    lcd.createChar(6, seven_bar);
  108.    lcd.createChar(7, eight_bar);*/
  109.   
  110.   pinMode(BLUE_PIN, OUTPUT);
  111.   pinMode(GREEN_PIN, OUTPUT);
  112.   pinMode(SOIL_SENSOR, INPUT);
  113.   lcd.init();                      // initialize the lcd
  114.   lcd.backlight();
  115.   
  116.   lcd_clear();
  117.   
  118.   lcd.setCursor(0, 0);
  119.   lcd.print("Plant hydration");
  120.   lcd.setCursor(0, 1);
  121.   lcd.print("monitor");
  122.   delay(4000);
  123. }
  124.   
  125. void loop(){
  126.   
  127.   int reading2 = take_reading();
  128.   
  129.   float reading = reading2;
  130.   
  131.   lcd.print("Water level:");
  132.   lcd.setCursor(0,1);
  133.   lcd.print(reading);
  134.   delay(1000);
  135.   
  136.   #ifdef DEBUG_VALS
  137.   debug_values(reading);
  138.   #endif
  139.   
  140.   Particle.publish("level", String(reading));
  141.   
  142.   if(reading >= .95*RESOLUTION){
  143.       lcd_clear();
  144.       lcd.print("Did you water");
  145.       lcd.setCursor(0,1);
  146.       lcd.print("too much?");
  147.       level = 16;
  148.   }
  149.   else if(reading >= .85*RESOLUTION){
  150.       lcd_clear();
  151.       lcd.print("That's plenty");
  152.       level = 14;
  153.   }
  154.   else if(reading >= .78*RESOLUTION){
  155.       lcd_clear();
  156.       lcd.print("Thanks for all");
  157.       lcd.setCursor(0,1);
  158.       lcd.print("of that water");
  159.       level = 13;
  160.   }
  161.   else if(reading >= .70*RESOLUTION){
  162.       lcd_clear();
  163.       lcd.print("Woah, that's");
  164.       lcd.setCursor(0,1);
  165.       lcd.print("a good drink");
  166.       level = 12;
  167.   }
  168.   else if(reading >= .65*RESOLUTION){
  169.       lcd_clear();
  170.       lcd.print("That makes me");
  171.       lcd.setCursor(0,1);
  172.       lcd.print("very happy");
  173.       level = 11;
  174.   }
  175.   else if(reading >= .60*RESOLUTION){
  176.       lcd_clear();
  177.       lcd.print("I love you");
  178.       lcd.setCursor(0,1);
  179.       lcd.print("more now");
  180.       level = 10;
  181.   }
  182.   else if(reading >= .55*RESOLUTION){
  183.       lcd_clear();
  184.       lcd.print("Meh, almost");
  185.       lcd.setCursor(0,1);
  186.       lcd.print("time for more");
  187.       level = 9;
  188.   }
  189.   else if(reading >= .50*RESOLUTION){
  190.       lcd_clear();
  191.       lcd.print("Did you water");
  192.       lcd.setCursor(0,1);
  193.       lcd.print("too much?");
  194.       level = 8;
  195.   }
  196.   else if(reading >= .45*RESOLUTION){
  197.       lcd_clear();
  198.       lcd.print("Still pretty");
  199.       lcd.setCursor(0,1);
  200.       lcd.print("content");
  201.       level = 7;
  202.   }
  203.   else if(reading >= .40*RESOLUTION){
  204.       lcd_clear();
  205.       lcd.print("Get ready for");
  206.       lcd.setCursor(0,1);
  207.       lcd.print("some watering!");
  208.       level = 6;
  209.   }
  210.   else if(reading >= .35*RESOLUTION){
  211.       lcd_clear();
  212.       lcd.print("I'm still");
  213.       lcd.setCursor(0,1);
  214.       lcd.print("waiting");
  215.       level = 5;
  216.   }
  217.   else if(reading >= .30*RESOLUTION){
  218.       lcd_clear();
  219.       lcd.print("OK, water me");
  220.       lcd.setCursor(0,1);
  221.       lcd.print("I'm very thirsty");
  222.       level = 4;
  223.   }
  224.   else if(reading >= .22*RESOLUTION){
  225.       lcd_clear();
  226.       lcd.print("Still no water?");
  227.       lcd.setCursor(0,1);
  228.       lcd.print("You're mean");
  229.       level = 3;
  230.   }
  231.   else if(reading >= .15*RESOLUTION){
  232.       lcd_clear();
  233.       lcd.print("Water please");
  234.       lcd.setCursor(0,1);
  235.       lcd.print("it's dry here!");
  236.       level = 2;
  237.   }
  238.   else if(reading >= .08*RESOLUTION){
  239.       lcd_clear();
  240.       lcd.print("I'm about");
  241.       lcd.setCursor(0,1);
  242.       lcd.print("to die");
  243.       level = 1;
  244.   }
  245.   else if(reading >= .04*RESOLUTION){
  246.       lcd_clear();
  247.       lcd.print("Blahhh :(");
  248.       lcd.setCursor(0,1);
  249.       lcd.print("you killed me");
  250.       level = 0;
  251.   }
  252.   delay(3000);
  253.   eval_level();
  254.   delay(4000);
  255.   lcd_clear();
  256.   no_green();
  257.   
  258. }
  259. void eval_level(){
  260.     if(level>8){
  261.         solid_green();
  262.     }
  263.     else if(level<8 && level != 0){
  264.         blink_blue(8, 250);
  265.         if(is_spam==false){
  266.         Particle.publish("dry", "True");
  267.         }
  268.         is_spam = true;
  269.     }
  270.     else if(level==8){
  271.         blink_blue(3, 250);
  272.     }
  273.     else if(level==0){
  274.         blink_blue(10, 250);
  275.     }
  276. }
  277. int take_reading(){
  278.     lcd_clear();
  279.     lcd.print("Taking reading");
  280.     int amount = analogRead(SOIL_SENSOR);
  281.     delay(1000);
  282.     lcd_clear();
  283.     return amount;
  284. }
  285. void blink_blue(int number_of_loops, int duration){
  286.     for(int i=0; i< number_of_loops; i++){
  287.         digitalWrite(BLUE_PIN, 1);
  288.         delay(duration);
  289.         digitalWrite(BLUE_PIN, 0);
  290.         delay(duration);
  291.     }
  292. }
  293. void solid_green(){
  294.     digitalWrite(GREEN_PIN, 1);
  295. }
  296. void no_green(){
  297.     digitalWrite(GREEN_PIN, 0);
  298. }
  299. void lcd_clear(){
  300.     lcd.clear();
  301.     lcd.setCursor(0,0);
  302. }
复制代码

此项目制作人为Arduino “having11” Guy,请点击这里查看原帖
来自DFRobot英文网站,转载需私信授权。

Miko  学徒

发表于 2021-4-17 22:27:05

这真不戳。。。。。。
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

为本项目制作心愿单
购买心愿单
心愿单 编辑
[[wsData.name]]

硬件清单

  • [[d.name]]
btnicon
我也要做!
点击进入购买页面
上海智位机器人股份有限公司 沪ICP备09038501号-4

© 2013-2024 Comsenz Inc. Powered by Discuz! X3.4 Licensed

mail