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

Posted 三明治开发社区

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了智能除味器——嵌入式开发相关的知识,希望对你有一定的参考价值。

一、产品创建

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

注意:不要将下载的SDK放在Liunx共享文件夹或者中文路径下,否则在编译时会出现 No such file or directory等未知错误。

下载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文件中将 use_ext_license_key、device_id_len 的值分别改为1、DEVICE_ID_LEN(16),否则上步修改的uuid、auth_key等不会生效。

3、设备连线

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

模组对应引脚串口对应引脚
VCCVCC(3.3V)
模组对应引脚JLINK对应引脚
SWDIOSWDIO
SWCSWCLK
GNDGND

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)找到 tuya-ble-sdk-demo-project-nrf52832-V2.1.0\\tuya_ble_sdk_demo\\board\\nRF52832\\tuya_ble_port 文件夹下的 custom_tuya_ble_config.h 文件。将第113行 TUYA_APP_LOG_ENABLE 日志输出使能。
​ (2)找到 ble_peripheral\\tuya-ble-sdk-demo-project-nrf52832-V2.1.0\\tuya_ble_sdk_demo\\board 文件夹下的board.h 文件。将第38行 TY_LOG_ENABLE 日志输出使能。
​ (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行宏定义 TUYA_BLE_SDK_TEST 关闭,该宏为测试模式的开关,打开会导致测试功能模块占用相关IO口资源使部分IO口以及相关外设无法正常使用

nRF52832学习笔记参考网址如下:

链接: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 平台丰富它的功能,也可以更加方便的搭建更多智能产品原型,加速智能产品的开发流程。

以上是关于智能除味器——嵌入式开发的主要内容,如果未能解决你的问题,请参考以下文章

智能除味器--硬件方案:PCBA设计

智能除味器——硬件方案:功能模块设计

智能除味器——硬件方案:功能模块设计

智能除味器--整体硬件方案概述

涂鸦智能颈部按摩仪设计——档位切换实现(嵌入式)

涂鸦智能颈部按摩仪设计——语音播报加热(嵌入式)