FastBond3挑战部分 - 基于STM32H5的远程温湿度监测设计
该项目使用了KiCad软件、C语言、HMI显示界面,实现了温湿度的数据采集以及显示报警的设计,它的主要功能为:采集当前的温度、湿度的数据值,在复杂的工业环境下稳定运行实现温湿度数据的采集以及远程通信的功能。。
标签
嵌入式系统
STM32
温湿度
申小林
更新2024-09-05
西南科技大学
11942

基于STM32H5的远程温湿度监测设计


 

1 创意方向

目前工业4.0以及中国工业2025的时代任务已经接近尾声,工业4.0主要是实现工业的智能化、数字化、实现工业产值的可监控,产品历史可追溯,而工业4.0的基础就是以各种传感器为最底层的数字化转换单元,将原有的离散量、模拟量转换为可以监控、可存储的数据类型,数字传感器奠定了工业4.0的数字化基础。

工业温湿度传感器在工业4.0的推进过程中起到了关键的作用,对于产品生产环境温度的监测起到了致关重要的作用,我们本次的创意是基于STM32H5的工业温湿度传感器,完成工厂的环境温度监测、实时显示、远程终端的数据读取和显示。

2 创意方案

2.1 硬件设计框图

整体的方案框图如下,我们在后面组详细的介绍。


整个设计框图如上述,包含电源部分、核心处理器最小系统单元、传感器、存储模块、声光报警单元、远程通信接口等基础电路组成。

电源方面的设计采用宽电压设计,适用于12V、24V的标准工业低压标准的工作电压,提高了传感器工作电压的适应性。系统包含声光报警单元,可以有效的对现有的状态进行指示,并且有效的提示工作人员当前的一个温度情况,同时也可以根据这个信号实现空调、通风系统的系统联动方案。液晶指示单元可以显示当前的温度值、湿度值、以及建议的工厂温湿度工作环境数值。远程通信单元主要是针对有远程通信数据要求的客户,保证数字化转型的数据共享功能,实现数据的传输的存储,上位机单元将显示当前的数据,并且将数据做存储,方便查询历史数据以及历史曲线,方便后期做智能化的处理提供有效的数据基础。

2.2 软件设计流程图

软件的流程相对比较复杂,这里将从整体到细节的方向进行说明。

 

整体处理软件流程图

 

整体的流程图相对比较简单,在MCU的处理过程中,都是按照流水线的处理流程来完成,我们首先完成系统的初始化任务,对芯片的内存、FLASH的空间进行分配,初始化管脚的功能,完成接口基础信息的设置,保证系统的稳定运行,然后完成温室度的采集工作以及通信数据处理的工作,如此循环往复,实时更新采集的数据值,并且根据采集到的数据对数据进行显示,如果有超出范围的话可以根据实际情况进行报警动作。

报警动作流程图

报警流程主要是为了告知工厂的工作人员当前的环境指标超标,并提醒他们进行及时的调节整改。报警处理流程设置了两个工作定值,一个是温度定值,一个是时间定值,只有超过温度并且持续超过一短时间之后,才会有报警动作,避免了由于电器干扰、数据跳变引起的短暂的数值超标的现象,可以有效的避免干扰,完成准确的报警动作。

3 方案器件介绍

3.1 核心处理器STM32H563

STM32H563是一款基于32ARM® Cortex®-M33内核的高性能微控制器,属于STM32H5系列,专为高性能嵌入式应用设计。采用ARM® Cortex®-M33内核,工作频率高达250MHz,能够快速处理各种复杂的嵌入式控制任务。250MHz频率下,从Flash存储器执行时,STM32H563能够提供高达375 DMIPS/1023 CoreMark的性能。STM32H563配备了多种通信外设,包括UARTSPII2CI3CADCDAC等,方便与外部设备进行通信和控制,多达34个通信外设,如USB 2.0全速主机和从机、以太网MAC、相机接口等,满足多样化的应用需求。

 

3.2 温湿度传感器SHTC3

SHTC3是业内知名的Sensirion公司推出的新一代数字温湿度传感器,它传承了盛思锐湿度和温度传感器在业界有口皆碑的质量和可靠性。

高精度:SHTC3具备顶尖的测量精度,湿度测量精度可达±2%相对湿度,温度测量精度可达±0.2℃。

宽测量范围:可以测量0100%的相对湿度以及-40℃至125℃的温度,满足多种应用场景的需求。

宽电源电压范围:支持3.3V5V的宽电源电压,提供了更大的灵活性。

低功耗:在低功耗模式下,功耗低于0.15mA,非常适合由电池供电的移动或无线应用。

快速响应:响应时间仅为8秒(tau63%),能够迅速反映环境变化。

