1. 所选主题和项目介绍
1.1 项目背景
随着智能建筑技术的快速发展,中央空调系统作为现代建筑的核心设施,其智能化控制程度直接影响到建筑的能源效率和居住舒适度。传统的中央空调末端控制通常采用简单的开关式调节,无法实现精确的流量控制和温度调节,导致能源浪费和舒适度下降。
本项目基于STM32H503微控制器,设计了一套智能化的中央空调终端步进电机控制系统。该系统通过实时采集环境温度数据,结合多圈绝对角度传感器ADMT4000进行精确位置反馈,实现对中央空调终端开口的线性精确控制。系统采用温度-角度映射算法,将超温程度与步进电机转动角度进行线性对应,从而实现根据温度变化自动调节风口开度的功能。
1.2 项目目标
本项目的主要目标是设计并实现一套完整的中央空调终端控制系统,具体包括以下几个方面:
温度采集与监测:通过高精度的TSYS03数字温度传感器实时采集环境温度,精度达到±0.3℃,能够准确反映室内温度变化。温度数据每500毫秒更新一次,为控制系统提供可靠的输入信号。
位置精确控制:采用ADMT4000多圈绝对角度传感器,实现对步进电机转动角度的精确测量。该传感器最大可测量46圈(16560度),分辨率达到0.351度,完全满足中央空调终端3圈(1080度)行程的控制需求(本次的需求设定主要是用于展示,可以结合实际情况进行修改)。通过实时位置反馈,实现闭环控制,确保实际开度与目标开度一致。
自动调节功能:系统根据温度变化自动调节终端开口大小。当温度低于设定阈值时,终端完全关闭;当温度超过阈值时,终端开口根据超温程度线性开启,最大可开启至3圈行程。这种设计既保证了舒适度,又避免了过度制冷造成的能源浪费。
人机交互界面:采用1.54寸TFT液晶显示屏,提供直观的操作界面。系统设有显示页面和设置页面两个界面,显示页面实时展示温度、设定阈值、当前位置、目标位置、系统状态等关键信息;设置页面可进行传感器复位等操作。四键矩阵键盘用于系统启停、阈值调节、页面切换等操作。
1.3 项目意义
本项目的实施具有重要的实用价值和技术意义。首先,通过精确的温度-角度映射控制,实现了中央空调终端的连续可调,避免了传统开关式控制的温度波动问题,显著提升了室内舒适度。其次,系统采用闭环位置反馈控制,能够精确到达目标位置,避免了步进电机失步造成的定位误差,提高了控制可靠性。此外,系统设计考虑了多种异常情况的处理,如传感器故障、角度超限等,具有较高的安全性和可靠性。
2. 硬件介绍
2.1 主控芯片STM32H503
本项目选用STMicroelectronics公司的STM32H503RBT6作为主控芯片,这是ST公司推出的一款高性能ARM Cortex-M33内核的32位微控制器,具有丰富的外设资源和强大的运算能力。STM32H503RBT6的主要特性包括:工作频率高达250MHz,内置512KB Flash和128KB SRAM,支持丰富的外设接口,包括多个SPI、I2C、UART等通信接口,以及多达16个16位定时器和多个PWM输出通道。该芯片还集成了高精度ADC、DAC和比较器等模拟外设,能够满足本项目对温度采集、PWM输出和位置反馈等多种功能的需求。
在GPIO配置方面,本项目利用了STM32H503绘制的核心板的多个GPIO引脚,分别连接温度传感器(I2C接口)、角度传感器(SPI接口)、TFT显示屏(SPI接口)、步进电机驱动(PWM输出和GPIO控制)以及四键矩阵键盘(外部中断)。芯片的EXTI外部中断模块支持多个引脚的上升沿/下降沿触发,非常适合按键输入的实时响应。
2.2 温度传感器TSYS03
TSYS03是TE Connectivity公司生产的高精度数字温度传感器,采用I2C接口通信,体积小巧(2.5mm×2.5mm×0.9mm),非常适合空间受限的应用场景。
本项目中,TSYS03通过I2C1接口(PB6为SCL,PB7为SDA)与STM32H503连接,每500毫秒进行一次温度测量,温度值经过-2.0℃校准补偿后用于控制算法。
2.3 多圈绝对角度传感器ADMT4000
ADMT4000是本项目核心的传感器器件,用于测量步进电机的绝对转动位置。ADMT4000 是一种磁转数传感器,即使在设备断电时也能够记录磁系统的旋转次数。通电时可以查询该套件,以报告系统的绝对位置。绝对位置通过串行外设接口 (SPI) 报告。ADMT4000 最多可计数 46 圈外部磁场,以顺时针 (CW) 方向递增绝对位置计数。该套件包括三个磁传感器,一个用于计数系统旋转次数的巨磁电阻(GMR)转数计数传感器,一个 GMR 象限检测传感器和一个各向异性磁阻(AMR)角度传感器。AMR 角度传感器与 GMR 象限检测传感器结合使用,可确定系统在 360° 范围内的绝对位置。将 GMR 转数计数传感器输出与 AMR 角度传感器输出相结合,该套件就能以高角度精度报告系统的位置。
2.4 步进电机及驱动
本项目使用的步进电机是典型的两相四线步进电机,额定电压为4.1V,步距角为1.8度。步进电机的特点是每接收一个脉冲信号转动一个固定角度(整步模式)或其整数倍(细分模式),非常适合需要精确位置控制的场景。步进电机的驱动采用分立的半桥驱动电路,使用GPIO直接控制电机的使能(EN)和方向(DIR)信号,通过PWM信号(固定50%占空比)控制脉冲输入。这种设计的优势在于结构简单、成本低、易于调试,同时通过调节PWM频率可以控制电机转速。
传感器板置于步进电机的背面,如下图:
2.5 TFT液晶显示屏
显示模块采用1.54寸TFT彩色液晶显示屏,分辨率为240×240像素,采用SPI接口与主控芯片通信。
本项目中,TFT显示屏用于显示系统状态信息,包括温度、阈值、当前位置、目标位置、系统运行状态、ADMT4000传感器数据等。显示屏界面分为左右两个区域:左侧显示HVAC控制相关信息,右侧显示ADMT4000角度传感器数据。
交互板上有用户输入采用的四键矩阵键盘,包括K1、K2、K3、K4四个按键。这四个按键均连接到STM32H503的GPIO引脚,并配置为外部中断模式,实现按键的实时响应。
按键功能定义:
按键 | 物理位置 | 功能 |
K1 | SW1 | 系统启动/停止 / 返回显示页面 |
K2 | SW3(物理SW2) | 阈值+0.5℃ / ADMT4000复位 |
K3 | SW2(物理SW3) | 阈值-0.5℃ / 切换到设置页面 |
K4 | SW4 | 系统启停(备用) |
按键采用外部中断方式检测,具有200ms的软件去抖时间。通过在中断回调函数中设置标志位,然后在主循环中处理相关逻辑,实现了非阻塞的按键响应设计。
3. 方案框图和项目设计思路
3.1 系统总体架构
本系统采用分层模块化的设计思想,从整体上划分为四个主要层次:感知层、控制层、执行层和人机交互层。这种设计使得各层之间的接口清晰,便于独立开发和调试。
感知层负责采集系统运行所需的各类传感器数据,包括温度传感器TSYS03和角度传感器ADMT4000。温度传感器实时采集室内环境温度,为控制算法提供输入信号;角度传感器测量步进电机的当前绝对位置,构成闭环控制的位置反馈通道。
控制层是系统的核心,基于STM32H503微控制器运行温度-角度映射算法。该层根据温度偏差计算目标位置,与当前位置比较后输出控制指令。控制算法采用带滞回环的Bang-Bang控制策略,有效避免了执行器频繁动作造成的机械磨损。
执行层由步进电机及其驱动电路组成,接收控制层的PWM脉冲信号和方向控制信号,驱动步进电机转动到目标位置。电机轴与中央空调终端的调节阀连接,通过旋转改变开口大小。
人机交互层包括TFT显示屏和四键键盘,用户可以通过键盘设置温度阈值、启动/停止系统、切换显示页面等,显示屏实时反馈系统运行状态。
3.2 系统框图
3.3 温度-角度映射算法
本系统的核心控制算法是将温度偏差与步进电机目标位置建立线性映射关系。算法设计考虑了以下几个方面:
设定阈值:用户可通过键盘设置温度阈值(默认25℃),阈值范围限制在15℃至35℃之间,防止误操作。
超温计算:系统计算当前温度与设定阈值的差值(over_temp = current_temp - threshold)。
分段线性映射:
超温范围 | 电机目标位置 | 说明 |
over_temp ≤ 0℃ | stepper_closed_angle | 完全关闭 |
0℃ < over_temp < 5℃ | stepper_closed_angle + (over_temp/5)×1080° | 线性开启 |
over_temp ≥ 5℃ | stepper_closed_angle + 1080° | 完全开启(3圈) |
算法实现(Stepper_SetAngleFromTemp函数):
void Stepper_SetAngleFromTemp(float temp, float threshold)
{
if (!stepper_calibrated) return;
float over_temp = temp - threshold;
if (over_temp <= 0)
{
// 温度 <= 阈值:完全关闭
stepper_target_angle = stepper_closed_angle;
}
else if (over_temp >= 5.0f)
{
// 超温 >= 5°C:完全开启(3圈 = 1080度)
stepper_target_angle = stepper_closed_angle + STEPER_FULL_RANGE;
}
else
{
// 超温 0-5°C:线性插值
stepper_target_angle = stepper_closed_angle + (over_temp / 5.0f) * STEPER_FULL_RANGE;
}
}
3.4 滞回控制策略
为了防止步进电机在目标位置附近频繁启停造成的振动和机械磨损,系统采用了滞回(Hysteresis)控制策略。当电机接近目标位置时,系统不是立即停止电机,而是让电机继续运行直到进入一个较宽的"停止区"才关闭电机。当位置偏差再次增大到"重启阈值"时才重新启动电机。
参数设置:
参数 | 数值 | 说明 |
停止阈值 | 3° | 运行时,距离目标3度以内即停止 |
重启阈值 | 8° | 停止后,偏差超过8度才重新启动 |
实现逻辑(Stepper_Update函数):
// 滞回控制逻辑
if (stepper_reached)
{
// 电机已停止,检查是否需要重启
if (error > 8.0f || error < -8.0f)
{
// 偏差过大,需要重新启动
stepper_reached = 0;
}
else
{
// 在重启阈值内,保持停止
HAL_GPIO_WritePin(STEPER_ENABLE_PORT, STEPER_ENABLE_PIN, GPIO_PIN_SET);
Stepper_Stop();
return;
}
}
else
{
// 电机运行中,检查是否到达目标
if (error > -3.0f && error < 3.0f)
{
// 进入停止阈值,关闭电机
stepper_reached = 1;
HAL_GPIO_WritePin(STEPER_ENABLE_PORT, STEPER_ENABLE_PIN, GPIO_PIN_SET);
Stepper_Stop();
return;
}
}
这种滞回控制策略有效减少了电机在稳态时的启停次数,延长了电机和机械结构的使用寿命。
3.5 角度安全范围保护
ADMT4000传感器的测量范围是0至16560度,而步进电机的行程设计为3圈(1080度)。为了防止机械结构过载或传感器故障导致的问题,系统设置了角度安全范围保护。
最小安全角度:1000度(留有约28度的余量)
最大安全角度:16560度(ADMT4000的物理极限)
故障判定条件:
- 初始校准时,如果ADMT4000读数不在1000-16560度范围内,判定为传感器故障
- 运行过程中,如果实时角度超出1000-16560度范围,判定为角度异常
故障处理:
- 设置stepper_error标志
- 立即停止步进电机
- 在显示屏上显示"ERR"错误提示
- 系统保持停止状态,需要复位才能恢复
4. 原理图和PCB设计
我们本次进行系统设计用到的模块都是自行设计的(除了本次的ADMT4000传感器模块)。
主控板:
原理图:

