温馨提示:这篇文章已超过948天没有更新,请注意相关的内容是否还可用!
因临近春节回老家,无人照顾养的茉莉花,借鉴别人的思路新手照搬例程点灯APP自动浇花,分享出来希望大佬优化。代码杂乱不足之处嘴下留情
app截图
Arduino代码
#define BLINKER_WIFI #include <ArduinoJson.h>//此库需要放在Blinker.h库前不然会出现编译错误 #include <Blinker.h> #include <DHT.h> #define JDQ 12 //继电器信号引脚 #define TR 35 //土壤传感器信号引脚 #define DHTPIN 25 //温湿度传感器信号引脚 #define DHTTYPE DHT11 //温湿度传感器类型 #define ran "SliderKey" DHT dht(DHTPIN, DHTTYPE); char auth[] = "................."; /********************************************************************************************************* 新建数据类型组件对象,作用:将数据传输到手机blinker app *********************************************************************************************************/ BlinkerNumber TRZ("TRZ"); //blinker-app创建名为TRZ的数据模块显示土壤值 BlinkerNumber HUMI("humi");//blinker-app创建名为humi的数据模块显示湿度值 BlinkerNumber TEMP("temp");//blinker-app创建名为temp的数据模块显示温度值 BlinkerNumber RSS("rssi");//blinker-app创建名为huashi的数据模块显示华式温度 BlinkerNumber LU("ludian");//blinker-app创建名为ludian的数据模块显示露点值 BlinkerNumber HUMISJ("humi9");//blinker-app创建名为humi9的图表显示湿度历史数据 BlinkerNumber TEMPSJ("temp9");//blinker-app创建名为temp9的图标显示温度历史数据 BlinkerNumber TRZSJ("TRZ9");//blinker-app创建名为TRZ9的图标显示土壤值历史数据 BlinkerNumber CI("ci"); BlinkerSlider Slider1("ran"); BlinkerButton Button1("zhaoming"); BlinkerButton Button2("jiaoshui"); BlinkerText TURANG("turang"); BlinkerText BENG("beng"); BlinkerText YUNHANG("yunhang"); BlinkerText CITY("city"); BlinkerText WURAN("wuran"); BlinkerText PM("pm"); BlinkerText BTQX("btqx"); BlinkerText WSQX("wsqx"); BlinkerText BTWD("btwd"); BlinkerText WSWD("wswd"); BlinkerText BTFX("btfx"); /*********************************************************************************************************变量*********************************************************************************************************/ //天气 String city1, level1, pm251, forecasts_0_date1, forecasts_0_week1, forecasts_0_dayweather1, forecasts_0_nightweather1, forecasts_0_daytemp1, forecasts_0_nighttemp1, forecasts_0_daywind1, forecasts_0_nightwind1, forecasts_0_daypower1, forecasts_0_nightpower1;//天气及空气质量 int a3 = 0; //用于间隔更新天气 bool first_label = false; //开机标签,开机第一时间更新天气信息 //土壤值读取 uint16_t LeiJi[20];//存储土壤累计读取数值 uint16_t TRzhi;//土壤值 uint16_t Amin = 60700; //土壤最小校准值 uint16_t Amax = 24200; //土壤最大校准值 //空气温湿度 float n1 = 0.0, n2 = 0.0, t = 0, h = 0, rssi = 0; double humi_read = 0, temp_read = 0, huashi_read = 0, ludian_read = 0, ci_read = 0; //判断是否浇花 String turang_read, beng_read, T, B; int ci = 0, zhi = 40; //配网设置 int count = 0; //时间计数 bool WIFI_Status = true; //WIFI状态标志位 /********************************************************************************************************* Esptouch配网*********************************************************************************************************/ void blinkerConnect() //网络链接 { WiFi.begin();//没有这行命令ESP32断电重启不会自动连接WIFI BLINKER_LOG("\r\n正在连接WIFI..."); while (WiFi.status() != WL_CONNECTED) //判断是否连接WIFI成功 { if (WIFI_Status) { BLINKER_LOG("WIFI连接中"); digitalWrite(LED_BUILTIN, HIGH); delay(500); digitalWrite(LED_BUILTIN, LOW); delay(500); count++; if (count >= 30) //5s { WIFI_Status = false; BLINKER_LOG("WiFi连接失败,请用ESPtouch进行配网"); } } else { smartConfig(); } } BLINKER_LOG("连接成功IP地址为:", WiFi.localIP()); } void smartConfig()//ESPtouch配网 { WiFi.mode(WIFI_STA);//设置STA模式 BLINKER_LOG("\r\nWait for Smartconfig..."); WiFi.beginSmartConfig();//开始SmartConfig,等待手机端发出用户名和密码 while (1) { BLINKER_LOG("等待配网中"); digitalWrite(LED_BUILTIN, HIGH); //指示灯闪烁 delay(1000); digitalWrite(LED_BUILTIN, LOW); //指示灯闪烁 delay(1000); if (WiFi.smartConfigDone()) //配网成功,接收到SSID和密码 { BLINKER_LOG("配网成功"); BLINKER_LOG("SSID:", WiFi.SSID().c_str()); BLINKER_LOG("PSK:", WiFi.psk().c_str()); break; } } } /********************************************************************************************************* 土壤值读取*********************************************************************************************************/ void turang()//土壤值读取 { uint8_t i; for (i = 0; i < 20; i++) { //连续取采集多个样本,缺点AD读取会有延迟 LeiJi[i] = analogRead(TR); //读取土壤湿度传感器的值 Blinker.delay(100); } TRzhi = 0; //平均所有值 for (i = 0; i < 20; i++) { TRzhi += LeiJi[i]; } //Serial.println(TRzhi);//串口输出土壤值 TRzhi = map(TRzhi, Amin, Amax, 0, 100); //校准值转换成0-100 TRzhi = constrain(TRzhi, 0, 100); //将传感器值的范围限制在0到100之间 Blinker.delay(1000); } /*********************************************************************************************************室内温度值读取*********************************************************************************************************/ // 快速计算露点,速度是5倍dewPoint() double dewPointFast(double celsius, double humidity) { double a = 17.271; double b = 237.7; double temp = (a * celsius) / (b + celsius) + log(humidity / 100); double Td = (b * temp) / (a - temp); return Td; } void wenshidu() //空气温湿度值读取 { float h = dht.readHumidity(); float t = dht.readTemperature(); float hic = dht.computeHeatIndex(t, h, false); float n2 = (((9.0 / 5.0) * t + 32.0));//摄氏温度转为华式温度 float n1 = dewPointFast(dht.readTemperature(), dht.readHumidity());//计算露点 humi_read = h;//湿度值 temp_read = t;//温度值 huashi_read = n2;//华式温度 ludian_read = n1;//露点值 rssi = (WiFi.RSSI());//WIFI信号强度 Blinker.delay(1000); } /*********************************************************************************************************判断是否浇水*********************************************************************************************************/ void slider1_callback(int32_t value)//读取设定自动浇水阈值,初始值为40 { BLINKER_LOG("get slider value: ", value); zhi = value; } void gh() //读取的土壤值与设定的浇水阈值对比判断是否浇水 { if ((TRzhi < zhi) && (temp_read < 36) && (humi_read < 75)) { //如果读取土壤值小于自动浇水阈值且温度小于36度湿度低于75%则给继电器高电平信号打开水泵浇水 digitalWrite(JDQ, HIGH); //给继电器输出高电平打开水泵 Blinker.println("土壤干旱,需要浇水"); ci++; T = "土壤干旱"; B = "水泵打开"; Blinker.delay(3000); } else if ((TRzhi > zhi) && (humi_read < 75)) { //如果读取土壤值大于设定浇水阈值且湿度小于75%则给继电器低电平信号关闭水泵 digitalWrite(JDQ, LOW); //关闭LED灯 Blinker.println("土壤潮湿,不需要浇水"); T = "土壤湿润"; B = "水泵关闭"; Blinker.delay(3000); } else if (t > 36)//如果读取温度值大于36℃则给继电器低电平信号关闭水泵 { digitalWrite(JDQ, LOW); Blinker.println("温度过高,不适宜浇水"); T = "温度过高不适宜浇水"; B = "水泵关闭"; Blinker.delay(3000); } else if (humi_read > 75)//如果读取湿度值大于75%则给继电器低电平信号关闭水泵 { digitalWrite(JDQ, LOW); Blinker.println("空气湿度高,可能会下雨!"); T = "空气湿度高可能会下雨"; B = "水泵关闭"; Blinker.delay(3000); } } /*********************************************************************************************************记录历史数据*********************************************************************************************************/ void dataStorage()//记录历史数据 { Blinker.dataStorage("humi9", humi_read); Blinker.dataStorage("temp9", temp_read); Blinker.dataStorage("TRZ9", TRzhi); } void printlf() //打印调试信息 { BLINKER_LOG("空气湿度:", humi_read, " %"); BLINKER_LOG("摄氏温度: ", temp_read, " *C"); BLINKER_LOG("华氏温度: ", huashi_read, " °F"); BLINKER_LOG("露点: ", ludian_read, " Td"); BLINKER_LOG("土壤湿度: ", TRzhi, " %"); BLINKER_LOG("浇水阈值: ", zhi, " %"); BLINKER_LOG("自动浇水次数:", ci, " 次"); BLINKER_LOG("当前土壤状态:", T, ""); BLINKER_LOG("当前水泵状态:", B, ""); BLINKER_LOG("当前WIFI信号强度:", rssi, "db"); } /********************************************************************************************************* 手动浇水*********************************************************************************************************/ void button2_callback(const String & state)//手动浇水 { BLINKER_LOG("get button state: ", state); if (state == "on") { digitalWrite(JDQ, HIGH); // 反馈开关状态 Button2.print("on"); B = "开始手动浇水"; } if (state == "off") //按照例程else if无法关闭 { digitalWrite(JDQ, LOW); // 反馈开关状态 Button2.print("off"); B = "停止手动浇水"; } Blinker.delay(300); } void button1_callback(const String & state) //原计划设置光照补偿(无用改为系统指示灯开关) { BLINKER_LOG("get button state: ", state); if (state == "on") { digitalWrite(LED_BUILTIN, HIGH); // 反馈开关状态 Button1.print("on"); BENG.print("系统指示灯开启"); } if (state == "off") { digitalWrite(LED_BUILTIN, LOW); // 反馈开关状态 Button1.print("off"); BENG.print("系统指示灯关闭"); } Blinker.delay(300); } /*********************************************************************************************************系统运行时间*********************************************************************************************************/ String rts() { int rt = Blinker.runTime(); int r, e, f, s; String fh; Blinker.delay(100); if (rt >= 86400) //天数 { r = rt / 86400; e = rt / 3600 - r * 24; f = rt / 60 - r * 1440 - e * 60; s = rt - r * 86400 - e * 3600 - f * 60; } else if (rt >= 3600) { r = 0; e = rt / 3600; f = rt / 60 - e * 60; s = rt - e * 3600 - f * 60; } else { r = 0; e = 0; f = rt / 60; s = rt - f * 60; } if (f == 0 & e == 0 & r == 0) { fh = String("") + s + "秒"; } else if (r == 0 & e == 0 ) { fh = String("") + f + "分" + s + "秒"; } else if (r == 0) { fh = String("") + e + "小时" + f + "分" + s + "秒"; } else { fh = String("") + r + "天" + e + "小时" + f + "分" + s + "秒"; } return (fh); } /*********************************************************************************************************天气数据及空气数据读取*********************************************************************************************************/ void airData(const String & data) //空气质量 { BLINKER_LOG("air: ", data); const size_t capacity = JSON_OBJECT_SIZE(11) + 120; DynamicJsonDocument doc(capacity); DeserializationError error = deserializeJson(doc, data); if (error) { Serial.print(F("deserializeJson() failed: ")); Serial.println(error.c_str()); return; } const char* city = doc["city"]; const char* updateTime = doc["updateTime"]; const char* aqi = doc["aqi"]; const char* level = doc["level"]; const char* pm25 = doc["pm25"]; const char* pm10 = doc["pm10"]; const char* SO2 = doc["SO2"]; const char* NO2 = doc["NO2"]; const char* CO = doc["CO"]; const char* O3 = doc["O3"]; city1 = city; level1 = level; pm251 = pm25; BLINKER_LOG("城市:", city1);//1 BLINKER_LOG("更新时间:", updateTime); BLINKER_LOG("aqi:", aqi); BLINKER_LOG("污染程度:", level1); //2 BLINKER_LOG("pm25:", pm251);//3 BLINKER_LOG("pm10:", pm10); BLINKER_LOG("SO2:", SO2); BLINKER_LOG("NO2:", NO2); BLINKER_LOG("CO:", CO); BLINKER_LOG("O3:", O3); } void weatherForecastData(const String & data)//天气 { BLINKER_LOG("weather: ", data); const size_t capacity = JSON_ARRAY_SIZE(4) + JSON_OBJECT_SIZE(4) + 4 * JSON_OBJECT_SIZE(10) + 650; DynamicJsonDocument doc(capacity); DeserializationError error = deserializeJson(doc, data); if (error) { Serial.print(F("deserializeJson() failed: ")); Serial.println(error.c_str()); return; } const char* city = doc["city"]; const char* province = doc["province"]; const char* updateTime = doc["updateTime"]; JsonArray forecasts = doc["forecasts"]; JsonObject forecasts_0 = forecasts[0]; const char* forecasts_0_date = forecasts_0["date"]; const char* forecasts_0_week = forecasts_0["week"]; const char* forecasts_0_dayweather = forecasts_0["dayweather"]; const char* forecasts_0_nightweather = forecasts_0["nightweather"]; const char* forecasts_0_daytemp = forecasts_0["daytemp"]; const char* forecasts_0_nighttemp = forecasts_0["nighttemp"]; const char* forecasts_0_daywind = forecasts_0["daywind"]; const char* forecasts_0_nightwind = forecasts_0["nightwind"]; const char* forecasts_0_daypower = forecasts_0["daypower"]; const char* forecasts_0_nightpower = forecasts_0["nightpower"]; forecasts_0_dayweather1 = forecasts_0_dayweather; forecasts_0_nightweather1 = forecasts_0_nightweather; forecasts_0_daytemp1 = forecasts_0_daytemp; forecasts_0_nighttemp1 = forecasts_0_nighttemp; forecasts_0_daywind1 = forecasts_0_daywind; BLINKER_LOG("城市:", city); BLINKER_LOG("更新时间:", updateTime); BLINKER_LOG("时间:", forecasts_0_date); BLINKER_LOG("星期:", forecasts_0_week); BLINKER_LOG("白天天气现象:", forecasts_0_dayweather);//4 BLINKER_LOG("晚上天气现象:", forecasts_0_nightweather);//5 BLINKER_LOG("白天温度:", forecasts_0_daytemp);//6 BLINKER_LOG("晚上温度:", forecasts_0_nighttemp);//7 BLINKER_LOG("白天风向:", forecasts_0_daywind);//8 BLINKER_LOG("晚上风向:", forecasts_0_nightwind); BLINKER_LOG("白天风力:", forecasts_0_daypower); BLINKER_LOG("晚上风力:", forecasts_0_nightpower); } void jggxtq() //时间段判断更新 { int8_t hour = Blinker.hour();//时 int8_t min = Blinker.minute();//分 BLINKER_LOG("判断是否更新天气"); if (hour == 8) { a3 = 8; } if (hour == 10) { a3 = 10; } if (hour == 14) { a3 = 14; } if (hour == 16) { a3 = 16; } if (hour == 18) { a3 = 18; } if (hour == 21) { a3 = 21; } if (hour == 20) { a3 = 20; } if (hour == 22) { a3 = 22; } if (hour == 23) { a3 = 23; } if (hour == a3) { if (min == 0) { BLINKER_LOG("开始更新天气"); Blinker.weatherForecast(); Blinker.air(); Blinker.delay(4000); } } } /*********************************************************************************************************心跳发送数据到手机APP*********************************************************************************************************/ void heartbeat()//心跳 发送数据到手机APP { HUMI.print(humi_read);//湿度 TEMP.print(temp_read);//温度 TRZ.print(TRzhi);//土壤值 RSS.print(rssi);//华式温度值 LU.print(ludian_read);//露点值 CI.print(ci_read);//水泵浇水次数 TURANG.print(T);//土壤状态 BENG.print(B);//水泵状态 YUNHANG.print(rts());//显示系统运行时间 Slider1.print(zhi);//浇水阈值 CITY.print(city1);//显示城市 WURAN.print(level1);//显示污染程度 PM.print(pm251);//显示PM值 BTQX.print(forecasts_0_dayweather1);//白天天气气象 WSQX.print(forecasts_0_nightweather1); //晚上天气气象 BTWD.print(forecasts_0_daytemp1);//白天温度 WSWD.print(forecasts_0_nighttemp1);//晚上温度 BTFX.print(forecasts_0_daywind1);//白天风向 } void setup() { first_label = true; pinMode (JDQ, OUTPUT); pinMode(LED_BUILTIN, OUTPUT); digitalWrite(LED_BUILTIN, LOW); Serial.begin(115200);//打开串口波特率设置115200 BLINKER_DEBUG.debugAll();//开启调试 BLINKER_DEBUG.stream(Serial); Blinker.begin(auth, WiFi.SSID().c_str(), WiFi.psk().c_str()); //根据配网得到的WIFI信息和设备秘钥,连接到Blinker云 blinkerConnect();//连接网络 Blinker.attachHeartbeat(heartbeat); Blinker.attachDataStorage(dataStorage);//开启历史数据 Blinker.attachAir(airData);//注册空气质量 Blinker.attachWeatherForecast(weatherForecastData);//注册天气 Slider1.attach(slider1_callback); Button1.attach(button1_callback); Button2.attach(button2_callback); dht.begin(); } void loop() { Blinker.run(); //通电更新天气及空气质量 if ((first_label == true)) { if (Blinker.init()) { Blinker.weatherForecast(); Blinker.air(); Blinker.delay(2000); first_label = false; } } turang(); wenshidu(); Blinker.delay(2000); gh(); printlf(); ci_read = ci;//浇水次数 jggxtq(); }
文章版权声明:除非注明,否则均为半星笔记原创文章,转载或复制请以超链接形式并注明出处。
还没有评论,来说两句吧...