1200字范文,内容丰富有趣,写作的好帮手!
1200字范文 > 改造一台可以计算滤芯使用寿命的智能空气净化器——嵌入式功能实现篇

改造一台可以计算滤芯使用寿命的智能空气净化器——嵌入式功能实现篇

时间:2024-02-17 22:57:47

相关推荐

改造一台可以计算滤芯使用寿命的智能空气净化器——嵌入式功能实现篇

接上篇改造一台可以计算滤芯使用寿命的智能空气净化器— 给大家介绍智能净化器的硬件改造方案。本篇带大家了解如何实现智能空气净化器的各种净化模式以及滤芯检测和滤芯寿命计算功能。

一. 功能需求

功能简述:智能空气净化器通常有有自动、手动、睡眠三种工作模式,可以通过按键和App切换。其中自动模式可以根据检测环境中有害物质的浓度自动控制风扇转速、UV灯、屏幕灯光等;还可以通过NFC检测滤芯是否安装,并读取滤芯生产信息;同时能够智能计算滤芯寿命。

二. 环境搭建

2.1 开发环境搭建

(1)开发环境搭建可以参考Wi-Fi 模组二次开发教程——1. SoC开发环境搭建。如果已经有虚拟机和乌班图的开发环境可直接跳至4.2 下载编译依赖工具处进行剩余环境搭建。

(2)产品创建可以参考Wi-Fi模组二次开发教程——2. 涂鸦IoT平台介绍。创建产品后,添加产品标准功能DP点和自定义功能DP点。空气净化器DP点如下表。

(3)参考Wi-Fi模组二次开发课程——3. 快速上手来完成代码修改编译、固件上传、获取token、烧录授权和设备配网。

2.2 功能DP点

三. 总体设计

3.1 模块划分

对功能需求进行分析梳理后,可将空气净化器demo程序划分为以下八大模块:

3.2 代码结构

tuya_air_cleaner_demo├── platform /* 涂鸦通用 Tuya IoTOS SDK 的开发编译环境和工具链 */├── sdk /* 存放涂鸦通用 Tuya IoTOS SDK 的头文件和库文件 */└── app /* 存放涂鸦通用 Tuya IoTOS SDK 的 demo */├── src /* 源文件目录 */│ ├── common│ │ ├── tuya_device.c /* 应用层入口 */│ │ ├── tuya_dp_process.c /* DP上下发处理 */│ │ ├── tuya_iot_funtion.c/* 连接IOT云 */│ │ └── tuya_key_funtion.c/* 按键处理 */│ ├── driver│ │ ├── mfrc522│ │ │ ├── tuya_mfrc522_app.c /* NFC芯片mfrc522中间层驱动 */│ │ │ └── tuya_mfrc522.c/* NFC芯片mfrc522驱动 */│ │ ├── tm1650│ │ │ ├── soc_i2c.c /* 软件I2C模拟驱动 */│ │ │ ├── tm1650_app.c /* 液晶显示屏芯片tm1650中间层驱动 */│ │ │ └── tm1650.c /* 液晶显示屏芯片tm1650驱动 */│ │ ├── tuya_buz_driver.c /* 蜂鸣器驱动 */│ │ ├── tuya_hardware_driver.c /* 硬件GPIO驱动 */│ │ ├── tuya_lcd_display.c/* 液晶屏应用层驱动 */│ │ └── tuya_motor_driver.c/* 风扇电机驱动 */│ └── function│ ├── tuya_air_quality_funtion.c /* 空气质量获取和显示功能 */│ ├── tuya_automatic_mode_funtion.c/* 自动模式相关功能 */│ ├── tuya_countdown_funtion.c/* 倒计时功能 */│ ├── tuya_filter_funtion.c /* 滤芯寿命相关功能 */│ ├── tuya_mode_funtion.c/* 模式切换相关功能 */│ ├── tuya_nfc_funtion.c/* 滤芯NFC检测相关功能 */│ └── tuya_timer_funtion.c /* Timer相关功能 */└── include├── common│ ├── tuya_device.h│ ├── tuya_dp_process.h│ ├── tuya_iot_funtion.h│ └── tuya_key_funtion.h├── driver│ ├── mfrc522│ │ ├── tuya_mfrc522_app.h│ │ └── tuya_mfrc522.h│ ├── tm1650│ │ ├── soc_i2c.h│ │ ├── tm1650_app.h│ │ └── tm1650.h│ ├── tuya_buz_driver.h│ ├── tuya_hardware_driver.h│ ├── tuya_lcd_display.h│ └── tuya_motor_driver.h└── function├── tuya_air_quality_funtion.h├── tuya_automatic_mode_funtion.h├── tuya_countdown_funtion.h├── tuya_filter_funtion.h├── tuya_mode_funtion.h├── tuya_nfc_funtion.h└── tuya_timer_funtion.h