PCB图:

交互板:
原理图:

PCB:

温度采集板:
原理图:

PCB:

最后的实物连接效果:
5. 软件设计流程
系统上电后,首先进行外设初始化,包括GPIO配置、SPI初始化、I2C初始化、定时器配置等。随后依次初始化温度传感器TSYS03和角度传感器ADMT4000。
初始化阶段完成后,系统进入主循环。主循环采用基于时间片的轮询方式,每100毫秒读取一次ADMT4000角度数据,每500毫秒读取一次温度数据并更新显示。这种设计避免了CPU资源浪费,同时保证了系统的实时性。
主程序流程图:
ADMT4000驱动
ADMT4000驱动负责SPI通信和角度数据解析。驱动实现了初始化、寄存器读取、角度计算等功能。本项目中,ADMT4000通过SPI2接口与STM32H503连接,具体接线为:PB12为CS片选信号,PB13为SCK时钟信号,PB14为MISO数据输出信号,PB15为主控数据输出(虽然本项目仅读取数据)。此外,传感器还包含ADMT_RST复位引脚(PC6)、ADMT_RS复位信号引脚(PC4)和ADMT_SHDN掉电控制引脚(PB0)。
ADMT4000数据协议解析:
绝对角度数据的读取涉及复杂的协议处理。通过分析 datasheet 和实际测试,ABSANGLE寄存器的数据格式如下:
数据位 | 说明 |
Bit[9:0] | 单圈角度原始值,分辨率0.351° |
Bit[15:10] | 整圈数(6位),最大46圈 |
Bit[7:5] | 状态标志位 |
Bit[4] | 角度极性(正/负) |
// ADMT4000寄存器定义
#define ADMT4000_REG_CNVPAGE 0x01
#define ADMT4000_REG_ABSANGLE 0x03
#define ADMT4000_REG_DIGIO 0x04
#define ADMT4000_REG_ANGLE 0x05
#define ADMT4000_REG_FAULT 0x06
// 全局变量
float ANGLE_data = 0; // 单圈角度 (0-360°)
float ABSANGLE_data = 0; // 绝对角度 (0-16560°)
uint8_t TurnCnt = 0; // 整圈计数
// CRC校验计算
void admt4000_compute_crc(uint8_t reg_addr, uint16_t reg_data, uint8_t excess,
uint8_t *crc_ret, uint8_t is_write)
{
int crc[] = {1, 1, 1, 1, 1};
int i, xor;
uint32_t data_in;
// 构建输入数据
if (is_write) {
data_in = ((reg_addr << 16) | reg_data) << 3;
} else {
data_in = ((reg_addr << 16) | reg_data) << 3 | excess;
}
// 计算CRC
for (i = 25; i >= 0; i--) {
xor = ((data_in >> i) & 0x1) ^ crc[4];
poly = crc[1] ^ xor;
crc[4] = crc[3];
crc[3] = crc[2];
crc[2] = poly;
crc[1] = crc[0];
crc[0] = xor;
}
// 输出5位CRC
*crc_ret = 16 * crc[4] + 8 * crc[3] + 4 * crc[2] + 2 * crc[1] + crc[0];
}
// 读取绝对角度
void ADMT4000_GetABSANGLE(void)
{
ADMT4000_Read_Data(ADMT4000_REG_ABSANGLE, &ABSRece_Data);
// 解析数据
uint16_t angle_raw = ABSRece_Data & 0x3FF; // 低10位:单圈角度
int16_t whole_turns = (ABSRece_Data >> 10) & 0x3F; // Bit[15:10]:整圈数
if (whole_turns <= 0x35) { // 有效范围:0-53圈
TurnCnt = whole_turns;
ABSANGLE_data = ((float)TurnCnt * 360.0f) +
((float)angle_raw * 0.351f);
} else if (whole_turns == 0x36) {
TurnCnt = 99; // 标记无效
ABSANGLE_data = 0xffff;
} else {
TurnCnt = 255; // 负数标记
ABSANGLE_data = 0xffff;
}
}
步进电机控制
步进电机控制模块实现了校准、位置更新、温度映射等功能。步进电机的速度与PWM信号的频率成正比。本项目中,TIM2定时器配置为PWM输出模式,预分频系数为720,计数器周期为999,由此产生的PWM频率约为100Hz(计算公式:f = 72MHz / 720 / 1000 ≈ 100Hz)。对于1.8度/步的步进电机,这意味着每秒可输出100个脉冲,电机转速约为100步/秒或约2.8圈/分钟。步进电机的方向控制通过DIR引脚实现:当DIR为高电平时,电机在一个方向旋转;当DIR为低电平时,电机在相反方向旋转。本项目中,DIR高电平设置为"开启"方向(开口增大),DIR低电平设置为"关闭"方向(开口减小)。
关键参数定义(main.c):
#define STEPER_FULL_RANGE 1080.0f // 电机总行程:3圈 × 360° = 1080°
#define STEPER_ANGLE_MIN 1000.0f // 最小安全角度(考虑机械限位和误差)
#define STEPER_ANGLE_MAX 16560.0f // 最大角度(ADMT4000的测量上限)
// 步进电机校准
void Stepper_Calibrate(void)
{
stepper_error = 0;
// 检查初始角度是否在有效范围
if (admt_abs_angle < STEPER_ANGLE_MIN ||
admt_abs_angle > STEPER_ANGLE_MAX)
{
stepper_error = 1; // 设置错误标志
stepper_calibrated = 0; // 校准失败
return;
}
// 设置关闭位置为当前位置
stepper_closed_angle = admt_abs_angle;
stepper_target_angle = stepper_closed_angle;
stepper_calibrated = 1; // 校准成功
stepper_reached = 1; // 初始状态视为已到达目标
}
// 步进电机更新
void Stepper_Update(void)
{
if (!stepper_calibrated || stepper_error) return;
float current_angle = admt_abs_angle;
// 安全检查
if (current_angle < STEPER_ANGLE_MIN ||
current_angle > STEPER_ANGLE_MAX)
{
stepper_error = 1;
HAL_GPIO_WritePin(STEPER_ENABLE_PORT, STEPER_ENABLE_PIN, GPIO_PIN_SET);
Stepper_Stop();
stepper_dir = 0;
return;
}
float error = stepper_target_angle - current_angle;
// 滞回控制
if (stepper_reached) {
if (error > 8.0f || error < -8.0f) {
stepper_reached = 0; // 需要重启
} else {
HAL_GPIO_WritePin(STEPER_ENABLE_PORT, STEPER_ENABLE_PIN, GPIO_PIN_SET);
Stepper_Stop();
return;
}
} else {
if (error > -3.0f && error < 3.0f) {
stepper_reached = 1; // 已到达
HAL_GPIO_WritePin(STEPER_ENABLE_PORT, STEPER_ENABLE_PIN, GPIO_PIN_SET);
Stepper_Stop();
return;
}
}
// 方向控制
if (error < 0) {
HAL_GPIO_WritePin(STEPER_DIR_PORT, STEPER_DIR_PIN, GPIO_PIN_SET);
stepper_dir = 1; // 开启方向
} else {
HAL_GPIO_WritePin(STEPER_DIR_PORT, STEPER_DIR_PIN, GPIO_PIN_RESET);
stepper_dir = -1; // 关闭方向
}
// 启动电机
HAL_GPIO_WritePin(STEPER_ENABLE_PORT, STEPER_ENABLE_PIN, GPIO_PIN_RESET);
Stepper_Start();
}
// 温度-角度映射
void Stepper_SetAngleFromTemp(float temp, float threshold)
{
if (!stepper_calibrated) return;
float over_temp = temp - threshold;
if (over_temp <= 0) {
stepper_target_angle = stepper_closed_angle;
} else if (over_temp >= 5.0f) {
stepper_target_angle = stepper_closed_angle + STEPER_FULL_RANGE;
} else {
stepper_target_angle = stepper_closed_angle +
(over_temp / 5.0f) * STEPER_FULL_RANGE;
}
}
ADMT4000复位序列
ADMT4000传感器支持硬件复位,复位序列的正确执行对传感器正常工作至关重要。
void ADMT4000_Reset(void)
{
// 初始状态:RS和SHDN均为低电平
HAL_GPIO_WritePin(ADMT_RS_GPIO_Port, ADMT_RS_Pin, GPIO_PIN_RESET);
HAL_GPIO_WritePin(ADMT_SHDN_GPIO_Port, ADMT_SHDN_Pin, GPIO_PIN_RESET);
HAL_Delay(10);
// 1. 拉低RST复位设备
HAL_GPIO_WritePin(ADMT_RST_GPIO_Port, ADMT_RST_Pin, GPIO_PIN_RESET);
HAL_Delay(10);
// 2. 释放RST
HAL_GPIO_WritePin(ADMT_RST_GPIO_Port, ADMT_RST_Pin, GPIO_PIN_SET);
HAL_Delay(50);
// 3. 拉高SHDN使能29V电源
HAL_GPIO_WritePin(ADMT_SHDN_GPIO_Port, ADMT_SHDN_Pin, GPIO_PIN_SET);
HAL_Delay(1000); // 等待电源稳定
// 4. 发送RS高脉冲(10ms)
HAL_GPIO_WritePin(ADMT_RS_GPIO_Port, ADMT_RS_Pin, GPIO_PIN_SET);
HAL_Delay(50);
HAL_GPIO_WritePin(ADMT_RS_GPIO_Port, ADMT_RS_Pin, GPIO_PIN_RESET);
// 5. 重新初始化传感器
ADMT4000_Init();
}
6. 硬件功能展示
显示页面

