使用Arduino创建智能灌溉控制器通过动态水循环智能灌溉您的院子。同时使用光传感器检测日出时间并相应地自动调整灌溉的开始时间。但当天气太冷的时候,请停止使用此系统给院子浇水。可实现的功能列表室外温度传感器室外雨量传感器外光传感器电池支持的实时时钟,用于每周调度非易失性存储-永远不会因断电而失去浇水日出检测智能浇水节省您的水费日出前浇水以留出适当的浸泡时间减少真菌生长轻松的日程控制构建智能灌溉控制器所需的部件IO扩展器x21-Wire到I2C。1-Wire结光连接器分路器ArduinoNano4通道直流5V继电器。TSL2561光传感器。DS18B20防水温度传感器。光学红外水位传感器。DS3231AT24C32IIC精密实时时钟。I2CSSD1306OLED128x64显示器。200x120x75mm透明防水塑料外壳。100x68x50mm透明防水塑料外壳。ip68pg7防水尼龙电缆接头。ip68pg11防水尼龙电缆接头。RJ11Keystone螺丝端子插孔。50英尺4C4PRJ11线。6英尺4C4PRJ11线。2.54毫米头线。x22针单刀单掷瞬时按钮微动开关12VDC1A墙壁适配器电源。接线图OLED显示器通过按下菜单按钮显示菜单并继续按下按钮以循环浏览所有菜单选项。界面停止活动30秒后菜单将自动退出。按选择按钮执行所需的菜单功能。那么为什么要使用IO扩展器呢?设计更简单现成的零件无需编写1-Wire驱动程序无需编写DS3231RTC驱动程序无需写入EEPROM驱动程序无需编写OLED显示驱动程序没有显示字体占用Arduino代码空间无需编写温度传感器驱动程序无需写入光学雨量传感器驱动器节省Arduino上的代码空间;仅12710字节(39%)写代码只用了三天使用标准RJ11电话线轻松接线没有传感器电缆长度问题比类似的商业系统更便宜易于更改以适应个性化需求单电源构建系统将ArduinoNano连接到IO扩展器并使用以下代码对其进行编程。确保更改ONEWIRE_TO_I2C_ROM1和ONEWIRE-TO_I2C_ROM2定义的地址以匹配您的1-Wire到I2C地址。/*IOExpandersketchoptimized**IrrigationSystemv1.1**/#include#include//Filelocated\ProgramFiles(x86)\Arduino\hardware\tools\avr\avr\include\time.h#include#include#include#include"IOExpander.h"#defineFAHRENHEIT#defineINIT_BOARD"g5w1;g11w1;g11d0,75;g12w1;g12d0,75;rsf"#defineONEWIRE_TO_I2C_ROM1"i4scc"#defineONEWIRE_TO_I2C_ROM2"i6s8f"#defineONEWIRE_TEMPERATURE"t6s0300"#defineRTC_SENSOR"s4te"#defineI2C_EEPROM"s4tf"#defineI2C_OLED"s4t10"#defineI2C_LIGHT"s3t9;sc0"#defineOPTICAL_SENSOR"g5a"#defineBUTTON1"g11d"#defineBUTTON2"g12d"#defineWATER_TIME_BEFORE_SUNRISE60#defineSUNRISE_LUX100#defineRAIN_DETECT_LEVEL4.0#defineDO_NOT_WATER_TEMP4.4444//40F#defineMAX_ZONES4#defineHOUR_IN_DAY24L#defineMIN_IN_HOUR60L#defineSEC_IN_MIN60L#defineSEC_IN_HOUR(MIN_IN_HOUR*SEC_IN_MIN)#defineSEC_IN_DAY(HOUR_IN_DAY*SEC_IN_HOUR)#defineDAYS_IN_WEEK7#defineSEC_IN_WEEK(SEC_IN_DAY*DAYS_IN_WEEK)#defineSUN0x01#defineMON0x02#defineTUE0x04#defineWED0x08#defineTHR0x10#defineFRI0x20#defineSAT0x40#defineEVERYDAY(SUN|MON|TUE|WED|THR|FRI|SAT)#defineSUNRISE0x80#defineMENU_OPTIONS9#defineMENU_TIME30#defineOFF0#defineON1#defineSTATE_ON_OFF0x01//#defineSERIAL_DEBUG#ifdefSERIAL_DEBUGSoftwareSerialswSerial(8,7);#endifcharweekday[][4]={"SUN","MON","TUE","WED","THU","FRI","SAT"};charmenu[][13]={"Next","Water","Reset","ClockMin+","ClockMin-","ClockHour+","ClockHour-","Sunrise","ON/OFF"};enum{MENU_NEXT,MENU_WATER,MENU_RESET,MENU_CLOCK_MIN_PLUS,MENU_CLOCK_MIN_MINUS,MENU_CLOCK_HOUR_PLUS,MENU_CLOCK_HOUR_MINUS,MENU_SUNRISE,MENU_ON_OFF};typedefstruct{chardescription[16];uint8_trelay;}ZONE;typedefstruct{uint8_tzone;uint8_tdays;int8_thour;int8_tmin;uint8_tduration;}SCHEDULE;typedefstruct{time_tsunrise_time;time_tlast_water_time;uint8_twater_schedule;uint8_twater_duration;uint8_train[MAX_ZONES];uint8_tstate;uint8_tcrc;}NVRAM;enum{ZONE1,ZONE2,ZONE3,ZONE4};enum{RELAY1=1,RELAY2,RELAY3,RELAY4};ZONEzone[]={{"FrontRight",RELAY1},{"FrontLeft",RELAY2},{"Bushes",RELAY3},{"LeftSide",RELAY4},};SCHEDULEschedule[]={{ZONE1,SUNRISE|EVERYDAY,-1,0,4},{ZONE2,EVERYDAY,6,15,5},{ZONE3,EVERYDAY,6,0,10},{ZONE4,EVERYDAY,6,10,6},};NVRAMnvram;boolupdate_nvram=false;uint8_tcrc8(uint8_t*data,uint16_tlength){uint8_tcrc=0;while(length--){crc=_crc8_ccitt_update(crc,*data++);}returncrc;}intled=13;boolinit_oled=true;boolupdate_oled=true;boolinit_board=true;#ifdefFAHRENHEIT#defineC2F(temp)CelsiusToFahrenheit(temp)floatCelsiusToFahrenheit(floatcelsius){return((celsius*9)/5)+32;}#else#defineC2F(temp)(temp)#endifvoidSerialPrint(constchar*str,floatdecimal,charerror){Serial.print(str);if(error)Serial.print(F("NA"));elseSerial.print(decimal,1);}time_tNextScheduleTime(time_tlast_time,uint8_t*next_schedule){time_tnext_time=-1;time_tclk_time;uint8_ti;tmclk;uint8_twday;for(i=0;iif(schedule[i].days&SUNRISE){clk_time=nvram.sunrise_time;clk_time+=schedule[i].hour*SEC_IN_HOUR;clk_time+=schedule[i].min*SEC_IN_MIN;localtime_r(&clk_time,&clk);}else{localtime_r(&last_time,&clk);clk.tm_hour=schedule[i].hour;clk.tm_min=schedule[i].min;clk.tm_sec=0;clk_time=mktime(&clk);}wday=clk.tm_wday;while(clk_time{clk_time+=SEC_IN_DAY;if(++wday>SATURDAY)wday=SUNDAY;if(wday==clk.tm_wday)break;//Onlycheckoneweek}if(clk_timenext_time=clk_time;*next_schedule=i;}}returnnext_time;}voidStartScheduleTime(time_tstart_time,uint8_tstart_schedule){uint8_ti;nvram.last_water_time=start_time;nvram.water_schedule=start_schedule;nvram.water_duration=schedule[start_schedule].duration+1;update_nvram=true;//Checkifitrainedi=schedule[start_schedule].zone;if(i0){if(nvram.rain[i]>nvram.water_duration)nvram.water_duration=0;elsenvram.water_duration-=nvram.rain[i];nvram.rain[i]=0;}}voidWaterScheduleTime(void){uint8_ti;nvram.water_duration--;update_nvram=true;i=schedule[nvram.water_schedule].zone;if(iSerial.print("r");Serial.print(zone[i].relay);if(nvram.water_duration>0)Serial.println("o");elseSerial.println("f");SerialReadUntilDone();}}voidsetup(){Serial.begin(115200);#ifdefSERIAL_DEBUGswSerial.begin(115200);#endifpinMode(led,OUTPUT);//delay(1000);wdt_enable(WDTO_8S);}voidloop(){statictmrtc;tmclk,sunrise_clk;time_trtc_time;time_tclk_time;statictime_tnext_time;staticuint8_tlast_sec;staticuint8_tlast_min;boolerror_rtc;boolerror_light;boolerror_temp;staticlonglux=0;staticfloattemp,rain;staticuint8_tsunrise_counter=MIN_IN_HOUR;staticboolcheck_sunrise=false;uint8_ti;staticboolread_nvram=true;statictime_twater_time;staticuint8_twater_schedule;uint8_tsz;uint8_twday;longn;boolbutton1,button2;staticint8_tmenu_select=-1;statictime_tmenu_time=0;Serial.println();if(SerialReadUntilDone()){if(init_board){SerialCmdDone(INIT_BOARD);init_board=false;}if(init_oled){if(SerialCmdNoError(ONEWIRE_TO_I2C_ROM1)){SerialCmdDone(I2C_OLED";si;sc;sd");init_oled=false;}}if(SerialCmdDone(RTC_SENSOR)){error_rtc=!SerialReadTime(&rtc);if(!error_rtc){clk=rtc;//mktime()canchangestructtmrtc_time=mktime(&clk);localtime_r(&rtc_time,&rtc);//Getwday.}if(read_nvram){if(SerialCmdNoError(I2C_EEPROM)){SerialReadEEPROM((uint8_t*)&nvram,0,sizeof(nvram));if(nvram.crc!=crc8((uint8_t*)&nvram,sizeof(nvram)-sizeof(uint8_t))){//swSerial.println("CRC8Failure!");//Initializenvrammemset(&nvram,0,sizeof(nvram));clk=rtc;clk.tm_hour=6;clk.tm_min=0;clk.tm_sec=0;nvram.sunrise_time=mktime(&clk);if(nvram.sunrise_timeupdate_nvram=true;}//Checklastwatertimenolessthanoneweekif(rtc_time-nvram.last_water_time>SEC_IN_WEEK)nvram.last_water_time=rtc_time-SEC_IN_WEEK;//Checksunrisetimeif(rtc_time>nvram.sunrise_time){localtime_r(&nvram.sunrise_time,&sunrise_clk);clk=rtc;clk.tm_hour=sunrise_clk.tm_hour;clk.tm_min=sunrise_clk.tm_min;clk.tm_sec=sunrise_clk.tm_sec;nvram.sunrise_time=mktime(&clk);if(nvram.sunrise_time}if(nvram.water_duration){nvram.water_duration++;water_time=nvram.last_water_time;}else{clk_time=(nvram.last_water_time)?nvram.last_water_time:rtc_time;water_time=NextScheduleTime(clk_time,&water_schedule);}read_nvram=false;}}}//Processonlyonceeveryminuteif(rtc.tm_min!=last_min){//Requesta1-Wiretemperaturemeasurement.Readitlater.error_temp=!SerialCmdNoError(ONEWIRE_TEMPERATURE);if(!error_temp)SerialCmdDone("tt");error_light=!SerialCmdNoError(ONEWIRE_TO_I2C_ROM2";oo0");if(!error_light){SerialCmdDone(I2C_LIGHT);//DonotuseoverdriveSerialCmd("sr");SerialReadInt(&lux);SerialReadUntilDone();}if(SerialCmd(OPTICAL_SENSOR)){SerialReadFloat(&rain);SerialReadUntilDone();}error_temp=!SerialCmdNoError(ONEWIRE_TEMPERATURE);if(!error_temp){SerialCmd("tr");SerialReadFloat(&temp);SerialReadUntilDone();}//Isitsunrise?if(luxif(sunrise_counter>0)sunrise_counter--;elsecheck_sunrise=true;}else{if(sunrise_countersunrise_counter++;if(check_sunrise&&sunrise_counter==MIN_IN_HOUR){nvram.sunrise_time=rtc_time+(SEC_IN_DAY-SEC_IN_HOUR);check_sunrise=false;update_nvram=true;}}}//Isitraining?if(rainfor(i=0;iif(nvram.rain[i]}update_nvram=true;}//Checkscheduleif(menu_select==-1&&!nvram.water_duration){while(water_time+(schedule[water_schedule].duration*SEC_IN_MIN)water_time=NextScheduleTime(water_time,&water_schedule);}if(water_timeStartScheduleTime(water_time,water_schedule);if(tempnvram.water_duration=0;}}//Doweneedtowater?if(nvram.water_duration){WaterScheduleTime();if(!nvram.water_duration)water_time=NextScheduleTime(water_time,&water_schedule);}last_min=rtc.tm_min;update_oled=true;}//Checkbuttonsbutton1=SerialReadButton(BUTTON1);if(button1){if(menu_select==-1)menu_select=0;else{if(++menu_select>=MENU_OPTIONS)menu_select=0;}menu_time=rtc_time;update_oled=true;}if(menu_select>=0){button2=SerialReadButton(BUTTON2);if(button2){clk_time=rtc_time;switch(menu_select){caseMENU_NEXT:caseMENU_RESET:if(nvram.water_duration){nvram.water_duration=1;WaterScheduleTime();}water_time=NextScheduleTime((menu_select==MENU_NEXT)?water_time:rtc_time,&water_schedule);break;caseMENU_WATER:StartScheduleTime(water_time,water_schedule);WaterScheduleTime();break;caseMENU_CLOCK_MIN_PLUS:clk_time+=SEC_IN_MIN;break;caseMENU_CLOCK_MIN_MINUS:clk_time-=SEC_IN_MIN;break;caseMENU_CLOCK_HOUR_PLUS:clk_time+=SEC_IN_HOUR;break;caseMENU_CLOCK_HOUR_MINUS:clk_time-=SEC_IN_HOUR;break;caseMENU_ON_OFF:nvram.state^=STATE_ON_OFF;update_nvram=true;break;}if(clk_time!=rtc_time){if(SerialCmdDone(RTC_SENSOR)){localtime_r(&clk_time,&clk);SerialWriteTime(&clk);rtc_time=clk_time;}}menu_time=rtc_time;update_oled=true;}}if(menu_select>=0&&rtc_time-menu_time>MENU_TIME){menu_select=-1;update_oled=true;}if(update_oled){if(SerialCmdNoError(ONEWIRE_TO_I2C_ROM1)){Serial.print("st10;so1;sc;sf0;sa0;sd0,0,\"");if(nvram.water_duration)Serial.print(nvram.water_duration);else{if((nvram.state&STATE_ON_OFF)==OFF)Serial.print("OFF");elseif(rainelseif(tempelseSerial.print("v1.1");}Serial.print("\";sf2;sa1;sd75,0,\"");if(menu_select==7){//Sunriseclk_time=nvram.sunrise_time;localtime_r(&clk_time,&clk);}elseclk=rtc;Serial.print(clk.tm_hour-((clk.tm_hour>12)?12:0));Serial.print(":");if(clk.tm_minSerial.print(clk.tm_min);Serial.println("\"");SerialReadUntilDone();Serial.print("sf1;sa0;sd79,8,\"");Serial.print((clk.tm_hour>12)?"PM":"AM");Serial.print("\";sf0;sa1;sd127,1,\"");Serial.print(weekday[clk.tm_wday]);Serial.print("\";sd127,13,\"");Serial.print(clk.tm_mon+1);Serial.print("/");Serial.print(clk.tm_mday);Serial.println("\"");SerialReadUntilDone();Serial.print("sf0;sa0;sd1,36,\"");i=schedule[water_schedule].zone;if(ilocaltime_r(&water_time,&clk);if(water_time-rtc_time>SEC_IN_DAY){Serial.print("\";sa1;sd126,36,\"");Serial.print(clk.tm_mon+1);Serial.print("/");Serial.print(clk.tm_mday);Serial.print("");Serial.print(clk.tm_hour-((clk.tm_hour>12)?12:0));Serial.print(":");if(clk.tm_minSerial.print(clk.tm_min);Serial.print("");}else{Serial.print("\";sf1;sa1;sd111,30,\"");Serial.print(clk.tm_hour-((clk.tm_hour>12)?12:0));Serial.print(":");if(clk.tm_minSerial.print(clk.tm_min);Serial.print("\";sf0;sd126,36,\"");}Serial.print((clk.tm_hour>12)?"PM":"AM");if(nvram.water_duration)Serial.print("\";so2;sc0,29,128,19");Serial.println();SerialReadUntilDone();if(menu_select==-1){//Serial.print("\";sa0;sd0,52,\"");//Serial.print(rain);SerialPrint("\";so1;sa2;sd63,52,\"",C2F(temp),error_temp);if(!error_temp)Serial.print("\",248,\""#ifdefFAHRENHEIT"F"#else"C"#endif);Serial.print("/");Serial.print(lux);}else{Serial.print("\";so0;sc0,51,128,14;sf0;sa2;sd63,52,\"");if(menu_select==MENU_ON_OFF){Serial.print((nvram.state&STATE_ON_OFF)?"OFF":"ON");}elseSerial.print(menu[menu_select]);}Serial.println("\";sd");SerialReadUntilDone();update_oled=false;}elseinit_oled=true;}if(update_nvram){if(SerialCmdNoError(I2C_EEPROM)){nvram.crc=crc8((uint8_t*)&nvram,sizeof(nvram)-sizeof(uint8_t));//swSerial.println(nvram.crc,HEX);SerialWriteEEPROM((uint8_t*)&nvram,0,sizeof(nvram));update_nvram=false;}}delay(50);}else{digitalWrite(led,HIGH);delay(500);digitalWrite(led,LOW);delay(500);init_board=true;init_oled=true;}wdt_reset();}注意:如果您使用USB端口对ArduinoNano进行编程,则必须将其与IO扩展器断开,因为它也使用相同的单个串行端口,如果您想调试,则需使用ICSP端口对ATmega328P进行编程。要启用软件调试端口,请取消注释SERIAL_DEBUG定义。必须首先配置分路器以将光学红外传感器数据线与1-Wire远程传感器线隔离。然后在R2处焊接一个0Ω的0603电阻。在PG7和PG11右侧的小外壳上钻一个7/16"的孔,在较大的外壳上钻一个11/16"的孔。使用dremel工具稍微扩大孔,直到压盖贴合。PG7将为远程传感器和PG11供电,用于12VDC、24VAC、歧管线和RJ11远程传感器线。连接SPST瞬时按钮微动开关并将其连接到RJ11螺钉端子。使用热缩管对触点进行绝缘。连接所有电线并将所有零件组装/送入大型外壳。如果用于远程传感器的50英尺RJ11线应刚好穿过PG11密封套,则无需切断它。在光学红外水传感器的小外壳顶部钻一个9/16"孔。使用dremel工具稍微扩大孔直到传感器恰好合适。使RJ11线尽可能短将有助于将其全部塞入较小的外壳中。组装后,建议在拧紧螺母之前在压盖螺母垫圈中添加一些船用胶水,以创造更好的效果。将远程传感器外壳安装在室外房屋的东侧,使光学红外水传感器和光传感器指向天空,途中无障碍物。在大外壳的顶部中间底部钻1/4"孔并安装按钮。使用dremel工具稍微扩大孔,直到按钮适合。测试系统并确保一切正常后还要测试继电器和传感器,请断开Arduino与IO扩展器的连接,并将其直接连接到您的计算机以手动控制它。再次确认一切正常后,使用双面胶带和包装泡沫将所有部件组装到外壳中以固定您的电路板,到此你就可以享受智能灌溉控制器的好处和节省了。如果您对此项目有任何想法、意见或问题,请在下方留言。原文链接丨以上内容来源网络,如涉及侵权可联系删除。