资讯详情

智能除味器——嵌入式开发

一、产品创造

1、功能需求

APP端功能 描述
模式选择 保鲜除臭模式
除味时间 设备除臭工作时间可定义
调整除臭档位 支持强、中、弱三档
低电报警 低电量报告,APP端报警
设备端功能 描述
配网模式 长按按键5s,设备进入配网状态,指示灯闪烁
调整除臭档位 短按键,强、中、弱三档循环切换
复位按键 短按复位按钮,程序复位

2、环境搭建

(1)产品创造

这次智能除臭器使用了温湿度传感器的面板。因此,在创建产品时,选择传感类别下的温湿度传感器和蓝牙进行通信。

默认选择所有功能点(随机删除可能导致面板数据丢失或无法打开面板)。面板选择温度和湿度Studio面板,在硬件开发中,选择相应的模块,最后获取激活码进行后续开发。

(2)获取sdk

  • 原厂(Nordic nRF52832) SDK获取:https://www.nordicsemi.com/Products/Development-software/nrf5-sdk/download#infotabs智能除臭器项目开发使用SDK版本是15.3.0

下载nRF52832 SDK后,找到相应DeviceDownload.zip解压文件,然后进入DeviceDownload文件夹后再次解压nRF5SDK153059ac345。

  • Tuya sdk获取

在环境建设中,硬件开发步骤选择相应的模块(这次是TYBN1)之后,下载模块对应的sdk数据解压后打开 tuya-ble-sdk-demo-project-nrf52832-V2.1.0 与文件夹同名的文件夹现在文件夹中。

将文件夹复制到原厂sdk的DeviceDownload\nRF5SDK153059ac345\nRF5_SDK_15.3.0_59ac345\examples\ble_peripheral文件夹下。 安装ARM CMSIS4.5.0.下载安装完成后,打开 tuya-ble-sdk-demo-project-nrf52832-V2.1.0\pca10040\s132\arm5_no_packs 文件夹下的keil工程。

(3)下载芯片对应的安装包

  1. 第一次打开工程会自动下载 nRF52832 芯片对应的安装包。
  2. (可选)安装包下载后,如果第一次开发,会显示以下错误信息,可以忽略错误,继续完成安装。
Cannot execute external request (Install Pack, "NordicSemiconductor:nRF_DeviceFamilyPack"): Pack not found Cannot execute external request (Install Pack, "NordicSemiconductor:nRF_DeviceFamilyPack:8.24.1"): Pack not found 

如下图所示:

安装完成后重启keil即可编译。

注:编译过程中可能会出现报错: RTE\Device\nRF52832_xxAA\system_nrf52.c(30): error: #5: cannot open source input file “nrf52_erratas.h”: No such file or directory 是因为keil版本问题。

只需用 DeviceDownload\nRF5SDK153059ac345\nRF5_SDK_15.3.0_59ac345\modules\nrfx\mdk 文件夹下的system_nrf52.c 替换掉 DeviceDownload\nRF5SDK153059ac345\nRF5_SDK_15.3.0_59ac345\examples\ble_peripheral\tuya-ble-sdk-demo-project-nrf52832-V2.1.0\pca10040\s132\arm5_no_packs\RTE\Device\nRF52832_xxAA 文件夹下的system_nrf52.c然后关闭文件keil工程,再重新打开该工程即可编译通过。

(4)修改PID、UUID、Auth_key、MAC地址

打开tuya_ble_sdk_demo文件夹找到tuya_ble_sdk_demo.h将自己在IoT在平台获得的授权代码清单中UUID、Auth_key、MAC创造产品PID填写下图所示的位置。

tuya_ble_sdk_demo.c文件中将 1.DEVICE_ID_LEN(16),否则将进一步修改uuid、auth_key等不会生效。

3、设备连线

成功编译后J-Link 烧录器连接到开发板,连接如下:

模块对应引脚 串口对应引脚
VCC VCC(3.3V)
模块对应引脚 JLINK对应引脚
SWDIO SWDIO
SWC SWCLK
GND GND

4、日志查看

查看使用日志 J-Link RTT Viewer 软件。下载后,在开始菜单中搜索 J-Flash Vx.xxb(x.xx 并打开版本号,点击 File->New Project 芯片选择 nRF52832_xxAA 点击OK。

点击 File->Open data file 选中 tuya-ble-sdk-demo-project-nrf52832-V2.1.0\pca10040\s132\arm5_no_packs\hex\material文件夹下的 s132_nrf52_6.1.1_softdevice.hex 文件

点击 Target->Connect 连接成功后点击 Target->Production Programming 开始下载协议栈固件。下面的日志口下载成功后会有Data file opened successfully 字样。最后点击 Target->Disconnect 断开连接。

log默认情况下,通过修改宏使能日志,操作步骤如下:

(1)找到 tya-ble-sdk-demo-project-nrf52832-V2.1.0\tuya_ble_sdk_demo\board\nRF52832\tuya_ble_port 文件夹下的 custom_tuya_ble_config.h 文件。将第113行 日志输出使能。 ​ (2)找到 ble_peripheral\tuya-ble-sdk-demo-project-nrf52832-V2.1.0\tuya_ble_sdk_demo\board 文件夹下的board.h 文件。将第38行 日志输出使能。 ​ (3)修改、编译完成后将hex文件烧录到模组。日志查看方法如下:

打开 J-link RTT Viewer Vx.xxb 后自动弹出以下对话框:

选择USB,在Specify Target Device中点击出现下面的弹窗,在红框内输入nRF52832_xxAA回车后双击选定。最后依次选择上图红框选项点击OK完成设置。

当界面内出现以下内容说明连接成功,可以正常查看日志。

5、修改测试宏

打开工程目录 tuya_ble_sdk_demo 下的 tuya_ble_sdk_test.h 文件,将第29行宏定义 关闭,该宏为测试模式的开关,打开会导致测试功能模块占用相关IO口资源使部分IO口以及相关外设无法正常使用

链接:https://blog.csdn.net/qq_36347513/category_9591718.html

二、软件方案

1、代码结构

智能除味器软件代码结构如下:

└── tuya_ble_sdk_demo ├── app ├── board │ ├── nRF52832 │ │ ├── include │ │ │ ├── tuya_appointment_timing_function.h │ │ │ ├── tuya_battery_check.h │ │ │ ├── tuya_ble_handle.h │ │ │ ├── tuya_deodorizer_temperature_humidity.h │ │ │ ├── tuya_key_process.h │ │ │ └── tuya_pwm.h │ │ ├── src │ │ │ ├── tuya_appointment_timing_function.c 设备定时 │ │ │ ├── tuya_battery_check.c 除味器完成回连上报数据 │ │ │ ├── tuya_ble_handle.c DP点数据处理 │ │ │ ├── tuya_deodorizer_temperature_humidity.c 自动档位调节 │ │ │ ├── tuya_key_process.c 手动档位调节 │ │ │ └── tuya_pwm.c 除味模式和保鲜模式

2、工作模式

智能除味器有除味、保险两种工作模式:

模式 功能
除味模式 臭氧离子发生器和负离子发生器一起工作
保鲜模式 臭氧离子发生器关闭,负离子发生器工作

其中,除味模式和保鲜模式分别有强、中、弱三个档位调节。通过对臭氧离子发生器和负离子发生器相连引脚进行不同的pwm占空比设置,使臭氧离子发生器和负离子发生器处于不同的工作强度,模拟出强、中、弱三档。PWM占空比对应关系如下:

档位 PWM占空比
强档 100%
中档 70%
弱档 50%

为了使面板内容更加丰富,本次除味器面板选择温湿度Studio面板,显示工作过程中的温湿度并形成温湿度曲线对数据进行记录。在产品创建时默认原有的DP功能点(随意删除可能会导致面板数据丢失或无法打开面板等情况)具体的DP点介绍如下:

自定义功能:

DP点名称 DP ID 数据传输类型 数据类型
工作模式 101 可下发可上报(rw) 枚举型(Enum)
档位 103 可下发可上报(rw) 枚举型(Enum)
定时 104 可下发可上报(rw) 枚举型(Enum)

在温湿度的标准功能中,将DP ID 3、4作为电池电量报警和电池电量显示的两个功能点来使用。

智能除味器处于除味模式一档档位的功能代码实现:

/** * @function: ty_ozone_first_gear_pwm_init * @brief: Ozone negative ion generator working mode * @param[in]: void * @return: success -> 0 fail -> else */
uint32_t ty_ozone_first_gear_pwm_init(void)
{ 
        
    uint32_t ret = 0;
    ozone_pwm.pin = OZONE_PWM_PIN;            //臭氧离子发生器连接引脚
    ozone_pwm.pin2 = NEGATIVE_ION_PWM_PIN;    //负离子发生器连接引脚
    ozone_pwm.polarity = 0;
    ozone_pwm.freq = 1000;
    ozone_pwm.duty = 50;
    negative_ion_pwm.duty = 50;

    ret = ty_pwm_init(&ozone_pwm);
    if(ret != 0){ 
        
        TUYA_APP_LOG_INFO("OZONE first pwm failed to initialize");
        return 1;
    }
    ty_pwm_start(&ozone_pwm);
    return 0;
}

智能除味器处于保鲜模式一档档位的功能代码实现:

/** * @function: ty_negative_ion_first_gear_pwm_init * @brief: Anion generator working mode * @param[in]: void * @return: success -> 0 fail -> else */
uint32_t ty_negative_ion_first_gear_pwm_init(void)
{ 
        
    uint32_t ret = 0;
    negative_ion_pwm.pin = NRFX_PWM_PIN_NOT_USED;
    negative_ion_pwm.pin2 = NEGATIVE_ION_PWM_PIN;
    negative_ion_pwm.polarity = 0;
    negative_ion_pwm.freq = 1000;
    negative_ion_pwm.duty = 50;

    ret = ty_pwm_init(&negative_ion_pwm);
    if (ret != 0)
    { 
        
        TUYA_APP_LOG_INFO("NEGATIVE_ION first pwm failed to initialize");
        return 1;
    }
    return 0;
}

3、档位调节

档位分为自动档位和手动档位两种调节方式。

除味器通过SHT30温湿度传感器获取温湿度,根据不同的温湿度数据自动进行档位调节(调节后,会将改变后的档位DP进行上报给APP面板),温湿度处理逻辑和档位对应关系如下:

温度 湿度 档位
(temperature > 10) && (temperature < 15) (humidity > 60) && (humidity < 65) 强档
(temperature > 15) && (temperature < 22) (humidity > 30) && (humidity < 50) 中档
(temperature > 22) && (temperature < 29) (humidity > 55) && (humidity < 75) 弱档

除味器自动档位调节以及进行自动挡位调节后档位DP上报的功能代码如下:

/** * @function: ty_gear_adjustment_using_temmperature_humidity * @brief: Automatic gear adjustment according to different temperature and humidity * @param[in]: void * @return: success -> 0 fail -> else */
uint32_t ty_gear_adjustment_using_temmperature_humidity(void)
{ 
        
    int32_t temperature = 0;
    int32_t humidity = 0;
    temperature = (int32_t)tuya_sht3x_collect_state.temperature_value;
    humidity = (int32_t)tuya_sht3x_collect_state.humidity_value;

    if ((temperature > 10) && (temperature < 15) && (humidity > 60) && (humidity < 65))
    { 
        
        if (mode_selection.fresh_keeping_mode == 1)
        { 
        
            ty_ozone_three_gear_pwm_init();
            ty_indicator_light();
            ty_third_gear();
        }
        if (mode_selection.deodorization_mode == 1)
        { 
        
            ty_ozone_three_gear_pwm_init();
            ty_negative_ion_three_gear_pwm_init();
            ty_indicator_light();
            ty_third_gear();
        }
    }
    else if ((temperature > 15) && (temperature < 22) && (humidity > 30) && (humidity < 50))
    { 
        
        if (mode_selection.fresh_keeping_mode == 1)
        { 
        
            ty_ozone_second_gear_pwm_init();
            ty_indicator_light();
            ty_second_gear();
        }
        if (mode_selection.deodorization_mode == 1)
        { 
        
            ty_ozone_second_gear_pwm_init();
            ty_negative_ion_second_gear_pwm_init();
            ty_indicator_light();
            ty_second_gear();
        }
    }
    else if ((temperature > 22) && (temperature < 29) && (humidity > 55) && (humidity < 75))
    { 
        
        if (mode_selection.fresh_keeping_mode == 1)
        { 
        
            ty_ozone_first_gear_pwm_init();
            ty_indicator_light();
            ty_first_gear();
        }
        if (mode_selection.deodorization_mode == 1)
        { 
        
            ty_ozone_first_gear_pwm_init();
            ty_negative_ion_first_gear_pwm_init();
            ty_indicator_light();
            ty_first_gear();
        }
    }
    else
    { 
        
        ;
    }

    return 0;
}
/** * @function: ty_first_gear * @brief: Adjust one gear to report DP * @param[in]: void * @return: success -> 0 fail -> else */
uint32_t ty_first_gear(void)
{ 
        
    uint32_t ret = 0;
    uint8_t dp_length = 5;
    uint8_t send_buf[5] = { 
        0};
    send_buf[0] = tuya_dp_id.gear_adjustment_id;
    send_buf[1] = tuya_dp_id.gear_adjustment_type;
    send_buf[2] = 0x00;
    send_buf[3] = 0x01;
    send_buf[4] = 0x00;
    ret = tuya_ble_dp_data_send(tuya_dp_id.sn_data + 2, DP_SEND_TYPE_ACTIVE, DP_SEND_FOR_CLOUD_PANEL, DP_SEND_WITHOUT_RESPONSE, send_buf, dp_length);
    return 0;
}

通过短按按键实现除味器的强、中、弱档位循环切换,同时调节后,会将改变后的档位DP进行上报给APP面板,核心功能代码如下:

/** * @function: ty_device_key_gear_adjust * @brief: Ozone generator and anion generator gear adjustment * @param[in]: void * @return: success -> 0 fail -> else */
uint32_t ty_device_key_gear_adjust(void)
{ 
        
    uint32_t gear_mode_ret = 0;
    uint32_t pin_level_state = 0;
    pin_level_state = ty_reset_key_state.key_short_press;
    if (pin_level_state == 1)
    { 
        
        ty_delay_us(10);
        if (pin_level_state == 1)
        { 
        
            gear_mode_ret = ty_get_device_gear_mode();              //获取当前的档位

            switch (gear_mode_ret)
            { 
        
                case 1:
                    if(mode_selection.fresh_keeping_mode == 1)
                    { 
        
                        ty_negative_ion_second_gear_pwm_init();     //保鲜模式二档
                        ty_indicator_light();
                        ty_second_gear();                           //上报当前档位
                    }
                    if(mode_selection.deodorization_mode == 1)
                    { 
        
                        ty_ozone_second_gear_pwm_init();            //除味模式二档
                        ty_indicator_light();
                        ty_second_gear();                           //上报当前档位
                    }

                    break;
                case 2:
                    if (mode_selection.fresh_keeping_mode == 1)
                    { 
        
                        ty_negative_ion_three_gear_pwm_init();      //保鲜模式二档
                        ty_indicator_light();
                        ty_third_gear();                            //上报当前档位
                    }
                    if (mode_selection.deodorization_mode == 1)
                    { 
        
                        ty_ozone_three_gear_pwm_init();             //除味模式二档
                        ty_indicator_light();
                        ty_third_gear();                            //上报当前档位
                    }

                    break;
                case 3:
                    if (mode_selection.fresh_keeping_mode == 1)
                    { 
        
                        ty_negative_ion_first_gear_pwm_init();      //保鲜模式二档
                        ty_indicator_light();
                        ty_first_gear();                            //上报当前档位
                    }
                    if (mode_selection.deodorization_mode == 1)
                    { 
        
                        ty_ozone_first_gear_pwm_init();             //除味模式二档
                        ty_indicator_light();
                        ty_first_gear();                            //上报当前档位
                    }

                    break;
                default:
                    break;
            }
            ty_sht3x_reset(); //i2c禁止初化
            ty_sht3x_init();  //温湿度传感器初始化

        }
    }
    ty_reset_key_state.key_short_press = 0;
    return 0;

}

4、低功耗

如果设备处于低电量或者设备定时到达,则进入低功耗,然后智能除味器需要上报低电量DP给APP面板,APP面板上进行低电量报警。

智能除味器进入低功耗并进行低电量上报给APP面板功能代码如下:

/** * @function:ty_device_stop_work * @brief: Turn off the peripherals and the device enters low power consumption * @param[in]: void * @return: success -> 0 fail -> else */

uint32_t ty_device_stop_work(void)
{ 
        
    ty_sht3x_single_messure();                //开启温湿度传感器单次测量模式,降低功耗
    nrf_gpio_pin_write(BOOST_PIN,0);          //关闭升压电路
    ty_switch_off_fan();                      //关闭电扇
    ty_switch_off_indicator_light();          //关闭指示灯
    ty_negative_ion_pwm_stop();               //关闭臭氧离子发生器和负离子发生器
    //ty_ble_stop_adv(); //蓝牙广播关闭函数
    ty_uart_uninit();                          //禁止串口初始化
    ty_uart2_uninit();                          //禁止串口初始化
    ty_rtc_uninit();                            //禁止RTC初始化
    ty_spi_disable();                           //禁止spi初始化

    ty_adc_uninit(&battery_check_adc);         //禁止电量检测
    ty_sht3x_reset();                         //关闭温湿度传感器
    low_power.low_power_glag = 1;               //设备进入低功耗状态
    appointment_timing_close.reservation_timing_off_flag = 1;
    return 0;
}
/** * @function:ty_low_power_dp_send * @brief: Low power report * @param[in]: void * @return: success -> 0 fail -> else */
uint32_t ty_low_power_dp_send(void)
{ 
        
    uint32_t ret = 0;
    uint8_t dp_length = 5;
    uint8_t send_buf[5] = { 
        0};
    send_buf[0] = tuya_dp_id.low_power_alarm_id;
    send_buf[1] = tuya_dp_id.low_power_alarm_type;
    send_buf[2] = 0x00;
    send_buf[3] = 0x01;
    send_buf[4] = 0x00;

    ret = tuya_ble_dp_data_send(tuya_dp_id.sn_data, DP_SEND_TYPE_ACTIVE, DP_SEND_FOR_CLOUD_PANEL, DP_SEND_WITHOUT_RESPONSE, send_buf, dp_length);
    if(ret != 0)
    { 
        
        TUYA_APP_LOG_INFO("ty_low_power_dp_send failed to send");
    }
    return 0;
}

5、设备定时

预约定时通过RTC来实现,设备工作时长有四种时长选择:

设备运行时长 设备关闭
15分钟 设别运行15分钟后关闭
30分钟 设备运行30分钟后关闭
1小时 设备运行1小时后关闭
2小时 设备运行2小时后关闭

在APP端对设智能除味器定时15分钟工作时长为例,首先需要计算出15分后RTC时间戳,此计算代码如下:

/** * @function:ty_rtc_get_time_and_fifteen_points_update_flag * @brief: Make an appointment for 15 minutes, obtain the time and update the flag bit * @param[in]: void * @return: success -> 0 fail -> else */
uint32_t ty_rtc_get_time_and_fifteen_points_update_flag(void)
{ 
        
    uint32_t current_time = 0;          //获取当前RTC时间
    ty_rtc_get_time(&current_time);
    appointment_time_arrival.time_end = current_time + APPOINTMENT_TIMING_FIFTEEN_POINTS;  //获取当前时间加上15分钟后的时间戳

    time_end_flag_bit.time_end_flag = 1;

    return 0;
}

然后在main()函数中判断当前的时间戳是否大于等于appointment_time_arrival.time_end结构体成员的值,如果满足条件,则设备调用ty_device_stop_work()接口,设备进入低功耗状态,核心代码如下:

/** * @function:ty_check_appointment_time * @brief: Determine whether the appointment time has arrived * @param[in]: void * @return: success -> 0 fail -> else */
uint32_t ty_check_appointment_time(void)
{ 
        
    uint32_t appointment_time = 0;
    if(!time_end_flag_bit.time_end_flag)
        return 0;

    while (time_end_flag_bit.time_end_flag)
    { 
        
        ty_rtc_get_time(&appointment_time);
        if (appointment_time >= appointment_time_arrival.time_end)    //判断预约除味器工作时长时间是否到达
        { 
        
            appointment_time_arrival.time_end = 0;
            time_end_flag_bit.time_end_flag = 0;
            ty_device_stop_work();                                   //关闭设备,进入低功耗状态
        }
    }

    return 0;
}

三、小结

​ 至此智能冰箱除味器样机就完成了,它可以APP控制,按键控制。具有模式切换,档位调节,自动定时,低电量告警等功能。智能除味器使用臭氧发生器与负离子发生器,产生臭氧与负离子,可以杀菌消毒,去除异味,净化空气,食材保鲜,是非常棒的智能硬件产品。在这款智能除味器的基础上还有很多功能可以深入开发,对其功能进行完善。同时您可以基于涂鸦 IoT 平台丰富它的功能,也可以更加方便的搭建更多智能产品原型,加速智能产品的开发流程。

标签: 用于电池箱连接器的连接结构保鲜传感器

锐单商城拥有海量元器件数据手册IC替代型号,打造 电子元器件IC百科大全!

锐单商城 - 一站式电子元器件采购平台