小体积:模块尺寸仅为14*17mm,便于集成到各种设备中。

4 原理图说明

4.1电源设计

电源部分使用了DCDC+LDO的经典电源搭配架构,电源设计上包含了防反接保护、过流保护、过压保护、LDO断=端输出还有电源指示灯,保证电源的正确指示。LDO的纹波较小,可以保证MCU的稳定运行。

4.2 最小系统设计

STM32H563的最小系统相对还是比较简单,配备了25MHz的无源晶振,同时还带有商店复位电路、SWD下载接口、LED指示灯,在保证系统稳定运行的同时通过指示灯表明灯光的状态。每个电源的旁路引脚都配有104 的旁路滤波电容。

4.3通信部分设计

通信部分主要是有两个接口,一个是RS485接口,一个是CAN接口,RS485接口使用了自首发电路,节约一个方向控制引脚,CAN总线主要是为了长距离通信的一个应用,CAN总线最长可以到10KM的通信距离。

4.4 采集部分说明

作品使用的事SHTC3进行的温湿度的采集工作,通信引脚都配了22R的限流电阻,并且配有4.7K的上拉电阻,保证整个通信线路的稳定性

5 源代码功能说明

代码部分相对还是比较复杂,这里讲通过采集部分、通信部分、数据结构规划三个方面进行说明,并针对核心代码进行分析。

5.1 温湿度采集

SHTC3的温湿度采集代码是直接借用的官方的代码,但是我们在使用的时候是使用IO管教模拟IIC接口进行通信,通过逻辑分析仪调节实际的通信速率。


//------------------------------------------------------------------------------
etError SHTC3_GetTempAndHumi(float *temp, float *humi)
{
etError error; // error code
uint16_t rawValueTemp; // temperature raw value from sensor
uint16_t rawValueHumi; // humidity raw value from sensor

error = SHTC3_StartWriteAccess();

// measure, read temperature first, clock streching enabled
error |= SHTC3_WriteCommand(MEAS_T_RH_CLOCKSTR);

// if no error, read temperature and humidity raw values
if(error == NO_ERROR)
{
error |= SHTC3_StartReadAccess();
error |= SHTC3_Read2BytesAndCrc(&rawValueTemp);
error |= SHTC3_Read2BytesAndCrc(&rawValueHumi);
}

SHTC3_StopAccess();

// if no error, calculate temperature in 癈 and humidity in %RH
if(error == NO_ERROR) {
*temp = SHTC3_CalcTemperature(rawValueTemp);
*humi = SHTC3_CalcHumidity(rawValueHumi);
}

return error;
}

//------------------------------------------------------------------------------
etError SHTC3_GetTempAndHumiPolling(float *temp, float *humi)
{
etError error; // error code
uint8_t maxPolling = 20; // max. retries to read the measurement (polling)
uint16_t rawValueTemp; // temperature raw value from sensor
uint16_t rawValueHumi; // humidity raw value from sensor

error = SHTC3_StartWriteAccess();

// measure, read temperature first, clock streching disabled (polling)
error |= SHTC3_WriteCommand(MEAS_T_RH_POLLING);

// if no error, ...
if(error == NO_ERROR)
{
// poll every 1ms for measurement ready
while(maxPolling--)
{
// check if the measurement has finished
error = SHTC3_StartReadAccess();

// if measurement has finished -> exit loop
if(error == NO_ERROR) break;

// delay 1ms
DelayUs(1000);
}

// if no error, read temperature and humidity raw values
if(error == NO_ERROR)
{
error |= SHTC3_Read2BytesAndCrc(&rawValueTemp);
error |= SHTC3_Read2BytesAndCrc(&rawValueHumi);
}
}

SHTC3_StopAccess();

// if no error, calculate temperature in 癈 and humidity in %RH
if(error == NO_ERROR)
{
*temp = SHTC3_CalcTemperature(rawValueTemp);
*humi = SHTC3_CalcHumidity(rawValueHumi);
}

return error;
}

//------------------------------------------------------------------------------
etError SHTC3_GetId(uint16_t *id)
{
etError error; // error code

error = SHTC3_StartWriteAccess();

// write ID read command
error |= SHTC3_WriteCommand(READ_ID);

// if no error, read ID
if(error == NO_ERROR) {
SHTC3_StartReadAccess();
error = SHTC3_Read2BytesAndCrc(id);
}

SHTC3_StopAccess();

return error;
}

//------------------------------------------------------------------------------
etError SHTC3_Sleep(void)
{
etError error = SHTC3_StartWriteAccess();

if(error == NO_ERROR) {
error |= SHTC3_WriteCommand(SLEEP);
}

SHTC3_StopAccess();

return error;
}