3.3 应用框架

下图所示为基于 Tuya Wi-Fi SDK 的应用框架:

Platform:所使用的芯片平台,芯片 + 协议栈由芯片公司维护。

Port:Tuya Wi-Fi SDK 所需要的抽象接口,需要用户根据具体的芯片平台移植实现。

Tuya Wi-Fi SDK : 封装了涂鸦 Wi-Fi 通信协议,提供构建涂鸦 Wi-Fi 应用所需的服务接口。

Application:基于Tuya Wi-Fi SDK 构建的应用。

Tuya SDK API:API用于设备实现Wi-Fi相关的管理、通信等,API的调用将采用基于消息的异步机制,API的执行结果将会以 Message 或者 Call back 的方式通知给设备的 Application。

SDK Config:Tuya Wi-Fi SDK 可裁剪可配置,通过配置文件中的宏定义可将 Tuya Wi-Fi SDK 设置成不同模式,例如配置成适用于多协议设备的通用配网模式、单模配网模式、是否使用 OS 等。

Main Process:为 Tuya SDK API 的主引擎,Application 需要一直调用,如果 Platform 架构是带OS的,Tuya Wi-Fi SDK 会基于 Port 层提供的OS相关接口自动创建一个任务用于执行Main Process,如果是非OS平台,需要设备 Application 循环调用。

Message or Call back:SDK 通过 Message 或者设备 Application注册的 Call back 函数向设备 Application 发送数据(状态、数据等)。

3.4 驱动软件模块

3.5 方案流程图

(1)模式选择功能流程图:

(2)按键功能流程图

(3)滤芯检测流程图

4. 功能实现

4.1 外设驱动

4.1.1 段码液晶屏

段码液晶屏由 3 * 8 断码屏和 5 个指示灯构成,分别对应PM2.5,PM10,TVOC,温度,湿度。

其中外挂驱动芯片 TM1650,I2C 通信,本文demo中使用 2 * GPIO 模拟 I2C 。

段码液晶屏部分代码:

