Toggle navigation
首页
问答
文章
积分商城
专家
专区
更多专区...
文档中心
返回主站
搜索
提问
会员
中心
登录
注册
AB32VG1
测试
温度监测
AB32VG1之温度监测及预警系统
发布于 2021-05-10 21:28:17 浏览:1009
订阅该版
[tocm] # 1、温度预警系统介绍 该系统可实现温度的实时监测(DS18B20)、温度存储(EE)、温度查询(UART)、温度预警以及告警。 串口助手使用的是XCOM(自动添加回车和换行),串口参数为:波特率9600、停止位1、数据位8、无校验。温度查询指令为what's the temp # 2、硬件 存储设备:AT24C04 引脚15(PB2-SDA)、16(PB1-SCL) 温度监测:DS18B20 引脚PF0 查询、预警、告警:串口通讯 UART1 指示灯 :三色LED ![image.png](https://oss-club.rt-thread.org/uploads/20210509/ac766d34795fe7dae791e16be3dcedc5.png) # 3、软件 ## 3.1、各模块基础内容 该系统参考内容如下: [AB32VG1之模拟IIC](https://club.rt-thread.org/ask/article/2755.html) [AB32VG1之DS18B20的使用](https://club.rt-thread.org/ask/article/2756.html) [AB32VG1之UART通讯](https://club.rt-thread.org/ask/article/2758.html) 以及JiangYangJie的[AB32VG1系列之点灯](https://club.rt-thread.org/ask/article/2599.html) ## 3.2、修改内容 ### 3.2.1 EE新增 添加EE初始化代码,在实现EE初始化的同时,还可以将上次断电之前储存的温度读出,进行显示,代码内容如下 ``` int at24cxx_Demo(void) { static at24cxx_device_t dev = RT_NULL; uint8_t testbuffer[4]; uint32_t Temp_Val = 0; if (dev) { at24cxx_deinit(dev); } dev = at24cxx_init("i2c1", 0); EE_DEV = dev; if (dev != RT_NULL) { rt_kprintf("EE Init OK \n"); if (at24cxx_check(dev) == 1) { rt_kprintf("EE check faild \n"); return RT_ERROR; } else { rt_kprintf("EE check OK \n"); } } else { rt_kprintf("Init EE faild \n"); return RT_ERROR; } /* read the eeprom data */ at24cxx_read(dev, 0x01, testbuffer, 4); Temp_Val = (uint32_t)(testbuffer[3]); Temp_Val = ((uint32_t)(Temp_Val)<<8)|(testbuffer[2]); Temp_Val = ((uint32_t)(Temp_Val)<<8)|(testbuffer[1]); Temp_Val = ((uint32_t)(Temp_Val)<<8)|(testbuffer[0]); rt_kprintf("The last temp is:%3d.%dC\n", Temp_Val / 10, Temp_Val % 10); DS18B20_Temp = Temp_Val; return RT_NULL; } INIT_COMPONENT_EXPORT(at24cxx_Demo); ``` ### 3.2.2 DS18B20新增 去除原例程中实时读取温度值的函数,添加读取温度值线程:使其1s读一次温度并进行滤波,代码如下: ``` static void read_temp_entry(void *parameter) { rt_device_t dev = RT_NULL; struct rt_sensor_data sensor_data; rt_size_t res; dev = rt_device_find(parameter); if (dev == RT_NULL) { rt_kprintf("Can't find device:%s\n", parameter); return; } if (rt_device_open(dev, RT_DEVICE_FLAG_RDWR) != RT_EOK) { rt_kprintf("open device failed!\n"); return; } rt_device_control(dev, RT_SENSOR_CTRL_SET_ODR, (void *)100); while (1) { res = rt_device_read(dev, 0, &sensor_data, 1); if (res != 1) { rt_kprintf("read data failed!size is %d\n", res); rt_device_close(dev); return; } else { DS18B20_Temp = filter(sensor_data.data.temp); } rt_thread_mdelay(1000); } } static int ds18b20_read_temp_sample(void) { rt_thread_t ds18b20_thread; ds18b20_thread = rt_thread_create("18b20tem", read_temp_entry, "temp_ds18b20", 1024, RT_THREAD_PRIORITY_MAX / 2, 20); if (ds18b20_thread != RT_NULL) { rt_thread_startup(ds18b20_thread); } return RT_EOK; } INIT_APP_EXPORT(ds18b20_read_temp_sample); ``` 在温度值滤波函数中添加每出现一次温度改变超过2℃就写一次EE,并且在终端进行提示,代码如下: ``` static rt_int32_t filter(rt_int32_t new_value) { static rt_int32_t value = 0; static rt_bool_t FirstGet = 0; static rt_int32_t Count = 0; unsigned char buf[4]; if(FirstGet != 0) { if ((abs(new_value - value)> A)&&((abs(new_value - value)< B))) { buf[0] = (unsigned char)(new_value & 0xFF); buf[1] = (unsigned char)((new_value>>8) & 0xFF); buf[2] = (unsigned char)((new_value>>16) & 0xFF); buf[3] = (unsigned char)((new_value>>24) & 0xFF); rt_kprintf("temp:%3d.%dC,write count :%d\n", new_value / 10, new_value % 10, Count++); value = new_value; at24cxx_write(EE_DEV, 0x01, buf, 4); return value; } } else { buf[0] = (unsigned char)(new_value & 0xFF); buf[1] = (unsigned char)((new_value>>8) & 0xFF); buf[2] = (unsigned char)((new_value>>16) & 0xFF); buf[3] = (unsigned char)((new_value>>24) & 0xFF); rt_kprintf("temp:%3d.%dC,write count :%d\n", new_value / 10, new_value % 10, Count++); FirstGet = 1; value = new_value; } return new_value; } ``` ### 3.2.3 UART新增 添加串口例程,这里添加的是官网[UART设备](https://www.rt-thread.org/document/site/programming-manual/device/uart/uart/)中的第二个例程,既接收到特定内容进行答复,程序里实现的是:接收到what's the temp指令,则回复当前温度,收到其它指令则回复Please check your CMD!。代码如下: ``` static const int8_t NoticeBuf1[]="The temperature is:"; static const int8_t NoticeBuf2[]="Please check your CMD!"; struct serial_configure config = RT_SERIAL_CONFIG_DEFAULT; /* 初始化配置参数 */ /* 用于接收消息的信号量 */ static struct rt_semaphore rx_sem; static rt_device_t serial; #define GET_TEMP_CMD "what's the temp" /** * @brief uart_input //接收数据回调函数 * @param dev * size * @retval RT_EOK */ static char Int2Char(int8_t Data) { char Temp_Change = 0; if(Data == 0) { Temp_Change = '0'; } else if(Data == 1) { Temp_Change = '1'; } else if(Data == 2) { Temp_Change = '2'; } else if(Data == 3) { Temp_Change = '3'; } else if(Data == 4) { Temp_Change = '4'; } else if(Data == 5) { Temp_Change = '5'; } else if(Data == 6) { Temp_Change = '6'; } else if(Data == 7) { Temp_Change = '7'; } else if(Data == 8) { Temp_Change = '8'; } else if(Data == 9) { Temp_Change = '9'; } else { Temp_Change = ' '; } return Temp_Change; } /* 数据解析线程 */ static void data_parsing(void) { int8_t ch; int8_t data[ONE_DATA_MAXLEN]; static int8_t i = 0; int8_t buf[6]; int8_t Hundred = 0 ,Dacade = 0,Unit = 0; while (1) { ch = uart_sample_get_char(); if(ch == DATA_CMD_END) { //针对XCOM结尾默认发送\r\n的处理 data[i--] = '\0'; data[i] = 0; data[i++] = 0; rt_kprintf("data=%s\r\n",data); if(0 == strcmp(data,GET_TEMP_CMD)) { if(DS18B20_Temp > 0)//温度为零上 { //先打印温度 rt_kprintf("The current temperature is:%3d.%dC\n", DS18B20_Temp / 10, DS18B20_Temp % 10); //串口输出温度 Hundred = (int8_t)(DS18B20_Temp / 100);//百位 Dacade = (int8_t)((DS18B20_Temp - Hundred*100) / 10);//十位 Unit = (int8_t)(((DS18B20_Temp - Hundred*100) - Dacade*10));//个位 buf[0] = Int2Char(Hundred); buf[1] = Int2Char(Dacade); buf[2] = '.'; buf[3] = Int2Char(Unit); buf[4] = '\r'; buf[5] = '\n'; } else { //先打印温度 rt_kprintf("The current temperature is:-%2d.%dC\n", -DS18B20_Temp / 10, -DS18B20_Temp % 10); //串口输出温度 Hundred = (int8_t)(-DS18B20_Temp / 100);//百位 Dacade = (int8_t)((-DS18B20_Temp - Hundred*100) / 10);//十位 Unit = (int8_t)(((-DS18B20_Temp - Hundred*100) - Dacade*10));//个位 buf[0] = '-'; buf[1] = Int2Char(Hundred); buf[2] = Int2Char(Dacade); buf[3] = '.'; buf[4] = Int2Char(Unit); buf[5] = '\r'; buf[6] = '\n'; } rt_device_write(serial, 0, NoticeBuf1, (sizeof(NoticeBuf1)-1)); rt_device_write(serial, 0, buf, 6); } else { rt_device_write(serial, 0, NoticeBuf2, (sizeof(NoticeBuf2)-1)); } i = 0; continue; } i = (i >= ONE_DATA_MAXLEN-1) ? ONE_DATA_MAXLEN-1 : i; data[i++] = ch; } } static int uart_data_sample(void) { rt_err_t ret = RT_EOK; char uart_name[RT_NAME_MAX]; char str[] = "hello RT-Thread!\r\n"; /* 查找系统中的串口设备 */ serial = rt_device_find(SAMPLE_UART_NAME); if (!serial) { rt_kprintf("find %s failed!\n", SAMPLE_UART_NAME); return RT_ERROR; } /* 修改串口配置参数 */ config.baud_rate = BAUD_RATE_9600; //修改波特率为 9600 config.data_bits = DATA_BITS_8; //数据位 8 config.stop_bits = STOP_BITS_1; //停止位 1 config.bufsz = 64; //修改缓冲区 buff size 为 128 config.parity = PARITY_NONE; //无奇偶校验位 /* 控制串口设备。通过控制接口传入命令控制字,与控制参数 */ rt_device_control(serial, RT_DEVICE_CTRL_CONFIG, &config); /* 初始化信号量 */ rt_sem_init(&rx_sem, "rx_sem", 0, RT_IPC_FLAG_FIFO); /* 以中断接收及轮询发送模式打开串口设备 */ rt_device_open(serial, RT_DEVICE_FLAG_INT_RX); /* 设置接收回调函数 */ rt_device_set_rx_indicate(serial, uart_input); /* 发送字符串 */ rt_device_write(serial, 0, str, (sizeof(str) - 1)); rt_kprintf("Serial Init ok\n"); /* 创建 serial 线程 */ rt_thread_t thread = rt_thread_create("serial", (void (*)(void *parameter))data_parsing, RT_NULL, 1024, 2, 10); /* 创建成功则启动线程 */ if (thread != RT_NULL) { rt_thread_startup(thread); } else { ret = RT_ERROR; } return ret; } INIT_APP_EXPORT(uart_data_sample); ``` ### 3.2.4 三色LED新增 不同温度闪烁不同颜色,并且在温度达到一定温度后主动通过串口提示温度偏高或告警(每两秒提示一次),并且在告警过程中依然可以查询当前温度,对应关系如下: 序号 | 温度段 | 颜色 | 备注 -----|-------|----- |----- 1 | 小于-5 | COLOR_PURPLE | 低温告警 2 | -5到5 | COLOR_BLUE | 低温提示 3 | 5到15 | COLOR_CYAN | 无 4 | 15到25 | COLOR_WHITE | 无 5 | 25到35 | COLOR_YELLOW | 无 6 | 35到40 | COLOR_GREEN | 高温提示 7 | 大于40 | COLOR_RED | 高温告警 代码内容如下: ``` /**define***********************************************************************/ #define LED_R "PE.1" #define LED_G "PE.4" #define LED_B "PA.2" //默认白色 COLORS COLOR_PANNAL = COLOR_WHITE; static const int8_t WarningBuf1[]="Temperature too high!!!\r\n"; static const int8_t WarningBuf2[]="Temperature too low!!!\r\n"; static const int8_t WarningBuf3[]="Temperature high!!!\r\n"; static const int8_t WarningBuf4[]="Temperature low!!!\r\n"; static uint8_t Warning_High = 0;//温度过高提醒 预留 static uint8_t Warning_Low = 0;//温度过低提醒 预留 static rt_base_t pin_r; static rt_base_t pin_g; static rt_base_t pin_b; /**fuction***********************************************************************/ //LED引脚初始化 int LED_INIT(void) { pin_r = rt_pin_get(LED_R); pin_g = rt_pin_get(LED_G); pin_b = rt_pin_get(LED_B); rt_pin_mode(pin_r, PIN_MODE_OUTPUT); rt_pin_mode(pin_g, PIN_MODE_OUTPUT); rt_pin_mode(pin_b, PIN_MODE_OUTPUT); return RT_NULL; } INIT_BOARD_EXPORT(LED_INIT); //LED全灭 void LED_CloseALL(void) { //黑(全部关闭) rt_pin_write(pin_r, OFF); rt_pin_write(pin_g, OFF); rt_pin_write(pin_b, OFF); } //温度与颜色关系 static void Temp_Color(void) { //温度超过40℃ if(DS18B20_Temp >= 400) { Warning_High = 1; COLOR_PANNAL = COLOR_RED; } else if((DS18B20_Temp < 400)&&(DS18B20_Temp >= 350))//350-400 { COLOR_PANNAL = COLOR_GREEN; } else if((DS18B20_Temp < 350)&&(DS18B20_Temp >= 251))//251-350 { COLOR_PANNAL = COLOR_YELLOW; } else if((DS18B20_Temp < 251)&&(DS18B20_Temp >= 150))//150-251 { COLOR_PANNAL = COLOR_WHITE; } else if((DS18B20_Temp < 150)&&(DS18B20_Temp >= 50))//50-150 { COLOR_PANNAL = COLOR_CYAN; } else if((DS18B20_Temp < 50)&&(DS18B20_Temp >= -50))//-50-50 { Warning_Low = 1; COLOR_PANNAL = COLOR_BLUE; } else if(DS18B20_Temp < -50)//<-50 { COLOR_PANNAL = COLOR_PURPLE; } else { COLOR_PANNAL = COLOR_NULL; } } //LED颜色选择 void LED_COLOR_CHANGE(void) { Temp_Color(); switch(COLOR_PANNAL) { case COLOR_RED: rt_pin_write(pin_r, ON); rt_pin_write(pin_g, OFF); rt_pin_write(pin_b, OFF); rt_device_write(rt_device_find(SAMPLE_UART_NAME), 0, WarningBuf1, (sizeof(WarningBuf1) - 1)); break; case COLOR_GREEN: rt_pin_write(pin_r, OFF); rt_pin_write(pin_g, ON); rt_pin_write(pin_b, OFF); rt_device_write(rt_device_find(SAMPLE_UART_NAME), 0, WarningBuf3, (sizeof(WarningBuf3) - 1)); break; case COLOR_YELLOW: rt_pin_write(pin_r, ON); rt_pin_write(pin_g, ON); rt_pin_write(pin_b, OFF); break; case COLOR_WHITE: rt_pin_write(pin_r, ON); rt_pin_write(pin_g, ON); rt_pin_write(pin_b, ON); break; case COLOR_CYAN: rt_pin_write(pin_r, OFF); rt_pin_write(pin_g, ON); rt_pin_write(pin_b, ON); break; case COLOR_BLUE: rt_pin_write(pin_r, OFF); rt_pin_write(pin_g, OFF); rt_pin_write(pin_b, ON); rt_device_write(rt_device_find(SAMPLE_UART_NAME), 0, WarningBuf4, (sizeof(WarningBuf4) - 1)); break; case COLOR_PURPLE: rt_pin_write(pin_r, ON); rt_pin_write(pin_g, OFF); rt_pin_write(pin_b, ON); rt_device_write(rt_device_find(SAMPLE_UART_NAME), 0, WarningBuf2, (sizeof(WarningBuf2) - 1)); break; case COLOR_NULL: rt_pin_write(pin_r, OFF); rt_pin_write(pin_g, OFF); rt_pin_write(pin_b, OFF); break; } } ``` ## 3.3、现象 ### 3.3.1 上电EE中初始化及温度值读取 ![image.png](https://oss-club.rt-thread.org/uploads/20210509/df53ec09a6437f9f5ed7d71f0d0e0725.png) ### 3.3.2 温度值变化超过两度刷新EE存储 ![image.png](https://oss-club.rt-thread.org/uploads/20210509/b468f686e57171223475c05f90024689.png) ### 3.3.3 上电自动串口设备在线通知+温度查询 ![image.png](https://oss-club.rt-thread.org/uploads/20210509/e461367946f9eee4a210876c8694275b.png) 温度查询指令正确时,终端会打印当前指令,并答复当前温度 ![image.png](https://oss-club.rt-thread.org/uploads/20210509/616773211a3d16f69397f62891051a5f.png) 温度查询指令错误时,终端会打印当前指令,并提示当前指令错误 ![image.png](https://oss-club.rt-thread.org/uploads/20210509/616773211a3d16f69397f62891051a5f.png) ### 3.3.4 温度预警+告警 因为条件有限无法实现预警与告警温度,所以写了一个可输入温度的MESH指令,在使用前需要拔掉DS18B20并重启,预警现象如下 1、低温预警 ![image.png](https://oss-club.rt-thread.org/uploads/20210509/138f152bd1bbddf8e63597d82ca2de73.png) 此时小灯闪烁蓝灯。 ![image.png](https://oss-club.rt-thread.org/uploads/20210509/bcc6faada8ce94b7165292f4aaaf03f6.png) 2、高温预警 ![image.png](https://oss-club.rt-thread.org/uploads/20210509/863d2e79bf29ff9383610ee20c6bf92b.png) 这里小灯应该闪绿色,具体的到视频里看吧。 3、低温告警 ![image.png](https://oss-club.rt-thread.org/uploads/20210509/9dbee24df044997386b77abda22f650a.png) 这里小灯应该闪紫色。 4、高温告警 ![image.png](https://oss-club.rt-thread.org/uploads/20210509/2c9d63ee54950db9a69853462041e1b1.png) 这里小灯应该闪红色。 # 5、心得体会 该系统从想法到实现,最主要耗费时间的地方在us级定时器以及串口的回调函数缺失问题的排查,其它的底层程序基本上没有自己动手去编写,仅仅是通过官方例程或者上一批测评代码进行的修改重组,足以说明RT-Thread Studio搭配蓝讯AB32VG1开发板进行小项目的开发是十分便捷的。唯一的不足是这款开发板资源太少,希望官方可以尽快补充吧。 因本人水平有限,文章内容及代码中可能会出现错误,还请谅解。 # 6、代码及视频展示地址 代码地址:[gitee](https://gitee.com/werper/ab32-vg1) 视频地址:[整体展示](https://www.bilibili.com/video/BV14b4y1f7Ek/)
0
条评论
默认排序
按发布时间排序
登录
注册新账号
关于作者
werper
叫我点灯大师
文章
9
回答
15
被采纳
1
关注TA
发私信
相关文章
1
关于free命令的测试和疑惑
2
如何测试一条指令的执行所需的时间?
3
riscv32-elf-xmaker 工具的目的
4
AB32VG1 的 RTC 内部怎么知道自己是第一次上电的呢?
5
AB32VG1 蓝牙功能
6
AB32VG1 片上 flash 的库能否发布出来
7
【中科蓝汛AB32VG1】开发板是否支持USB HOST
8
有基于RT-Thread 和 AB32VG1 的蓝牙示例吗?
9
AB32VG1_RTC时钟
10
AB32 串口2.是哪个管脚
推荐文章
1
RT-Thread应用项目汇总
2
玩转RT-Thread系列教程
3
国产MCU移植系列教程汇总,欢迎查看!
4
机器人操作系统 (ROS2) 和 RT-Thread 通信
5
五分钟玩转RT-Thread新社区
6
【技术三千问】之《玩转ART-Pi》,看这篇就够了!干货汇总
7
关于STM32H7开发板上使用SDIO接口驱动SD卡挂载文件系统的问题总结
8
STM32的“GPU”——DMA2D实例详解
9
RT-Thread隐藏的宝藏之completion
10
【ART-PI】RT-Thread 开启RTC 与 Alarm组件
热门标签
RT-Thread Studio
串口
Env
LWIP
SPI
AT
Bootloader
Hardfault
CAN总线
FinSH
ART-Pi
USB
DMA
文件系统
RT-Thread
SCons
RT-Thread Nano
线程
MQTT
STM32
RTC
FAL
rt-smart
ESP8266
I2C_IIC
WIZnet_W5500
UART
ota在线升级
PWM
cubemx
freemodbus
flash
packages_软件包
BSP
潘多拉开发板_Pandora
定时器
ADC
GD32
flashDB
socket
中断
Debug
编译报错
SFUD
msh
rt_mq_消息队列_msg_queue
keil_MDK
ulog
MicroPython
C++_cpp
本月问答贡献
出出啊
1517
个答案
342
次被采纳
小小李sunny
1443
个答案
289
次被采纳
张世争
805
个答案
174
次被采纳
crystal266
547
个答案
161
次被采纳
whj467467222
1222
个答案
148
次被采纳
本月文章贡献
出出啊
1
篇文章
4
次点赞
小小李sunny
1
篇文章
1
次点赞
张世争
1
篇文章
1
次点赞
crystal266
2
篇文章
2
次点赞
whj467467222
2
篇文章
1
次点赞
回到
顶部
发布
问题
投诉
建议
回到
底部