//------------------------------------------------------------------------------
etError SHTC3_Wakeup(void)
{
etError error = SHTC3_StartWriteAccess();

if(error == NO_ERROR)
{
error |= SHTC3_WriteCommand(WAKEUP);
}

SHTC3_StopAccess();

DelayUs(100); // wait 100 us

return error;
}

//------------------------------------------------------------------------------
etError SHTC3_SoftReset(void)
{
etError error; // error code

error = SHTC3_StartWriteAccess();

// write reset command
error |= SHTC3_WriteCommand(SOFT_RESET);

SHTC3_StopAccess();
return error;
}

//------------------------------------------------------------------------------
etError SHTC3_StartWriteAccess(void)
{
etError error; // error code

// write a start condition
I2c_StartCondition();

// write the sensor I2C address with the write flag
error = I2c_WriteByte(SHTC3_Addr << 1);

return error;
}

//------------------------------------------------------------------------------
etError SHTC3_StartReadAccess(void)
{
etError error; // error code

// write a start condition
I2c_StartCondition();

// write the sensor I2C address with the read flag
error = I2c_WriteByte((SHTC3_Addr << 1) | 0x01);

return error;
}

//------------------------------------------------------------------------------
void SHTC3_StopAccess(void)
{
// write a stop condition
I2c_StopCondition();
}

//------------------------------------------------------------------------------
static etError SHTC3_WriteCommand(etCommands cmd)
{
etError error; // error code

// write the upper 8 bits of the command to the sensor
error = I2c_WriteByte(cmd >> 8);

// write the lower 8 bits of the command to the sensor
error |= I2c_WriteByte(cmd & 0xFF);

return error;
}

//------------------------------------------------------------------------------
static etError SHTC3_Read2BytesAndCrc(uint16_t *data)
{
etError error; // error code
uint8_t bytes[2]; // read data array
uint8_t checksum; // checksum byte

// read two data bytes and one checksum byte
bytes[0] = I2c_ReadByte(ACK);
bytes[1] = I2c_ReadByte(ACK);
checksum = I2c_ReadByte(ACK);

// verify checksum
error = SHTC3_CheckCrc(bytes, 2, checksum);

// combine the two bytes to a 16-bit value
*data = (bytes[0] << 8) | bytes[1];

return error;
}

//------------------------------------------------------------------------------
static etError SHTC3_CheckCrc(uint8_t data[], uint8_t nbrOfBytes,uint8_t checksum)
{
uint8_t bit; // bit mask
uint8_t crc = 0xFF; // calculated checksum
uint8_t byteCtr; // byte counter

// calculates 8-Bit checksum with given polynomial
for(byteCtr = 0; byteCtr < nbrOfBytes; byteCtr++)
{
crc ^= (data[byteCtr]);
for(bit = 8; bit > 0; --bit)
{
if(crc & 0x80) {
crc = (crc << 1) ^ CRC_POLYNOMIAL;
} else {
crc = (crc << 1);
}
}
}

// verify checksum
if(crc != checksum) {
return CHECKSUM_ERROR;
} else {
return NO_ERROR;
}
}

//------------------------------------------------------------------------------
static float SHTC3_CalcTemperature(uint16_t rawValue)
{
return 175 * (float)rawValue / 65536.0f - 45.0f;
}

//------------------------------------------------------------------------------
static float SHTC3_CalcHumidity(uint16_t rawValue)
{
// calculate relative humidity [%RH]
// RH = rawValue / 2^16 * 100
return 100 * (float)rawValue / 65536.0f;
}

RTU通信的代码比较复杂,这里只展示部分代码处理过程,更加详细的可以参考FreeModbus的源码,



//=================================================================================
/*-----03-读多个寄存器 ---------------------------------------------------------*/
unsigned short ReadMultReg_03(unsigned char *Buffer,unsigned short StartAddr,unsigned short Length)//--读取函数 :数据存储介质-- 起始地址 ------ 以及数量--
{
unsigned short i=0;
CopyBoard CopyData; //中间变量存储--
CopyData.DataByteNum=Length*2;//--读取字节变量的数量--由于读取寄存器是16位的,而这里是按照字节处理的-所以要*2
CopyData.ReturnDataLength=Length*2;//--返回数据的长度----
CopyData.StartBytePosition=StartAddr;//--起始地址--
//--DataAddr=(unsigned char *)&AI_AO_Data[CopyData.StartBytePosition];
//--开始拷贝数据----
for (i=0;i<Length;i++)
{//--
Buffer[2*i]=((SysData.Datashort[i+StartAddr]>>8)&0xff);//--复制数据--
Buffer[2*i+1]=(SysData.Datashort[i+StartAddr]&0xff);
}
return CopyData.ReturnDataLength;//--返回拷贝的字节数量----
}
//=================================================================================
/*-----04-读输入寄存器 --------------------------------------------------------*/
unsigned short ReadInputReg_04(unsigned char *Buffer,unsigned short StartAddr,unsigned short Length)
{
unsigned short i=0;
CopyBoard CopyData; //中间变量存储--
CopyData.DataByteNum=Length*2;//--读取字节变量的数量--由于读取寄存器是16位的,而这里是按照字节处理的-所以要*2
CopyData.ReturnDataLength=Length*2;//--返回数据的长度----
CopyData.StartBytePosition=StartAddr;//--起始地址--
// DataAddr=(unsigned char *)&AI_AO_Data[CopyData.StartBytePosition];
//--开始拷贝数据----
for (i=0;i<Length;i++)
{//--
Buffer[2*i]=(( SysData.Datashort[i+StartAddr]>>8)&0xff);//--复制数据--
Buffer[2*i+1]=(SysData.Datashort[i+StartAddr]&0xff);
}

return CopyData.ReturnDataLength;//--返回拷贝的字节数量----
}

