【系统功能】
cw32l083为主控制的无线终端数据收发。运行国产rt-thread操作系统。主要功能为实现用e31-ttl-50接收各个模块发送上来的数据,解析数据,分析数据,显示数据,并实现信息的显示,以及异常情况的显示、警告功能。
无线终端主要以cw32l031为主控,采集sht30温湿度传感器数据,通过e31-ttl-50无线模块将数据上传。实现5微安的待机电流的超低功耗。
【功能模块】
主机:
1、接收模块:接收无线终端模块发送的温湿度数据,解析数据后,更新模块数据。
2、巡检模块:定时巡检各个无线终端的数据,判定工作状况、更新显示、报警标志。
3、显示模块:根据各个模块的工作状态,生成为示数据,用tft屏展示。
4、报警模块:驱动pwm模块,装载pwm重载值,发出警示声音。
无线终端:
1、温湿采集模块:采集sht30数据。
2、发送模块:将数据打包,通过无线发送。
3、休眠模块:发送完数据后进入深度休眠状态,由awt模块定时唤醒。
【硬件】
主机:
1、cw32l083vxtx startkit rev01开发板。
2、st7735tft显示屏。
3、e31-ttl-50无线串口模块。
无线终端:
1、cw32l031开发板
2、sht30温湿度传感器。
3、e31-ttl-50无线串口模块。
4、可充电锂电池。
【开发环境】
1、代码编译环境采集ubuntu20.4;
2、代码编辑工具为vscode 1.79.2;
3、交叉编译器为arm-nano-eabi-gcc;
4、固件库为cw32提供的固件库;
5、gcc启动文件与链接由作者在cortex-m0+的其他软件上移植过来;
6、下载器为cw32配送的wch-link;
7、代码下载软件为pyocd;
8、调式工具为gdb。
本次开发板的编译环境、工具均采用开源工具。
【操作系统】
本工程的主控,作者移植了rtt-thread nano 3.15版本。rtt作为一款国产开源免费的操作系统可以提供强大的功能,为cw32的性能发挥提供强力的支持。
【程序流程图】
1、主机端由rtt开启两个主要任务,用于数据显示与巡检,同时利用串口中断来实时处理接收的数据。gtim定时开启pwm任务,来驱动开发板板载的beep。流程图如下:
2、无线终端采用单线流程,主要是采集数据后进入休眠,做到极简才能实现最好的功耗控制。流程图如下:
【原理图】
1、无线端终采集:
2、主机端:
【程序设计】
一、无线采集端
1.iic初始化,采用模拟i2c主要代码是对
二、主机端
1.主机端我们处理数据的核心为sht30数据,声明结构体如下:
typedef struct _sht30_data
{
uint32_t id;int temp; //温度值int temp_upper_limit; //温度值上限int temp_lower_limit; //温度值下限uint16_t humi; //湿度uint16_t humi_upper_limit; //湿度上限uint16_t humi_lower_limit; //湿度上限uint32_t time_tick; //更新数据计时enum _sht30_errcode sht_errcode;} sht30_infor;
主要用于存储数据的核心,以后所有的任务都是针对这个模块进行。
2.同时声明一个枚举,来确定测量点的状态:
enum _sht30_errcode{
normal=0,abnormal,offline,};
3.先约定好默的一些参数,最大传感器个数,温湿度报警上下限,巡检次数初值:
#define maxid 2
#define maxtime 300
#define humi_lower 500
#define humi_upper 750
#define tmpe_lower 100
#define tmpe_upper 300
到此我们的数据结构设计完成。
4.时钟的初始化,由于主机端需要高速处理数据这里配置为64mhz:
void rcc_cofiguration(void)
{
rcc_hsi_enable(rcc_hsiosc_div6);// 使能pll,通过hsi倍频到 64mhzrcc_pll_enable(rcc_pllsource_hsi, 8000000, 8); //hsi 默输出8mhz///< 当使用的时钟源hclk大于24m,小于等于48mhz:设置flash 读等待周期为2 cycle/// > pow2_table[cw_sysctrl- >cr0_f.hclkprs];pclk_freq > >= pow2_table[cw_sysctrl- >cr0_f.pclkprs];// 调试串口使用uart3// pa8- >tx// pa9< -rx// 时钟使能rcc_ahbperiphclk_enable(e31_uart_gpio_clk, enable);e31_uart_apbclkenx(e31_uart_clk, enable);// 先设置uart tx rx 复用,后设置gpio的属性,避免口线上出现毛刺e31_uart_aftx;e31_uart_afrx;gpio_initstructure.pins = e31_uart_tx_gpio_pin;gpio_initstructure.mode = gpio_mode_output_pp;gpio_init(e31_uart_tx_gpio_port, &gpio_initstructure);gpio_initstructure.pins = e31_uart_rx_gpio_pin;gpio_initstructure.mode = gpio_mode_input_pullup;gpio_init(e31_uart_rx_gpio_port, &gpio_initstructure); uart_initstructure.uart_baudrate = e31_uart_baudrate;uart_initstructure.uart_over = uart_over_16;uart_initstructure.uart_source = uart_source_pclk;uart_initstructure.uart_uclkfreq = pclk_freq;uart_initstructure.uart_startbit = uart_startbit_fe;uart_initstructure.uart_stopbits = uart_stopbits_1;uart_initstructure.uart_parity = uart_parity_no ;uart_initstructure.uart_hardwareflowcontrol = uart_hardwareflowcontrol_none;uart_initstructure.uart_mode = uart_mode_rx | uart_mode_tx;uart_init(e31_uartx, &uart_initstructure); //优先级,无优先级分组nvic_setpriority(e31_uart_irq, 0);//uartx中断使能nvic_enableirq(e31_uart_irq);}
同时配置中断函数,主要功能是判断是否接到了帧属,如果接收到帧尾则把数据交给回调函数进行处理,代码如下:
void uart1_uart4_irqhandler(void)
{
/* user code begin */uint8_t txrxbuffer;if(uart_getitstatus(cw_uart1, uart_it_rc) != reset){ txrxbuffer = uart_receivedata_8bit(cw_uart1); if(e31_rx_cnt < e31_rx_maxlen) { if ((txrxbuffer == 0x0a) && (e31_rx_state == 1)) { e31_rx_state = 2; e31_exp_data(); } else if ((txrxbuffer == 0x0d) && (e31_rx_state == 0)) { e31_rx_state = 1; } else if (e31_rx_state == 0) { e31_rx_buff[e31_rx_cnt] = txrxbuffer; e31_rx_cnt ++; } } else { e31_rx_cnt = 0; e31_rx_state = 0; } uart_clearitpendingbit(cw_uart1, uart_it_rc);}/* user code end */}
同时回调函数,为处理与解析数据更新到sht30数据之中:
void e31_exp_data(void)
{
int temp;uint16_t humi;uint32_t id;if(e31_rx_state == 2){ if(e31_rx_cnt == 14) { temp = e31_rx_buff[10]< <8 | e31_rx_buff[11]; humi = e31_rx_buff[12]< <8 | e31_rx_buff[14]; id = e31_rx_buff[6]< <24 | e31_rx_buff[7]< <16 | e31_rx_buff[8]< <8 | e31_rx_buff[9]; updata_sht30(temp, humi, id); rt_kprintf(id:%x, temp:%d, humi:%d\\r\\n, id, temp, humi); }}e31_rx_cnt = 0;e31_rx_state = 0;}
6.st7735的驱动,驱动采集模拟spi进行驱动,详细的驱动见工程源码包。
7.pwm驱动,pwm选用pa6为pwm输出端,初始化为1khz的输出来驱动板载的蜂鸣器。在初始化驱动后,我们装载最大的装截时,占空比为100%,使得蜂鸣器停止,在后面的需要输入报警声后,调整为50%的占空比,来实现蜂鸣器的报警声:
void init_beep(void)
{
gtim_inittypedef gtim_initstruct = {0};__rcc_gtim1_clk_enable(); // gtim2时钟使能/* pa6 pwm 输出 */__rcc_gpioa_clk_enable();pa06_afx_gtim1ch1();pa06_dir_output();pa06_digtal_enable(); gtim_initstruct.mode = gtim_mode_time;gtim_initstruct.oneshotmode = gtim_count_continue;gtim_initstruct.prescaler = gtim_prescaler_div2;// gtim_initstruct.reloadvalue = 60100ul - 1; // pwm频率为 48m/60100=800hz, spwm周期 = 800/2/1000= 0.4hzgtim_initstruct.reloadvalue = 32000ul - 1; // pwm频率为 64m/2/64000=1000hz, spwm周期 = 800/2/1000= 0.4hzgtim_initstruct.toggleoutstate = disable;gtim_timebaseinit(cw_gtim1, >im_initstruct);gtim_ocinit(cw_gtim1, gtim_channel1, gtim_oc_output_pwm_high);gtim_setcompare1(cw_gtim1, 32000-1);gtim_cmd(cw_gtim1, enable);}
void alarm_on(void)
{
gtim_setcompare1(cw_gtim1, 16000-1);;}
void alarm_off(void)
{
gtim_setcompare1(cw_gtim1, 32000-1);}
8.按照程序流程图,我们创建了两个任务,一个为巡检任务来实现对传感器模块的数据监控,并实理更新工作状态,代码如下:
/* 巡检任务 */
void thread_sht30_check_entry(void *parameter)
{
int i;uint8_t alarm_sta;while(1){ alarm_sta = 0; for(i=0; i< maxid; i++) { if(sht30[i].time_tick == 0) { //发送离线的警告 sht30[i].sht_errcode = offline; sht30[i].temp = 0; sht30[i].humi = 0; alarm_sta ++; } else if (sht30[i].temp sht30[i].temp_upper_limit \\ || sht30[i].humi sht30[i].humi_upper_limit ) { sht30[i].sht_errcode = abnormal; sht30[i].time_tick--; alarm_sta++; } else { sht30[i].sht_errcode = normal; sht30[i].time_tick--; } } if(alarm_sta > 0) { alarm_on(); } else { alarm_off(); } rt_thread_mdelay(500);}}
/* 巡检任务 */
void sht30_check(void)
{
rt_thread_init(&tid_check_sht30, sht30_check, thread_sht30_check_entry, rt_null, &thread_sht30_check_stack[0], sizeof(thread_sht30_check_stack), thread_priority - 1, thread_timeslice);rt_thread_startup(&tid_check_sht30);}
9.显示任务,为定时按照传感器的工作状态来实现数据的展示,主要是根据三个状态、以及温湿度是否超过或者低于限值来显示不同的颜色,代码如下:
/* 线程 显示 的入口函数 */
static void thread_lcd_entry(void *parameter)
{
sht30_data_init();char buff_temp[15];char buff_humi[15];uint16_t temp_background_color, temp_font_color;uint16_t humi_background_color, humi_font_color;int y_offset = 0;int i = 0;while (1){ y_offset = 46; for(i=0;i< maxid;i++) { rt_kprintf(sensorid:%d stata: %d, i+1, sht30[i].sht_errcode); y_offset = y_offset + i*70; sprintf(buff_temp,%d%d.%d,sht30[i].temp/100, sht30[i].temp/10%10, sht30[i].temp%10); sprintf(buff_humi,%d%d.%d,sht30[i].humi/100, sht30[i].humi/10%10, sht30[i].humi%10); switch (sht30[i].sht_errcode) { case normal: temp_background_color = gray0; temp_font_color = blue; humi_background_color = gray0; humi_font_color = blue; break; case offline: temp_background_color = gray2; temp_font_color = blue; humi_background_color = gray2; humi_font_color = blue; sprintf(buff_temp, ); sprintf(buff_humi, ); break; case abnormal: if(sht30[i].humi sht30[i].humi_upper_limit) { humi_background_color = yellow; humi_font_color = black; } else { humi_background_color = gray0; humi_font_color = blue; } if(sht30[i].temp sht30[i].temp_upper_limit) { temp_background_color = yellow; temp_font_color = black; } else { temp_background_color = gray0; temp_font_color = blue; } break; default: break; } gui_drawfont_gbk16(90,y_offset,temp_font_color,temp_background_color,buff_temp); //更新显示 gui_drawfont_gbk16(90,y_offset+20,humi_font_color,humi_background_color,buff_humi); } rt_thread_mdelay(10000);}}
/* 显示任务 */
void lcd_show(void)
{
rt_thread_init(&tid_show_sht30, lcd show, thread_lcd_entry, rt_null, &thread_lcd_show_stack[0], sizeof(thread_lcd_show_stack), thread_priority - 1, thread_timeslice);rt_thread_startup(&tid_show_sht30);}
【工程效果】
1、无线数据采集端能实现的采集数据,并按照设定的时间实现超远距离、超低功耗的长时间运行,经测量功耗情况如下:
从上面的数据我们可以看出,待机电流为7.5微安左右,在每两分钟启用一次数据上报,最在工作电流为46.5ma,平均电流为110ua,平均功率为362微瓦。可以推算一下,1000mah的电池可以持续供电100天左右。如果我们采用在温湿度正常的范围内缓存,每一个小时做一次数据上传,那么预计可以延长30倍的工作时间,那就是10年左右的待机。
2、主机端,我们可以实时的监控无线数据采集工作站的实现状况。
离线的警示:
温度异常:
【项目总结】
经过半个月的项目开发,主要实现了rt-thread nano移植,温湿度计、无线串口模块、lcd屏的驱动。实现了一套温湿度监测系统的基本功能。
【项目拓展计划】
下一步,将继续完善监控系统。
1、进行数据储存。
2、数据的历史数据查看。
3、连接互联网,把数据分发给服务器。
电梯物联网技术到底有什么优势呢?
海信推出黑钢453L冰箱 目前澳大利亚市场上最节能的冰箱
物联网正在推动电力行业达到新的效率、测试策略和创新水平
一文了解STM32启动过程
盘点凯翼X3的icar智能互联系统四大看点
CW32L083智能温湿度监控系统
LED显示屏逐渐进入许多新的市场应用领域
TÜV莱茵举办线上研讨会,探讨欧盟车辆设计与回收新要求
科普:你用的手机上都用到了什么通信调制技术
谷歌推出免费Android服务,面向听力残障人士,支持超过70种语言
BLDC的无感控制方法
拍照不够强没关系,华为荣耀8 pro用VR征服消费者
基于LC709204F的智能锂电池电量计
尴尬!小米6贴膜曝光,撞脸华为P10,开孔极为相似
销量规模再上新台阶!广汽公布三季度业绩报告
威力WL-18A-E3,WL-20A_E3,WL-18A-k
CR6267SH是否可替换XXX6255FS 两者对比为你揭晓
微机综合保护装置及电力监控系统在某公路配电工程的应用
人工智能能完美融入到智能家居中吗
苹果芯片订单将继续交付给台积电