esp8266做到现在,该应用一下了,就做了个定时浇花的。
原理上不外乎该系列前面的文章,多加了一个闹铃设置程序。并且在tcp server和MQTT配置里加上了设置方式。
硬件上除了自己打板的esp8266-01继电器控制板,另外需要一个小板子用来插接控制板和水泵,水泵的两极需要电容和续流二极管,否则继电器工作会受影响。供电部分因为是四套控制装置,总电流峰值会达到近4A,所以用了个5V6A的电源。
总的来说,硬件上集合了浪涌防护,反接保护,短路保护,继电器续流保护,手动复位按键,复位电容泄放二极管,多IO口引出,多取电接口,软件上有flash参数读写保护,参数序列化掉电恢复,内存允许范围内可定义多组闹铃(一个闹铃占12字节空间,上百组没问题),ntp时间同步,自动域名解析,web配置,tcp server配置服务,tcp client状态上报,MQTT客户端状态发布和控制命令订阅等等。这里只重点说下闹铃功能编码。
闹铃设置支持MQTT推送设置,支持TCP server命令控制,可以按时、分、秒、日、星期重复。闹铃结构体,包含成员:ID,重复模式,开始时间,结束时间,重复间隔(在某些重复模式下有效):
1 2 3 4 5 6 7 |
typedef struct STAlarm{ uint8 ID; EPepeatMode RptMode; uint32 Start; uint32 Stop; uint32 RptIntvl; //<0 error, =0 for no repeat, >0 for seconds wait to realarm }STAlarm; |
用一个重复的系统定时任务进行闹铃响应检测,在定时任务回调函数里进行闹铃判断、ntp同步等,该定时任务可以根据所需要的定时精度进行宏设定,比如要实现秒级的闹铃,可将定时任务的间隔设置小于1000,但是不能太小,否则系统频繁触发定时任务,而且注意该定时任务并不精确,因而不能指望闹铃的时间准确,包括ntp时间同步也不精确,只是期望获得日期信息。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 |
void ICACHE_FLASH_ATTR AlarmTimerCB(){ LOCAL uint32 sntpQueryCtn = 0; if(sntpQueryCtn == 0 || timeStamp==0){ uint32 timeStampTmp; timeStampTmp = sntp_get_current_timestamp(); if(timeStampTmp !=0){ timeStamp = timeStampTmp; //9-10 0:0:0 -- 17784 days= 1,536,451,200s TRACE("sntp time stamp:%d,%s\n",timeStamp,sntp_get_real_time(timeStamp)); }else if(timeStamp> SNTP_QUERY_INTVL * 2){ timeStamp += ALARM_CHK_INTVL/1000; } }else if(timeStamp> SNTP_QUERY_INTVL * 2){ timeStamp += ALARM_CHK_INTVL/1000; } os_printf("time stamp:%d,%s\r\n",timeStamp,sntp_get_real_time(timeStamp)); if(timeStamp>0 && bAlarmEnable){ bool bRun = false; int i=0; for(i=0;i<MAX_ALARM_NUM;i++){ TRACE("alarm id:%d:%d:%d:%d:%d\r\n",stFlashProtParam.AlarmQueue[i].ID, stFlashProtParam.AlarmQueue[i].RptMode, stFlashProtParam.AlarmQueue[i].Start, stFlashProtParam.AlarmQueue[i].Stop, stFlashProtParam.AlarmQueue[i].RptIntvl); if(stFlashProtParam.AlarmQueue[i].RptMode == RPT_ONLY_ONCE ){ if(timeStamp >= stFlashProtParam.AlarmQueue[i].Start && timeStamp < stFlashProtParam.AlarmQueue[i].Stop){ bRun = true; }else if(timeStamp >= stFlashProtParam.AlarmQueue[i].Stop && timeStamp <= stFlashProtParam.AlarmQueue[i].Stop + ALARM_EXPIRE){ stFlashProtParam.AlarmQueue[i].RptMode = 0-RPT_ONLY_ONCE; SaveFlashProtParam(); } }else if(stFlashProtParam.AlarmQueue[i].RptMode > 0 && stFlashProtParam.AlarmQueue[i].RptMode <= DAYS_OF_WEEK){ if(timeStamp >= stFlashProtParam.AlarmQueue[i].Start && timeStamp < stFlashProtParam.AlarmQueue[i].Stop){ bRun = true; }else if(timeStamp >= stFlashProtParam.AlarmQueue[i].Stop){// && timeStamp <= stFlashProtParam.AlarmQueue[i].Stop + ALARM_EXPIRE){ switch(stFlashProtParam.AlarmQueue[i].RptMode){ case EVERY_HOUR: stFlashProtParam.AlarmQueue[i].Start += 3600; stFlashProtParam.AlarmQueue[i].Stop += 3600; break; case EVERY_DAY: stFlashProtParam.AlarmQueue[i].Start += 86400; stFlashProtParam.AlarmQueue[i].Stop += 86400; break; case EVERY_WEEK: stFlashProtParam.AlarmQueue[i].Start += 86400*7; stFlashProtParam.AlarmQueue[i].Stop += 86400*7; break; case EVERY_MONTH: break; case EVERY_YEAR: break; case INTVL_SECS: stFlashProtParam.AlarmQueue[i].Start += stFlashProtParam.AlarmQueue[i].RptIntvl; stFlashProtParam.AlarmQueue[i].Stop += stFlashProtParam.AlarmQueue[i].RptIntvl; break; case INTVL_MINS: stFlashProtParam.AlarmQueue[i].Start += stFlashProtParam.AlarmQueue[i].RptIntvl * 60; stFlashProtParam.AlarmQueue[i].Stop += stFlashProtParam.AlarmQueue[i].RptIntvl * 60; break; case INTVL_HOURS: stFlashProtParam.AlarmQueue[i].Start += stFlashProtParam.AlarmQueue[i].RptIntvl * 3600; stFlashProtParam.AlarmQueue[i].Stop += stFlashProtParam.AlarmQueue[i].RptIntvl * 3600; break; case INTVL_DAYS: stFlashProtParam.AlarmQueue[i].Start += stFlashProtParam.AlarmQueue[i].RptIntvl * 86400; stFlashProtParam.AlarmQueue[i].Stop += stFlashProtParam.AlarmQueue[i].RptIntvl * 86400; break; case DAYS_OF_WEEK: break; default: break; } SaveFlashProtParam(); } } } if(bRun){ RelayOn(); }else{ RelayOff(); } } sntpQueryCtn++; sntpQueryCtn %= SNTP_QUERY_INTVL; |
下面放图
原博客: