[i=s] 本帖最后由 大猫的鱼 于 2025-5-25 21:08 编辑 [/i]
通断器之类的产品中“定时控制”是一个很常用也很实用的功能,所以不添加这个功能的话感觉做这个DIY项目就没有太多意义了。再看着第一帖里提出的几点不足,怎么看怎么难受。忙里偷闲终于是趁活动结束之前把想要的功能都搞完了,这篇帖子就算是这个小项目的完结吧。
1 简述
第一帖:基础功能,完成固定wifi联网、mqtt通讯、实时与延时模式控制
【电子DIY作品】基于Ai-WB2的10A远程通断器
第二贴:添加自动配网功能
基于Ai-WB2的10A无线通断器-自动配网
第三贴(本帖):添加定时控制功能
2 时间获取思路
“定时控制”重要的是一个时间获取。本设计采用的是:
流程: ①设备联网->②NTP服务器获取时间信息->③内部RTC校时->④判断是否到定时时间
3 程序设计
由于Ai-WB2没有真正意义上的RTC外设和BAT引脚,仅仅是SDK中提供了RTC方面的API,所以本质上依旧是定时器。也就没有闹钟终端相关的功能(也可能是我没找到)只能不断的获取RTC时间进行比较。还有就是定时时间和模式之类的参数经常会变化,采用内部flash存储的话终究是不太好的。因此本项目仅仅将配网的wifi信息存入flash中,其他未做保存。当然如果真正要做的话建议外挂时钟芯片+EEPROM。
由于添加的新的模式,因此通讯协议也做了更新
//实时、延时模式设置命令
{
"id":1, //继电器序号
"mode":1, //延时模式 0:实时模式,此时不关注value; 1:延时模式
"value":10 //延时时间 单位s
}
//定时模式设置命令
{
"id":1, //继电器序号
"mode":2, //延时模式 0:实时模式 1:延时模式 2:定时模式
"isOpen":1 //要设置的开关状态 0:ON 1:OFF
"timestamp":1748177499 //定时时间 采用Unix时间戳格式
}
//ON/OFF设置命令格式(仅对实时、延时模式有效)
{
"id":1, //继电器序号
"mode":0, //延时模式 0:实时模式; 1:延时模式
"isOpen":1 //开关状态 0:ON 1:OFF
}
//响应包格式
{
"id":1, //cmd中继电器序号
"mode":0, //延时模式 0:实时模式,此时不关注value; 1:延时模式
"isOpen":1 //当前继电器开关状态 0:ON 1:OFF
}
rtc.c
#include <lwip/tcpip.h>
#include <utils_time.h>
#include <hosal_rtc.h>
#include <sntp.h>
#include <time.h>
#include "rtc.h"
#include "relay.h"
#include "main.h"
hosal_rtc_dev_t rtc;
hosal_rtc_time_t rtcTime;
utils_time_date_t date;
void _startup_sntp(void *arg)
{
printf("--------------------------------------- Start NTP now\r\n");
sntp_setoperatingmode(SNTP_OPMODE_POLL);
sntp_setservername(0, sntp_server);
sntp_init();
printf("--------------------------------------- Start NTP Done\r\n");
}
uint32_t Utc_To_Unix(uint16_t year,uint8_t mon,uint8_t day,uint8_t hour,uint8_t min,uint8_t sec)
{
struct tm time_info;
uint32_t time_stamp = 0;
if(mon > 12 || day > 31 || hour > 23 || min > 59 || hour > 59)
return 0;
time_info.tm_year = year - 1900; // 年份从1900年开始
time_info.tm_mon = mon - 1; // 月份从0开始
time_info.tm_mday = day; // 日
time_info.tm_hour = hour - 8; // 小时
time_info.tm_min = min; // 分钟
time_info.tm_sec = sec; // 秒
time_info.tm_isdst = -1; // 让mktime()自动检测夏令时
time_stamp = (uint32_t)mktime(&time_info);
return time_stamp;
}
void Task_SNTP(void *param)
{
uint32_t seconds = 0, frags = 0;
uint32_t timeStamp = 0;
tcpip_callback(_startup_sntp, NULL);
rtc.port = 0;
rtc.config.format = HOSAL_RTC_FORMAT_DEC;
vTaskDelay(5000 / portTICK_PERIOD_MS);
hosal_rtc_init(&rtc);
sntp_get_time(&seconds, &frags);
utils_time_date_from_epoch(seconds+UTC*60*60, &date);
rtcTime.year = date.ntp_year-2000;
rtcTime.month = date.ntp_month;
rtcTime.date = date.ntp_date;
rtcTime.hr = date.ntp_hour;
rtcTime.min = date.ntp_minute;
rtcTime.sec = date.ntp_second;
hosal_rtc_set_time(&rtc, &rtcTime);
printf("Set Unix:%d\r\n\r\n",Utc_To_Unix(rtcTime.year + 2000,rtcTime.month,rtcTime.date,rtcTime.hr,rtcTime.min,rtcTime.sec));
while (1)
{
if(hosal_rtc_get_time(&rtc, &rtcTime) == 0){
timeStamp = Utc_To_Unix(rtcTime.year + 2000,rtcTime.month,rtcTime.date,rtcTime.hr,rtcTime.min,rtcTime.sec);
for(int i=0;i<8;i++){
if(Relay[i].mode == 2 && timeStamp == Relay[i].timeStamp){
Relay[i].timeStamp = 0;
RelayOne_Set(Relay[i].id,Relay[i].isOpen);
CmdAck(Relay[i].id,Relay[i].mode,bl_gpio_output_get_value(Relay[i].pin));
}
}
// printf("%04u-%02u-%02uT%02u:%02u:%02u\r\n",rtcTime.year + 2000,rtcTime.month,rtcTime.date,rtcTime.hr,rtcTime.min,rtcTime.sec);
// printf("Unix:%d\r\n\r\n",Utc_To_Unix(rtcTime.year + 2000,rtcTime.month,rtcTime.date,rtcTime.hr,rtcTime.min,rtcTime.sec));
}
vTaskDelay(100 / portTICK_PERIOD_MS);
}
}
rtc.h
#ifndef __RTC_H_
#define __RTC_H_
#include <stdint.h>
#include <bl602.h>
#define sntp_server "ntp.aliyun.com"
#define UTC 8
void Task_SNTP(void *param);
#endif
4 项目总结
本次项目主要使用了Ai-WB2的资源或功能有:GPIO、定时器、RTC、http通讯、mqtt通讯、sntp获时 等。实现的功能一句话来说就是:远程对设备进行 实时、延时与定时 三种模式控制。总体上来说选用Ai-WB2-12F作为主控还是很有性价比的。
附件:
附件:WLRelayV1.1(添加定时功能).rar