/*** @brief: tuya_lcd_show_num* @desc: show num on lcd* @param[in] number:-99<number<999* @return OPERATE_RET OPRT_OK is sucess, other is fail*/OPERATE_RET tuya_lcd_show_num(IN INT_T number){OPERATE_RET op_ret = OPRT_OK;MINUS_FLAG_E minus_flag = MINUS_NULL;UCHAR_T i = 0;UCHAR_T bit[3];if (number > MAX_NUM) {number = MAX_NUM;}if (number < MIN_NUM) {number = MIN_NUM;}if (number < 0) {if (number > -10) {//-10<number<0minus_flag = MINUS_TEN;} else {//-100<number<-10minus_flag = MINUS_HUNDRED;}number = number * (-1);}bit[0] = number / 100 % 10; //hundredbit[1] = number / 10 % 10; //tenbit[2] = number % 10; //one/* hundred == 0 */if (bit[0] == 0) {if (minus_flag == MINUS_HUNDRED) {bit[0] = SEG_SHOW_MINUS; //hundred bit show minus} else {bit[0] = SEG_SHOW_NULL; //hundred bit show null}/* ten == 0 */if (bit[1] == 0) {if (minus_flag == MINUS_TEN) {bit[1] = SEG_SHOW_MINUS; //ten bit show minus} else {bit[1] = SEG_SHOW_NULL; //ten bit show null}}}/* i2c send command and data */for (i = 0; i < 3; i++) {op_ret = tuya_tm1650_app_write(dig[i], seg_num[bit[i]]); if (op_ret != OPRT_OK) {PR_ERR("tuya_tm1650_app_write error:%d", op_ret);return op_ret;}}return op_ret;}/*** @brief: tuya_led_show* @desc: Choose the led that led show* @param[in] show_led: 0,1,2,3,4,5* @return OPERATE_RET OPRT_OK is sucess, other is fail*/OPERATE_RET tuya_led_show(IN CONST UCHAR_T show_led){OPERATE_RET op_ret = OPRT_OK;//Check the input parameter, show_led: 0~5if (show_led > 5) {PR_ERR("show_led input parameter error!");return OPRT_INVALID_PARM;}/* i2c send command and data */op_ret = tuya_tm1650_app_write(dig[3], seg_led[show_led]); if (op_ret != OPRT_OK) {PR_ERR("tuya_tm1650_app_write error:%d", op_ret);return op_ret;}return op_ret;}

4.1.2 风扇电机

采用空气净化器专用的直流无刷电机,模块主要引脚如下表。

电源和I/O引脚输入步骤:

开机:5V on > 24V on > CLK

关机:BRK输入Hi > CLK信号输入Low > 24V off > 5V off

风扇电机驱动部分代码

/*** @brief: _tuya_motor_start* @desc: start motor to control fan speed* @param[in] percent:set fan speed percent, 0.2~1* @return OPERATE_RET OPRT_OK is sucess, other is fail*/STATIC OPERATE_RET _tuya_motor_start(IN CONST FLOAT_T percent){OPERATE_RET op_ret = OPRT_OK;FLOAT_T speed_percent = 0;speed_percent = percent;//Check the input parameter, percent: 0.2~1if (speed_percent < 0.2) {speed_percent = 0.2;}if (speed_percent > 1) {speed_percent = 1;}/* Break pin off */tuya_gpio_write(MOROR_BRK_PIN, TRUE);/* Start motor pwm */op_ret = tuya_motor_pwm_start(430 * speed_percent); //430hz is max frequencyif (op_ret != OPRT_OK) {PR_ERR("tuya_motor_pwm_start error:%d", op_ret);return op_ret;}return op_ret;}/*** @brief: tuya_motor_stop* @desc: stop motor* * @return OPERATE_RET OPRT_OK is sucess, other is fail*/OPERATE_RET tuya_motor_stop(VOID_T){OPERATE_RET op_ret = OPRT_OK;/* Break pin on */tuya_gpio_write(MOROR_BRK_PIN, FALSE);/* stop motor pwm */op_ret = tuya_pwm_stop(p_pwm_motor);if (op_ret != OPRT_OK) {PR_ERR("stop motor pwm error:%d", op_ret);return op_ret;}/* set g_fan_speed_percent value*/g_fan_speed_percent = 0;PR_DEBUG("ali, tuya_motor_stop suc");return op_ret;}

4.2 应用功能

4.2.1 空气指标获取

向空气质量传感器发送命令,然后读取UART数据缓存,解析得到空气质量指标。

空气指标获取部分代码:

CONST UCHAR_T uart_buf_tx[4] = {0x11, 0x01, 0x16, 0xD8};/*** @brief: tuya_get_air_quality_index* @desc: get air quality index* * @return OPERATE_RET OPRT_OK is sucess, other is fail*/STATIC OPERATE_RET tuya_get_air_quality_index(VOID_T){OPERATE_RET op_ret = OPRT_OK;UINT_T tmp_len = 0, read_len = 0, read_time = 0;UCHAR_T uart_buf_rx[UART_BUFSZ];UINT_T cs_check_num = 0;/* write command 11 01 16 D8 */tuya_uart_write(p_uart0, uart_buf_tx, sizeof(uart_buf_tx));/* read the return data */do {tmp_len = tuya_uart_read(p_uart0, &uart_buf_rx[read_len], UART_BUFSZ - read_len);read_len += tmp_len;if (read_time++ > 20) {PR_ERR("uart no return data");return OPRT_COM_ERROR;}tuya_hal_system_sleep(10);} while (read_len < UART_BUFSZ);/* check frame header */if ((uart_buf_rx[0] != 0x16) || (uart_buf_rx[1] != 0x13) || (uart_buf_rx[2] != 0x16)) {PR_ERR("uart receive data error, frame header");return OPRT_COM_ERROR;}/* check cs check num */cs_check_num = 256 - tuya_get_check_sum(uart_buf_rx, UART_BUFSZ-1);if (uart_buf_rx[UART_BUFSZ-1] != cs_check_num) {PR_ERR("uart receive data error, cs check num");return OPRT_COM_ERROR;}/* set air quality index value */g_air_quality_index.pm25 = uart_buf_rx[9]*256 + uart_buf_rx[10];g_air_quality_index.pm10 = uart_buf_rx[11]*256 + uart_buf_rx[12];g_air_quality_index.tvoc = (uart_buf_rx[3]*256 + uart_buf_rx[4]); //ppb,alitestg_air_quality_index.temperature = (uart_buf_rx[13]*256 + uart_buf_rx[14] - 500)/10;g_air_quality_index.humidity = (uart_buf_rx[15]*256 + uart_buf_rx[16])/10;return op_ret;}

4.2.2 风扇自动调节

风扇自动调节规则:

滤芯寿命降低导致净化效果衰减,通过风速提升进行补偿:

80-100%, 按上述规则

50-80%, 风速提升10%

20-50%,风速提升20%

0-20%,风速提升30%

风扇自动调节部分代码:

/*** @brief: tuya_auto_fan_speed_start* @desc: start auto fan speed* @param[in] start:* TRUE: start* FLASE: stop* @return OPERATE_RET OPRT_OK is sucess, other is fail*/OPERATE_RET tuya_auto_fan_speed_start(IN CONST BOOL_T start){OPERATE_RET op_ret = OPRT_OK;if (FALSE == start) {tuya_pm25_scan_timer_stop();PR_DEBUG("stop auto fan speed");/* release flag */compare_flag.pm25_75_115 = FALSE;compare_flag.pm25_35_75 = FALSE;compare_flag.pm25_35_75_again = FALSE;motor_already_stop = FALSE;return op_ret;}/* release time */g_pm25_good_time = 0;/* scan pm2.5 value once */PR_DEBUG("start auto fan speed");tuya_pm25_scan();/* cycle scan pm2.5, 30s */tuya_pm25_scan_timer_start();return op_ret;}/*** @brief: tuya_pm25_scan* @desc: scan pm2.5 value once* * @return OPERATE_RET OPRT_OK is sucess, other is fail*/OPERATE_RET tuya_pm25_scan(VOID_T){OPERATE_RET op_ret = OPRT_OK;PM25_VALUE_RANGE_E pm25_value_range;FLOAT_T speed_percent = 0;UINT_T pm25_new = 0;pm25_new = g_air_quality_index.pm25;g_pm25_reduction = g_pm25_last - pm25_new;g_pm25_last = pm25_new;/* Check whether to into the dark sleep mode */if (TRUE == stop_auto_speed_flag) {return op_ret;}/* Check whether to into the environmental mode */if (pm25_new < 35) {//hold for 2 hours, 240*30 sif (g_pm25_good_time++ >= 240) {if (g_pm25_good_time > 1000) {g_pm25_good_time = 1000;}if (FALSE == motor_already_stop) {tuya_motor_stop();motor_already_stop = TRUE;}return op_ret;}} else {g_pm25_good_time = 0;motor_already_stop = FALSE;}/* Check pm2.5 value range */if (pm25_new >= 115) {pm25_value_range = PM25_RANGE_115;} else if (pm25_new >= 75) {pm25_value_range = PM25_RANGE_75_115;} else if (pm25_new >= 35) {pm25_value_range = PM25_RANGE_35_75;} else {pm25_value_range = PM25_RANGE_35;}/* control fan speed */switch (pm25_value_range){/* pm2.5: 115+ */case PM25_RANGE_115:speed_percent = 1;break;/* pm2.5: 75-115 */case PM25_RANGE_75_115:if (TRUE == compare_flag.pm25_35_75_again) {speed_percent = 1;} else {speed_percent = 0.8;}if (TRUE == compare_flag.pm25_75_115) {speed_percent = tuya_pm25_compare_75_115();} else {compare_flag.pm25_75_115 = TRUE;}break;/* pm2.5: 35-75 */case PM25_RANGE_35_75:compare_flag.pm25_75_115 = FALSE;speed_percent = 0.6;if (TRUE == compare_flag.pm25_35_75) {speed_percent = tuya_pm25_compare_35_75();compare_flag.pm25_35_75 = FALSE;} else if ((TRUE == compare_flag.pm25_35_75_again)) {speed_percent = tuya_pm25_compare_35_75_again();} else {compare_flag.pm25_35_75 = TRUE;}break;/* pm2.5: 0-35 */case PM25_RANGE_35:compare_flag.pm25_75_115 = FALSE;compare_flag.pm25_35_75_again = FALSE;speed_percent = 0.4;break; default:break;}/* start fan motor */op_ret = tuya_motor_start(speed_percent);if (OPRT_OK != op_ret) {PR_ERR("tuya_motor_start error:%d", op_ret);return op_ret;} return op_ret;}

4.2.3 滤芯NFC检测

NFC读卡器芯片为 MFRC522,滤芯上的NFC卡片类型为 NXP MIFARE Ultralight,内存 180 bytes,45 页(4 bytes 每页)。

NFC读卡器的步骤:寻卡>防冲撞>选卡>校验密码>读写卡片。Mifare Ultralight 类型卡片没有密码认证(Mifare One 类型卡片支持密码认证),所以使用 Mifare Ultralight 类型卡片的话就可以跳过校验密码步骤。

滤芯NFC卡片信息数据协议定义如下表:

滤芯NFC检测部分代码:

/*** @brief: tuya_nfc_detect_filter* @desc: nfc detect to read filter message* * @return OPERATE_RET OPRT_OK is sucess, other is fail*/STATIC OPERATE_RET tuya_nfc_detect_filter(VOID_T){OPERATE_RET op_ret = OPRT_OK;UCHAR_T i = 0;UCHAR_T page = 0;UCHAR_T read_buf[16] = {0};UCHAR_T TagType[2];UCHAR_T SelectedSnr[4];/* mfrc522 reset, and open antenna */PcdReset();PcdAntennaOff(); PcdAntennaOn(); /* look for card */op_ret = PcdRequest(0x52, TagType);if (OPRT_OK != op_ret) {PR_INFO("PcdRequest err:%d", op_ret);PR_INFO("Do not find NFC Card, filter do not install");return op_ret;}/* printf the type of card */PR_DEBUG_RAW("TagType: 0x");for (i = 0; i < 2; i++) {PR_DEBUG_RAW("%02X", TagType[i]);}PR_DEBUG_RAW("\n");/* card collision protection */op_ret = PcdAnticoll(SelectedSnr);if (OPRT_OK != op_ret) {PR_INFO("PcdAnticoll err:%d", op_ret);PR_INFO("Do not find NFC Card, filter do not install");return op_ret;}/* select card */op_ret = PcdSelect(SelectedSnr);if (OPRT_OK != op_ret) {PR_INFO("PcdSelect err:%d", op_ret);PR_INFO("Do not find NFC Card, filter do not install");return op_ret;}/* read card */PR_DEBUG("Find NFC Card, the filter is install ok");PR_DEBUG_RAW("Read NFC Card data:\n");for (page = 0; page < 45; page +=4) {//readop_ret = PcdRead(page, read_buf);if (OPRT_OK != op_ret) {PR_ERR("PcdRead err:%d, page:%d~%d", op_ret, page, (page + 3));}//get filter messageif (CARD_READ_PAGE_ADDR == page) {memset(filter_buf, 0x00, CARD_READ_BYTE_LEN);for (i = 0; i < CARD_READ_BYTE_LEN; i++) {filter_buf[i] = *(read_buf + i);}}//printf read bufPR_DEBUG_RAW(" ");for (i = 0; i < 16; i++) {PR_DEBUG_RAW("%02X ", read_buf[i]);}PR_DEBUG_RAW("----- page: %d~%d\n", page, (page + 3));}PR_DEBUG_RAW("\n");op_ret = tuya_analyze_CardData_to_get_filter_msg();if (OPRT_OK != op_ret) {return op_ret;}return op_ret;}/*** @brief: tuya_analyze_CardData_to_get_filter_msg* @desc: analyze CardData to get filter msg* * @return OPERATE_RET OPRT_OK is sucess, other is fail*/STATIC OPERATE_RET tuya_analyze_CardData_to_get_filter_msg(VOID_T){OPERATE_RET op_ret = OPRT_OK;UCHAR_T i = 0;/* check filter_buf */if (NULL == filter_buf) {PR_ERR("filter_buf is error");return OPRT_INVALID_PARM;}/* printf filter buf */PR_DEBUG_RAW("filter buf data: ");for (i = 0; i < CARD_READ_BYTE_LEN; i++) {PR_DEBUG_RAW("%02X ", filter_buf[i]);}PR_DEBUG_RAW("\n");/* check if filter is piratic */if (CARD_READ_HEAD_TAG != filter_buf[0]) {PR_INFO("Do not have tuya tag, filter is piratic");return OPRT_COM_ERROR;}/* get filter type */switch (filter_buf[1]) {case FILTER_STANDARD:g_filter_card_msg.type = FILTER_STANDARD;PR_DEBUG_RAW("filter type: standard\n");break;case FILTER_ANTIBACTERIAL:g_filter_card_msg.type = FILTER_ANTIBACTERIAL;PR_DEBUG_RAW("filter type: antibacterial\n");break;case FILTER_ALDEHYDE_REMOVAL:g_filter_card_msg.type = FILTER_ALDEHYDE_REMOVAL;PR_DEBUG_RAW("filter type: aldehyde removal\n");break;case FILTER_PROFESSIONAL:g_filter_card_msg.type = FILTER_PROFESSIONAL;PR_DEBUG_RAW("filter type: professional\n");break;default:PR_INFO("filter type buf data is erro, maybe filter is piratic");return OPRT_COM_ERROR;break;}/* get filter ID */g_filter_card_msg.ID = filter_buf[2] * 256 + filter_buf[3];PR_DEBUG_RAW("filter ID: %d\n", g_filter_card_msg.ID);/* get filter product date */g_filter_card_msg.product_date.year = filter_buf[4] + 2000;g_filter_card_msg.product_date.month = filter_buf[5];g_filter_card_msg.product_date.day = filter_buf[6];PR_DEBUG_RAW("filter product date: %d-%d-%d\n", filter_buf[4]+2000, filter_buf[5], filter_buf[6]);/* DP report */tuya_update_single_dp(FILTER_TYPE_DPID, PROP_ENUM, g_filter_card_msg.type);/* check whether the filter is new */tuya_check_whether_the_filter_is_new();return op_ret;}

4.2.4 滤芯寿命计算

(1)滤芯剩余寿命算法:

说明:

a、根据公式,只要知道当前滤芯粉尘的吸附量和pm2.5颗粒浓度,就可以算出当前粉尘吸附量;

b、每1分钟计算一次粉尘吸附量并累加;

c、当空气净化器收到关机命令时或者每过24h,系统会将此前累加的粉尘吸附量存入flash,下次开机可以继续累加;

d、滤芯寿命根据每周粉尘累加的吸附量上报一次。

**注:**若设备发生断电情况,可能会产生0~1天的误差。

(2)滤芯剩余可用天数算法:

粉尘吸附量累加一周后,就可以得到粉尘吸附的速度,根据粉尘吸附的速度和滤芯剩余的寿命,就可以估算出滤芯剩余可用天数。

滤芯寿命计算部分代码:

/*** @brief: tuya_filter_1minute_task* @desc: filter 1minute task* * @return OPERATE_RET OPRT_OK is sucess, other is fail*/STATIC VOID_T tuya_filter_1minute_task(VOID_T){STATIC UINT_T uv_close_time = 240;STATIC UINT_T s_tick;while(1) {UINT_T fan_speed_percent = 0;/* check whether air cleaner power on */if (POWER_ON == tuya_get_power_status()) {//get current fan_speedfan_speed_percent = tuya_get_fan_speed_percent();//figure pm_totalg_filter_pm_total = g_filter_pm_total + (FLOAT_T)fan_speed_percent/100 * FILTER_FIGURE_CONST;g_filter_msg.pm_total = g_filter_msg.pm_total + (FLOAT_T)fan_speed_percent/100 * FILTER_FIGURE_CONST;//DP report, pm_totaltuya_update_single_dp(PM_TOTAL_DPID, PROP_VALUE, g_filter_msg.pm_total/1000); //ug -> mg//DP report, runtime_totaltuya_update_single_dp(RUNTIME_TOTAL_DPID, PROP_VALUE, ++g_runtime_total); //runtime_total add}/* enter every 60 minutes, 1hour */if (s_tick++ >= 60){s_tick = 0;tuya_filter_1hour_task();}/* if uv close time more than 240min, scan for uv funtion */if (FALSE == tuya_get_uv_status) {if (uv_close_time++ >= 240) {tuya_uv_funtion_scan();if (uv_close_time > 1000) {uv_close_time = 1000;}}} else {uv_close_time = 0; }tuya_hal_system_sleep(FILTER_TASK_DELAY_TIME); //1min }}/*** @brief: tuya_filter_1hour_task* @desc: filter 1hour task* * @return OPERATE_RET OPRT_OK is sucess, other is fail*/STATIC VOID_T tuya_filter_1hour_task(VOID_T){POSIX_TM_S local_time;UINT_T now_days = 0;uni_local_time_get(&local_time);now_days = local_time.tm_year*365 + local_time.tm_mon*30 + local_time.tm_mday;if (g_now_days == 0) {g_now_days = now_days;}/* if days pass */if (g_now_days < now_days) {/* figure filter_use_days */g_filter_use_days = g_filter_use_days + (now_days - g_now_days);/* figure air cleaner run_days */g_run_days = g_run_days + (now_days - g_now_days);/* if air cleaner run_days more than 7 days */if (g_run_days >= 7) {//figure filter_lifeg_filter_msg.filter_life = (1 - (FLOAT_T)g_filter_pm_total / FILTER_MAX_PM_CAN_ABSORB) * 100;//figure filter_daysif (g_filter_pm_total == 0) {g_filter_msg.filter_days = 180;} else {g_filter_msg.filter_days = ((FILTER_MAX_PM_CAN_ABSORB * g_filter_use_days) / g_filter_pm_total) - g_filter_use_days;}//DP reportif (g_filter_msg.filter_days > 1000) {g_filter_msg.filter_days = 1000;}tuya_update_single_dp(FILTER_DAYS_DPID, PROP_VALUE, g_filter_msg.filter_days); //filter_daystuya_update_single_dp(FILTER_LIFE_DPID, PROP_VALUE, g_filter_msg.filter_life); //filter_lifeg_run_days = 0;}g_now_days = now_days;/* write save data in flash */tuya_write_save_data_in_flash();}}

以上就是本次智能空气净化器完整的改造方案,此次改造的重点开发工作在滤芯寿命计算上,除了可以预估滤芯使用时间,提醒更换滤芯,还能根据滤芯的使用情况来判断各档位的净化能力,完成有效净化。感兴趣的可以一起动手试试,有任何疑问也可以留言交流。

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。