自制ESP32cam远程控制浇水系统.docx
- 文档编号:11730433
- 上传时间:2023-03-31
- 格式:DOCX
- 页数:49
- 大小:3.26MB
自制ESP32cam远程控制浇水系统.docx
《自制ESP32cam远程控制浇水系统.docx》由会员分享,可在线阅读,更多相关《自制ESP32cam远程控制浇水系统.docx(49页珍藏版)》请在冰豆网上搜索。
自制ESP32cam远程控制浇水系统
自制ESP32-cam远程控制浇水系统
今年在疫情的影响下,有了些空余时间。
南京的梅雨过后天气开始热了。
一直想做一个远程控制浇水的系统。
开始了解Arduino编程,买了不少ESP8266、ESP32-Cam、继电器、电机等等,过程中遇到不少问题都查资料逐一解决,但是动手能力还是弱了些,最后总算完成,达到预期目标。
经过2个月的测试,现在把成功的写出来,分享给一样有兴趣的朋友。
(成品图)
(浇水中)
测试过程中为了能走出试验室,进入实际使用中,作了不少优化。
最大点就是电源了。
拖拉电线是件很麻烦的事情,拖拉电线既不美观也不安全,浇水都是在室外的多,要适应各种天气,暴晒、下雨、下雪。
12V的点是没有任何危险的。
而且可以随意放,只要靠近水龙头就可以。
接上后,水龙头是长开着的,所以在断电,电池没电,网络中断等情况下,电磁阀要保持长闭合状态,防止水失控。
这些方面都作了多次测试。
10000毫安的充电宝只能提供最多4天的ESP32-Cam的电力。
12v5a的蓄电池通过降压模块只能提供5V和12V最多3天的电力。
这是不能满足需求的,我们正常出门一次,如果天数较多,1个月时需要的。
浇水系统一天只会在早晨或晚上浇水,其余时间都是不需要的。
好在ESP32有这方面的考虑,有deep-sleep功能,可以深度休眠,使用Timer隔一段时间后唤醒就好。
如果一天只运行指定的一个小时段,这样1天就换回了24天,就能满足需求了。
一个12v5a蓄电池可以满足30天左右。
材料
在淘宝、京东、拼多多都可以买。
以下是我在淘宝购买的记录
总共花费:
290.2,浇水实用到的物品费用:
232.73
接线
ESP-Cam需要5V电压,所以用一个TTLUSB接头,USB接头插入电脑USB口可以供电,烧入Arduino程序。
ESP32-Cam说明:
Ø烧入程序时接线:
TX接ESP-CamRXD
RX接ESP-CamTXD
5V连接ESP-Cam5V
GND连接ESP-CamGND
ESP-CamIO0要和GND用冒连接
Ø运行时接线:
本程序运行时只使用5V、GND、GPIO13三个角针。
5V、GND是供电,GPIO13是输出继电器信号。
(运行时继电器的接线)
Ø继电器接线:
用杜邦线连接ESP32-CamGPIO13和图示中的口。
5V电压输入、GND和ESP32-Cam的电源共用。
12V电压输入和12输出串联在蓄电池和电磁阀之间。
5V的电源可以是12V蓄电池降压得到。
这样12V电磁阀和5V的ESP32-Cam、继电器可以共用一个电源。
如果想用家里的充电宝提供5V电源,用USBDip接头可以插入充电宝,为5V的ESP32-Cam、继电器供电,12V的电磁阀单独由蓄电池供电。
ESP-Cam中的程序控制GPO13端口输入高电平,低电平来控制继电器开和关。
这款继电器输入高电平时是关闭的,输入低电平是打开的。
Ø降压器使用
Ø水接线
水接线是个体力活,雾化喷头按购买的说明结合自家的花草情况进行部署。
电池阀的水接方法:
Arduino程序
ØArduino环境准备
1.Arduino可以官网下载,安装Arduino,我用的是1.8.12版本。
2.安装ESP32开发组建:
esp32_package_v1_0_2.exe可以网上找,找不到可以QQ我发,直接运行
3.Arduino要打ESP32_AzureIoT_Arduino补丁
ESP32_AzureIoT_Arduino.zip解压到
C:
\Users\admin\Documents\Arduino\hardware\espressif\esp32\libraries\AzureIoT
4.安装ESP32开发库,需要安装的库如下:
ArduinoJson-5.11.2.zip--JSON操作包
time-master.zip--时间包
CH341SER.ZIP--寄存器操作,存储wifi和服务地址
加载库如下页面操作:
设置:
Ø烧入程序:
按上面的接线完毕后,TTLUSB插入电脑USB,电脑打开Arduino,打开Waiter程序,点击写入就可以。
#include"esp_camera.h"
#include
#include
#include
#include
#defineCAMERA_MODEL_AI_THINKER//指定摄像头的模式,只能用这种
#include"camera_pins.h"
#definerelay13//ESP32指定继电器的控制针脚
booleansaveElc=true;//是否开启省点模式,只有在一个时间开启服务
StringstartTimeOfDay="6:
30:
00,18:
30:
00";//每天开启时间,逗号分割可以多个,这个取决于服务端的逻辑控制。
StringendTimeOfDay="7:
00:
00,19:
00:
00";//每天关闭时间
intdefaultStatus=HIGH;//默认继电器是高电平,关闭状态。
WiFiServerserver(8080);//ap模式下的服务端口,用于刚开始时设置wifi的密码和应用程序地址
//----wificonnectionandsyncdatatoiotserver
StringobjName="water";//设备类型
StringuserName="Wong";//用户名称
StringloginAcct="WFIOT";//服务端用户帐号
StringseqNum="01";//设备序列
StringuserId="1111000";//用户编号
StringmacAds;
intiotPort;
StringiotIp;
StringnetIp;
//web服务端需要有以下API接口用于和该设备通信和控制。
Web服务部署在Wifi局域网内。
StringiotCheckUrl="addIotUser";//服务端需要有的API名称,创建用户并检查用户是否存在。
StringiotSleepTime="getSleepSeconds";//获取休眠的时长,单位秒。
StringiotServiceUrl="getIotData";//设备获取服务端的指令,如关闭继电器,开启继电器。
StringiotUpdateServiceUrl="updateIotData";//设备断电重启时更新WifiIP到服务端。
intprocessStatus=0;
intrecovercount=0;
Stringssid;
Stringpwd;
structconfig_type
{
chariotIp[24];//定义配网得到的WIFI密码长度(最大64字节)
chariotPort[12];
charssid[24];
charpwd[24];
};
config_typecfg;
//web服务端存储的设备记录信息。
StringgetDesc(){
return"{\"iot_object\":
\""+objName+"\","
+"\"iot_object_mac\":
\""+macAds+"\","
+"\"iot_data\":
\""+getIotData()+"\","
+"\"user_name\":
\""+userName+"\","
+"\"user_obj_seq\":
\""+seqNum+"\","
+"\"user_id\":
\""+userId+"\","
+"\"net_ip\":
\""+netIp+"\","
+"\"app_ip\":
\""+iotIp+"\","
+"\"is_sleep\":
\""+saveElc+"\","
+"\"start_time\":
\""+startTimeOfDay+"\","
+"\"end_time\":
\""+endTimeOfDay+"\","
+"\"app_port\":
\""+String(iotPort)+"\","
+"\"register_srv\":
\""+iotCheckUrl+"\","
+"\"sync_data_srv\":
\""+iotServiceUrl+"\","
+"\"login_code\":
\""+loginAcct+"\","
+"}";
}
//请求web服务的路径
StringgetIotData(){
return"{imageUrl:
['http:
//"+netIp+"/control?
var=framesize&val=6','http:
//"+netIp+"/capture?
_cb=1593852828143'],relay:
'OFF'}";
}
voidloadConfig()//读取函数
{
EEPROM.begin(1024);
uint8_t*p=(uint8_t*)(&cfg);
for(inti=0;i { *(p+i)=EEPROM.read(i); } EEPROM.commit(); } voidsaveConfig()//保存函数 { Serial.println("saveConfig..."); EEPROM.begin(1024);//向系统申请1024kbROM //开始写入 uint8_t*p=(uint8_t*)(&cfg); for(inti=0;i { EEPROM.write(i,*(p+i));//在闪存内模拟写入 } EEPROM.commit();//执行写入ROM } intsetup_connectWifi(Stringssid,Stringpwd,StringlocalhostName){ if(ssid! =""&&pwd! =""){ WiFi.begin(ssid.c_str(),pwd.c_str()); }else{ WiFi.begin(); } intn=0; while(WiFi.status()! =WL_CONNECTED){ delay(100); n++; if(n>100){ Serial.print("Connected"+ssid+",fail"); return0; } Serial.print("."); } netIp=String(WiFi.localIP()[0])+"."+String(WiFi.localIP()[1])+"."+String(WiFi.localIP()[2])+"."+String(WiFi.localIP()[3]); Serial.println("connectedworkwifi"+netIp+"by"+ssid); if(iotIp){ setMac(); Stringtxt=sendHtmlPost(iotIp,iotPort,iotUpdateServiceUrl,"{\"user_id\": \""+userId+"\",\"iot_object_mac\": \""+macAds+"\",\"iot_data\": \""+getIotData()+"\"}"); Serial.println(txt); } return1; } voidsetMac(){ bytemac[6]; WiFi.macAddress(mac); macAds=String(mac[5])+": "+String(mac[4])+": "+String(mac[3])+": "+String(mac[2])+": "+String(mac[1])+": "+String(mac[0]); } voidstartReg(){ processStatus=1; setup_wifiAP_STA(); setup_server(); } voidsetup_wifiAP_STA(){ Serial.print("beginsetap..."); IPAddresslxip(192,168,2,1); IPAddresslxip1(192,168,2,1); IPAddresslxip2(255,255,255,0); setMac(); Serial.println("mac: "+macAds); Stringssid=String("TB_IOT-")+userName+""+objName+seqNum; Stringpassword=""; WiFi.mode(WIFI_AP_STA); WiFi.softAPConfig(lxip,lxip1,lxip2); WiFi.softAP(ssid.c_str(),password.c_str(),1); Serial.print("finishedsetap,pleaseconnect"); Serial.print(WiFi.softAPIP()); Serial.println(": 8080"); } voidsetup_server(){ server.begin(); Serial.println("startedhttpserver"); } booleanparseServerRequest(){ WiFiClientclient=server.available(); if(client){ Serial.println("[Clientconnected]"); StringfirstLine; Stringresposnehtml; intishead=1; intn=0; booleanflag=false; while(! client.connected()||! client.available()){ delay (1); n++; if(n>100){ delay(100); Serial.println("[serverwaittimeout]"); client.stop(); returnfalse; } Serial.print("."); } while(client.connected()||client.available()){ if(client.available()){ Stringline=client.readStringUntil('\r'); Serial.println(line); if(firstLine==NULL){ firstLine=line; //getwifiinfo...GET/queryServerList? ssid=wf&password=144565HTTP/1.1 Stringpars[5]; parseHtmlQueryString(firstLine,pars); Stringtype=pars[0]; if(type=="home"){ resposnehtml=homePage("","","","",""); }elseif(type=="queryServerList"){ //parseOutssidpassword if(pars[1]! =NULL&&pars[2]! =NULL&&pars[3]! =NULL){ intret=setup_connectWifi(pars[1],pars[2],objName+seqNum); if(ret==1){ Stringdata=checkAndUpdateDesc(pars[3],pars[4].toInt(),iotCheckUrl,iotServiceUrl,getDesc()); Stringf=data.substring(0,1); Stringmsg=data.substring (1); if(f=="Y"){ resposnehtml=successHtml(msg);//successclosewindow flag=true; }else{ resposnehtml=homePage("connectiotserverfail. } }else{ resposnehtml=homePage("SSID,Passwordfail,can'tconnectwifi,pleasecheck",pars[1],pars[2],pars[3],pars[4]); } }else{ resposnehtml=homePage("SSID,Password,IotIPisnull,pleasecheck",pars[1],pars[2],pars[3],pars[4]); } } if(resposnehtml! =NULL){ //Serial.println(client.status()); if(client.connected()){ Serial.println("response: "+resposnehtml); client.println(resposnehtml); delay(100); client.flush(); delay(1000); } } client.stop(); Serial.println("[Clientdisonnected]"); if(flag){ WiFi.mode(WIFI_STA); Serial.println("setwifimodeSTA"); if(setup_connectWifi(pars[1],pars[2],objName+seqNum)==1){ Serial.println("connected"+pars[1]); processStatus=0; strcpy(cfg.iotIp,pars[3].c_str()); strcpy(cfg.iotPort,pars[4].c_str()); strcpy(cfg.ssid,pars[1].c_str()); strcpy(cfg.pwd,pars[2].c_str()); Stringt=cfg.iotIp; saveConfig(); WiFi.setAutoConnect(true); Serial.println("savedconfigdatatocash"); }else{ Serial.println("can'tconnectwifi"+pars[1]); } } returntrue; } break; }else{ break; } } Serial.println("[Clientdisonnected2]"); client.stop(); returntrue; }else{ returnfalse; } } voidparseHtmlQueryString(Stringqstring,String*ret){ Stringtxt=GetRidOfurlCharacters(qstring); Serial.println(txt); Stringurl=txt.substring(txt.indexOf("/")+1,txt.indexOf("\r")); intn=url.indexOf("? "); if(n! =-1){ Stringa=url.substring(0,url.indexOf("? ")); ret[0]=a; Stringq=url.substring(url.indexOf("? ")+1,url.indexOf("HTTP")); ret[1]=q.substring(q.indexOf("ssid=")+5,q.indexOf("&p")); ret[2]=q.substring(q.indexOf("password=")+9,q.indexOf("&ioti")); ret[3]=q.substring(q.indexOf("iotip=")+6,q.indexOf("&iotp")); ret[4]=q.substring(q.indexOf("iotport=")+8,q.indexOf("")); iotIp=ret[3]; iotPort=ret[4].toInt(); }else{ ret[0]="home"; } Serial.println("0: "+ret[0]); Serial.println("1: "+ret[1]); Serial.println("2: "+ret[2]); Serial.println("3: "+ret[3]); } StringGetRidOfurlCharacters(StringurlChars) { urlChars.replace("%0D%0A",String('\n')); urlChars.replace("+",""); urlChars.replace("%20",""); urlChars.replace("%21","! "); urlChars.replace("%22",String(char('\"'))); urlChars.replace("%23","#"); urlChars.replace("%24","$"); urlChars.replace("%25","%"); urlChars.replace("%26","&"); urlChars.replace("%26%2365281%3B","! "); urlChars.replace("%27",String(char(39))); urlChars.replace("%28","("); urlChars.replace("%29",")"); urlChars.replace("%2A","*"); urlChars.rep
"+msg,pars[1],pars[2],pars[3],pars[4]);
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 自制 ESP32cam 远程 控制 浇水 系统