智能除味器——嵌入式开发
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)下载芯片对应的安装包
- 第一次打开工程会自动下载 nRF52832 芯片对应的安装包。
- (可选)安装包下载完成后,如果第一次开发,会显示以下报错信息,可忽略该报错,继续完成安装。
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 烧录器连接到开发板,连线如下:
模组对应引脚 | 串口对应引脚 |
---|---|
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)找到 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(¤t_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 平台丰富它的功能,也可以更加方便的搭建更多智能产品原型,加速智能产品的开发流程。
以上是关于智能除味器——嵌入式开发的主要内容,如果未能解决你的问题,请参考以下文章