前言
我们已经创造了产品并建立了它们app接下来,我们将实现智能水壶的温度采集和过温报警功能。
一、智能水壶的功能设置
- 智能水壶的功能设置如下表所示。我们将整个智能水壶分成几个模块,逐个实现功能;本文实现了水壶的温度收集和声音报警功能。温度收集主要用于水温的温度控制和调节。当温度高于105摄氏度时,水壶处于干烧状态,蜂鸣器进行声音报警。
| 功能 | 说明 |
|---|---|
| 煮沸 | 触摸按钮1,触发方式:触摸。默认煮沸。触摸按钮控制煮沸按钮 app控制:煮沸 |
| 保温键 | 触摸按钮1在默认自来水模式下进入55度保温模式 |
| 指示灯 | 按开关键,开关灯亮,开关灯熄灭。 按钮保温键,温度不到(高于或低于)设定温度,保温键亮橙色;温度达到设定温度,保温键亮绿色。 app设定保温,温度未到(高于或低于)设定温度,保温键亮橙色;温度到设定温度,保温键亮绿色。 |
| 按键提示 | 按开:按红灯亮,松开灭。蜂鸣器滴一声提醒。 保温键:按下橙灯亮,松开灭。蜂鸣器滴一声提醒。 |
| 煮水模式 | app控制:纯净水模式、自来水模式。自来水模式默认。纯水模式:恒温后直接加热至设定温度。 自来水模式:冷却值设定温度。 |
| 温度模式 | app控制。恒温模式。 恒温模式: 可app设定温度为45度、55度、70度、90度(或45-90度),选择后恒定在设定温度。默认为55度。 |
二、制定温度采集方案
1.温度采集原理
在这种情况下,温度采集方案采用热敏电阻,在不同温度下具有不同的电阻值。根据这一特点,通过电路设计和软件程序采集到热敏电阻的电阻值,计算当前的温度值。 采样电路图如下:R8为10k定值电阻,R六是热敏电阻(常温为1000)k阻值),ADC热敏电阻的电阻值可根据欧姆定律计算。 
- 获得热敏电阻值Rt,根据B3950热敏曲线可计算当前温度值。 上图是该系列热敏电阻的热敏曲线
上述参数含义 R0:25℃下电阻值 本文选择的热敏电阻为25℃阻值为10k R:当前温度下电阻的电阻值 T0:开尔文温度(2733).15 25) T:开尔文温度(273.15 当前摄氏度温度) B: 热敏特性常数 exp:e^n(e的n次方) 采样电路采样热敏电阻两端的电压,计算R的电阻,然后根据R的电阻计算当前温度 R=R0 expB (1/T-1/T0) || \/ T=1/(ln(R/R0)/B 1/T0)近似为T=1/(log(R/R0)/B 1/T0) T是开尔文的温度,转换成摄氏度 temp = T - 273.15 已知测温原理,下一步是软件实现阶段。
2.软件方案设置
在上一篇文章中,我们对现有文章进行了探讨tuya_demo_template项目进行了修改,实现了基本的嵌入式框架,现在我们在此基础上开发,实现了温度采集功能。
- 所用的SOC引脚图如下:
- 设置温度采集方案 根据上述温度测量原理,我们需要使用它AD采集功能,测量热敏电阻的两端电压;因此,我们使用所选的SOC自带的ADC电压采集采样功能SOC12位精度ADC,可以满足我们的采样精度。 获得电压后,按照上述原理推出的公式实现C语言代码,计算当前温度值。
- 无源蜂鸣器驱动。频率为5K在这种情况下,蜂鸣器用于按键和高温报警。
| 引脚说明 | |
|---|---|
TUYA_ADC2 |
ADC |
| buzzer_pin | P17 |
三、功能实现
1.代码实现
- 在工程中建立几份文件,b3950.c 、kettle_app.c、timer.c、gpio_control.c,最终文件组成如下:
├── src | ├── tuya_drive | | └── b3950 | | └── b3950.c ///温度传感器驱动 | | └── gpio_control | | └── gpio_control.c //gpio 控制相关 | | └── timer | | └── timer.c ////定时器相关 | ├── tuya_device.c //应用层入口文件 | └── kettle_app.c ///智能水壶主要应用文件 | ├── include //头文件目录 | ├── tuya_drive_h | | └── b3950_h | | └── b3950.h | | └── gpio_control_h | | └── gpio_control.h | | └── timer_h | | └── timer.h ////定时器相关 | ├── tuya_device.h | └── kettle_app.h | └── output ///编译产品
其中b3950.c文件中的内容主要是实现温度采集的代码,kettle_app.c 文件主要是智能水壶的应用代码,timer.c该函数是定时器的相关代码,主要用于驱动无源蜂鸣器的频率。
b3950.c中函数实现如下:
//初始化adc设备 void b3950_init(void) {
/*create adc device,get handle*/ temper_adc = (tuya_adc_t *)tuya_driver_find(TUYA_DRV_ADC, TUYA_ADC2); /*adc_dev cfg*/
TUYA_ADC_CFG(temper_adc, TUYA_ADC2, 0);
/*adc_dev init*/
tuya_adc_init(temper_adc);
}
/** * @Function: cur_temper_get * @Description: current temperature get * @Input: none * @Output: none * @Return: temperature value * @Others: */
int cur_temper_get()
{
int Rt = 0;
float Rp = 100000;
float T2 = 273.15 + 25;
float Bx = 3950;
float Ka = 273.15;
int temp = 0;
/*Collect AD data and store it in adc_buffer*/
tuya_adc_convert(temper_adc, &adc_buf, 1);
/*req_val(0-4096) - V(0-2.4)*/
volt = (float)adc_buf *2.4/ 4096;
//volt = adc_buf;
Rt = (3.3 - volt)*20000/volt;
PR_DEBUG("Rt:%d", Rt);
temp = (int)(1/(1/T2+log(Rt/Rp)/Bx)-Ka+0.5);
PR_DEBUG("volt:%f", volt);
return temp;
}
timer.c中函数实现如下:产生频率驱动蜂鸣器
//启动定时器
void timer_init(void)
{
timer = (tuya_timer_t *)tuya_driver_find(TUYA_DRV_TIMER, TUYA_TIMER1);
//The timer uses cycle mode
TUYA_TIMER_CFG(timer, TUYA_TIMER_MODE_PERIOD, tuya_timer0_cb, NULL);
tuya_timer_init(timer);
//Start the timer, 100us is a counting cycle
tuya_timer_start(timer, 100);
buzzer_set(1);
}
/** * @Function: timer_stop * @Description: stop timer0 * @Input: none * @Output: none * @Return: none * @Others: */
void timer_stop(void)
{
tuya_timer_stop(timer);
}
/** * @Function: tuya_timer0_cb * @Description: tuya_timer0_cb * @Input: none * @Output: none * @Return: none * @Others: */
void tuya_timer0_cb(void *arg)
{
static uint32_t s_tick;
static int level = 1;
level = ~level;
buzzer_set(level);
if (s_tick++ >= 700) {
s_tick = 0;
tuya_timer_stop(timer);
buzzer_set(0);
}
}
kettle_app.c中主要实现主任务线程创建、互斥锁创建、软件定时器任务创建,实现代码如下:
//线程初始化函数,创建定时器线程每5秒采集一次温度,创建主应用线程,创建互斥锁
void thread_init(void)
{
int rt = OPRT_OK;
// create mutex
if(NULL == mutex) {
rt = tuya_hal_mutex_create_init(&mutex);
if(OPRT_OK != rt) {
PR_ERR("tuya_hal_mutex_create_init err:%d",rt);
return rt;
}
}
//A timer with a period of 5 second is used to capture the temperature
rt = sys_add_timer(get_temper_timer_cb, NULL, &get_temper_timer);
if(rt != OPRT_OK) {
PR_ERR("add timer error!: %d", rt);
return;
}else {
rt = sys_start_timer(get_temper_timer,5000,TIMER_CYCLE);
if(rt != OPRT_OK) {
PR_ERR("start timer error!: %d", rt);
return;
}
}
rt = tuya_hal_thread_create(NULL, "app_kettle_thread", 512*4, TRD_PRIO_4, app_kettle_thread, NULL);
if (rt != OPRT_OK) {
PR_ERR("Create update_dp_thread error!: %d", rt);
return;
}
}
//智能烧水壶主应用线程,当前只实现过温报警功能,后面会填充水温调节等功能
void app_kettle_thread(void)
{
//Over temperature protection Limiting_Temperature :105℃
if(get_water_temperature() > Limiting_Temperature) {
timer_init(); //buzzer on
set_dp_fault_status(TRUE);//更新故障状态 正常->干烧
report_one_dp_status(DP_FAULT);//app上显示故障信息
relay_set(OFF);
}else {
if(get_dp_fault_status() == TRUE) {
set_dp_fault_status(FALSE);//更新故障状态 干烧->正常
report_one_dp_status(DP_FAULT);//app上显示故障信息
}
}
tuya_hal_system_sleep(1000);
}
}
//软件定时器回调函数,定时采集温度并上报
void get_temper_timer_cb(void)
{
static int last_temper = 0;
last_temper = cur_temper_get();
if(last_temper > 150) {
last_temper = 150;
}
else if(last_temper < 0) {
last_temper = 0;
}
set_current_temperature(last_temper);
tuya_hal_mutex_lock(mutex);
temper_s.value = last_temper;
tuya_hal_mutex_unlock(mutex);
PR_DEBUG("last_temper : %d",last_temper);
report_one_dp_status(DP_TEMPER);//上报温度信息到app
}
- 此时已经实现了智能烧水壶的温度采集和过温报警功能,后面文章我们将实现智能烧水壶的按键控制功能。
下篇章节快速入口: 智能烧水壶(WIFI版)04——TS02N触摸按键驱动篇
技术支持
您可以通过以下方法获得涂鸦的支持:
- 涂鸦智能IoT平台
- Demo中心
- 涂鸦智能开发者中心