系统启动后默认进入显示页面,页面布局采用左右分栏设计,左侧显示HVAC控制信息,右侧显示ADMT4000传感器数据。
7. 设计中遇到的难题和解决方法
问题描述:系统运行时发现ADMT4000传感器显示的绝对角度最大值只能达到600多度,然后就从头开始计数,而不是预期的16560度。
原因分析:经过深入分析驱动代码和 datasheet,发现数据解析逻辑存在错误。ABSANGLE寄存器的数据格式理解有误,导致整圈计数不正确。
datasheet中ABSANGLE寄存器的定义:
位 | 功能 |
Bit[9:0] | 单圈角度原始值 |
Bit[15:10] | 整圈数(最多46圈) |
原始代码将整个16位数据一起处理,没有正确分离角度和圈数。
解决方法:重新实现数据解码逻辑,正确分离低10位的单圈角度和高6位的整圈数,并进行相应的计算:
// 修正后的解码逻辑
uint16_t angle_raw = ABSRece_Data & 0x3FF; // 提取低10位
int16_t whole_turns = (ABSRece_Data >> 10) & 0x3F; // 提取Bit[15:10]
if (whole_turns <= 0x35) { // 0-53圈为有效值
TurnCnt = whole_turns;
ABSANGLE_data = ((float)TurnCnt * 360.0f) + ((float)angle_raw * 0.351f);
}
8. 心得体会
通过本项目的开发,对嵌入式系统开发的全流程有了深入的理解和实践经验。本项目深入应用了ADMT4000多圈绝对角度传感器,从datasheet研读到驱动编写,再到数据解析和校验,完整地掌握了磁编码器角度传感器的应用方法。特别是在数据解析方面,通过反复调试最终理解了传感器寄存器数据的正确格式,这对此类传感器的后续应用具有重要参考价值。项目涉及GPIO外部中断、SPI通信、I2C通信、PWM输出、定时器中断等多种外设,完整地练习了STM32H5系列芯片的外设配置和调试能力。