发帖
1 0 0

基于Ai-WB2的10A无线通断器(完结)-定时控制

大猫的鱼
论坛元老

18

主题

380

回帖

6366

积分

论坛元老

积分
6366
电子DIY 13 1 昨天 21:00
[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作为主控还是很有性价比的。

附件:upload 附件:WLRelayV1.1(添加定时功能).rar

──── 0人觉得很赞 ────

使用道具 举报

您需要登录后才可以回帖 立即登录
高级模式
返回
统计信息
  • 会员数: 28811 个
  • 话题数: 41182 篇