//=================================================================================
//=================================================================================

/*-----06-写单个寄存器 ----------------------------------------------------------*/

unsigned short WriteSingelReg_06(unsigned char *Buffer,unsigned short StartAddr,unsigned short Length)

{

unsigned short i=0;

CopyBoard CopyData; //中间变量存储--

CopyData.DataByteNum=Length*2;//--读取字节变量的数量--由于读取寄存器是16位的,而这里是按照字节处理的-所以要*2

CopyData.ReturnDataLength=Length*2;//--返回数据的长度----

CopyData.StartBytePosition=StartAddr;//--起始地址--

// DataAddr=(unsigned char *)&AI_AO_Data[CopyData.StartBytePosition];

//--开始拷贝数据----

for (i=0;i<Length;i++)

{//--

SysData.DataChar[i+StartAddr*2]=Buffer[i+1];//--复制数据--

SysData.DataChar[i+StartAddr*2+1]=Buffer[i];//--复制数据--

}

CopyData.ReturnDataLength=0;

return CopyData.ReturnDataLength;//--返回拷贝的字节数量----

}

5.3 数据结构规划分析

整体的规划上,还是需要包含整个的数据结构的,保证系统对所有数据的更新一集通信接口对数据的掌握情况。

我们在数据结构的处理上都是使用了统一的结构体、共用体来处理数据一集保证数据的统一性的。具体可以参考下方的代码

typedef struct SetValue
{
unsigned short HardVersion_Big; //--硬件版本号
unsigned short HardVersion_Little;
unsigned short SoftVersion_Big; //--软件版本号--
unsigned short softVersion_Little;
unsigned short Flash_Update_Flag; //--Flash 写入标志--
unsigned short ReserveSet[25]; //--定值预留--
}SetValue;

typedef struct
{
float HumData; //-湿度
float TempData; //-温度
float HumSetData_H;
float HumSetData_L;
float TempSetData_H;
float TempSetData_L;
unsigned short TempTimeSet;
unsigned short TempDataCount;
unsigned short TempWearnCurrent;
unsigned short TempWearnFlag;
unsigned short HumTimeSet;
unsigned short HumDataCount;
unsigned short HumWearnCurrent;
unsigned short HumWearnFlag;
unsigned short SeracomGood;//--通信状态



unsigned short Reserved[30];
//===============
//--定值存放于第50-80需要修改定值的话就在这个区域设置---
SetValue SetVal;
//--80-100是存储型号的--
}DataStruct;

6 电脑上位机界面设计


在上位机的界面 处理上我们使用了台达的HMI上位机软件做模拟上位机软件,这样的话可以更加方便实现数值的实现以及变位信号的更新,初始的界面是这样的:

上位机界面


7 总结

温湿度传感器是很早就想做的一个项目,但是没有一个合适的契机去完成他,正好这次电子森林以及得捷联合组织的这个活动让我有了这个机会完成这个设计,并且也给与了物质和精神上的鼓励和支持,能够与大家一起学习探讨,一起进步。也同时希望电子森林越做越好,得捷生意兴隆,也祝愿大家能够保持自己对于电子这一爱好的坚持。






KiCad文件
使用说明
全屏
附件下载
申小林的源码-20240829.rar
软件源码
BOOM
物料清单
团队介绍
个人作品,不涉及到团队
评论
0 / 100
查看更多
硬禾服务号
关注最新动态
0512-67862536
info@eetree.cn
江苏省苏州市苏州工业园区新平街388号腾飞创新园A2幢815室
苏州硬禾信息科技有限公司
Copyright © 2024 苏州硬禾信息科技有限公司 All Rights Reserved 苏ICP备19040198号