目录
项目背景:
分类:实验室项目
此项目是本实验室与酒厂的一项科研合作项目,目的是研制一套可以实时采集酒厂温湿度、光照度的自动化嵌入式设备,并将采集到的数据信息远程传
输到监管单位端,并通过上位机实时图形界面显示其一段时间内的温湿度、光照度的变化情况,为酒厂的安全生产提供外围保障。
项目准备:
1.所需知识点
(1)硬件电路设计
(2)STM32单片机的使用
(3)MODBUS通讯协议的熟练使用
(4)python界面的实现
(5)后端数据库的搭建
2.项目分工
因为我的方向是搞嵌入式的,对于前端和后端不是很了解,所以我只是负责数据采集与无线发送这一部分的工作,上位机搭建与数据库编写由另外两位
同学负责。因此,本次项目记录,我也只记录我在做项目嵌入式部分遇到的困难与 解决办法。
3.涉及知识点归纳
4.项目耗材
stm32zet6核心板一块、modbus 485协议的温湿度 光照度集成的传感器一个、lora模块一对、电源管理模块、5V-15V升压模块一个、锂电池 、RS232转
USB串口。
项目过程:
项目思路整理:
因为本项目中只涉及一个传感器,基于modbus通讯协议的要求,所以不用考虑对传感器进行地址设置的问题,通过传感器厂家赠送的软件,可以设置此
传感器的地址为0x01、波特率为4800;
如上图所示,是我们此次项目所选用的传感器,它的一些参数如下图,这也是 编程中所需要用到的重要参数;
温湿度问询帧
地址码 | 功能码 | 起始地址 | 数据长度 | 校验码低位 | 校验码高位 |
0x01 | 0x03 | 0x00 0x00 | 0x00 0x02 | 0xC4 | 0x0B |
应答帧(例如读到温度为-10.1℃,湿度为65.8%RH)
地址码 | 功能码 | 有效字节数 | 湿度值 | 温度值 | 校验码低位 | 校验码高位 |
0x01 | 0x03 | 0x04 | 0x02 0x92 | 0xFF 0x9B | 0x5A | 0x3D |
光照度问询帧
地址码 | 功能码 | 起始地址 | 数据长度 | 校验码低位 | 校验码高位 |
0x01 | 0x03 | 0x00 0x06 | 0x00 0x01 | 0x64 | 0x0B |
应答帧(例如读到光照度为30000 Lux)
地址码 | 功能码 | 返回有效字节数 | 数据区 | 校验码低位 | 校验码高位 |
0x01 | 0x03 | 0x02 | 0x05 0x30 | 0xBB | 0x00 |
代码编写:
int main(void)
{
delay_init(); //延时函数初始化
MD_Init();
LED_Init();
uart_init(115200);
USART4_Config(); //初始化USART4
delay_ms(1000);
IWDG_Init(7,625); //看门狗初始化
time_XM=0;
while(1)
{
delay_ms(75); //此函数设计的延时函数共计3S发送一次哦
ReadTemperatureHumidityIllumination(&t,&h,&i); //温湿度、光照度读取函数;
delay_ms(100);
temp_t = (float)t*0.1; //得到的温度为实际值的十倍,利用除法太费时间
temp_h = (float)h*0.1;
temp_i = (float)i;
if(i<100 && h!=0)
{
time_XM = time_XM + 1;
if(time_XM==3)
{
for(j=600;j>0;j=j-1)//此处函数段为低功耗处理部分;当检测到为晚上时,十分钟发
送一次
{
delay_ms(499);
IWDG_Feed(); //喂狗
}
time_XM=0;
}
}
else
delay_ms(800);
MD0=0;
MD1=0;
delay_ms(150);
printf("%3.2f %3.2f %3.2f\r\n",temp_t,temp_h,temp_i);
delay_ms(200);
MD0=1;
MD1=1;
IWDG_Feed();
}
}
主函数段解释:包含温湿度、光照度读取函数,和串口打印函数、和一部分低功耗函数优化;
void UART4_IRQHandler(void) //中断接收函数
{
u8 rec_data;
if(USART_GetITStatus(UART4, USART_IT_RXNE) == SET)
{
switch(read_state)
{
case 1:
rec_data =(u8)USART_ReceiveData(UART4);
if(rec_data==0x01) //如上表所示,接收的第一字节为01
{
buffer_h_t_result[0]=rec_data;
byte_count_485=1; //代表接收到一个正确字符
read_state=2;
}
else
{
byte_count_485=0;
read_state=0;
}
break;
case 2:
rec_data =(u8)USART_ReceiveData(UART4);
if(rec_data==0x03)
{
buffer_h_t_result[1]=rec_data;
byte_count_485++;
read_state=3;
}
else
{
byte_count_485=0;
read_state=0;
}
break;
case 3:
rec_data =(u8)USART_ReceiveData(UART4);
if(rec_data==0x04)
{
buffer_h_t_result[2]=rec_data;
byte_count_485++;
read_state=4;
}
else
{
byte_count_485=0;
read_state=0;
}
break;
case 4:
case 5:
case 6:
case 7:
case 8:
case 9: -
rec_data =(u8)USART_ReceiveData(UART4);
buffer_h_t_result[byte_count_485]=rec_data;
byte_count_485++;
read_state++;
break;
上述程序段为中断接收函数节选,程序段为只检测接收字符的前三个字节,写法采用的是状态机的写法;
void ReadTemperatureHumidityIllumination(int* te_e,int* hu_y,int* il_n)
{
u8 BUFFER_H_T_COMMOND[8]={0x01,0x03,0x00,0x00,0x00,0x02,0xc4,0x0b};
u8 COMMOND_H_T_LEN=8;
delay_init();
read_state=1;
//*****************************准备接收**********************************
uart4_send_buff(BUFFER_H_T_COMMOND,COMMOND_H_T_LEN);
delay_ms(50);//Ö¡¼
while( read_state!=10 && read_state!=0)
{
delay_ms(20);
if(read_state==1)
{
uart4_send_buff(BUFFER_H_T_COMMOND,COMMOND_H_T_LEN);
}
else
{
}
break;
};
if(read_state==10)
{
read_state=0;
*hu_y=(buffer_h_t_result[3]<<8)|buffer_h_t_result[4];
*te_e=(buffer_h_t_result[5]<<8)|buffer_h_t_result[6];
}
else
{
*hu_y=0xffff;
*te_e=0xffff;
}
delay_ms(20);
上述程序为读取传感器温湿度的程序,里面有一个为传感器和单片机不同时上电的一个小处理;
电路连接思路
因为在疫情隔离期间,只有一张纸,哈哈哈发张草图纪念一下!
最终实物连接图
项目优化处理
时钟方面
STM32系统时钟树详细介绍了所涉及的5种时钟,有以下三种时钟可以作为系统时钟(SYSCLK):
- HSI 振荡器时钟
- HSE 振荡器时钟
- PLL 时钟
在system_stm32f10x.c中系统默认设置为72M时钟,涉及的函数为
从中可以看出就是 根据不同的宏来设置不同的系统时钟,这些宏就在跟此函数在同一个源文件里 。官方很是考虑周到,我们只需要选择相应宏就能达到快速配置系统时钟的目的。
为降低时钟带来的功耗我做了以下修改:
1.将系统时钟设为HSE,
1.将HSE时钟设置为默认的8M,(此函数在stm32f10x.h中)
2.在SetSysClockToHSE将AHB、APB2、APB1分频因子增大一倍
休眠模式设定
(1)LORA方面
LORA的MD0、MD1引脚为模式设置引脚
当设置MD0=0,MD1=0时LORA工作为半双工状态,此时工作电流较大为30mA;当设置MD0=1,MD1=1时LORA工作为休眠状态,此时工作电流仅为3.8uA。
因此在主函数中,我仅设置200ms时间长度让LORA处于工作状态,其余时间处于休眠模式。
(2)STM32F103方面
STM32F103内置了低功耗模式,手册已写明:
可以让32在特定时间处于待机模式,采用RTC实时时钟来唤醒它。我测试表明,待机模式下芯片工作电流可以降低一半。
项目中的困难及解决方案
个别数据打印不完整问题
分析应该是在优化系统功耗时,每3s采集一次数据,但是3s的周期内仅让lora工作200ms,所以可能出现200ms内数据还没有完全发出,导致接收模块出现数据不完整现象。
解决方案:增加lora半双工工作时间至350ms,能更大程度减少数据丢失问题。
lora接收模块接收到的数据偶尔会出现乱码问题,导致上位机端解析错误至系统崩溃。
问题分析,数据采集是通过发送问询码并接受回执码这样一个过程,在接收回执码的过程中回执码的前三位是固定的,所以只要是回执码前三位判断正确则理论上接收数据正确,推断乱码情况是由于16进制回执码在转换为10进制的过程中出现的错误。
解决方案:将接收到的回执码判断后解析出对应位的16进制温湿度数据,直接将16进制数据发送,进制转换的过程移至上位机端。