4、位置检测原理:绝对位置与相对位置、上电初始位置丢失、参考点(Home)位置、机械限位与软限位
好,咱们进入第四讲。位置检测,说白了就是天窗的「眼睛」。眼睛要是瞎了,天窗就不知道自己开到哪了,轻则关不上,重则把密封条挤坏甚至烧电机。我这些年处理过的天窗故障,有一半以上都跟位置检测有关。
4.1 绝对位置 vs 相对位置:两种思路
先讲清楚两个基本概念。绝对位置,就是天窗在滑轨上的「门牌号」。比如滑轨全长1000个脉冲,天窗完全关闭时位置是0,完全打开时是1000。每次上电,这个数值都是固定的,不依赖上一次的运行记录。
相对位置呢?它只记录「我从上次断电前走到了哪」。说白了就是个计数器。电机转一圈,霍尔传感器产生几个脉冲,MCU就加几个数。断电后计数器归零,下次上电从零开始重新数。
我个人习惯,在量产项目中用「相对位置+参考点校准」的方案。为什么?因为绝对位置需要额外的传感器或者编码器,成本高。你想想看,一个天窗模块的BOM成本可能就几十块钱,加个绝对值编码器,成本直接翻倍,主机厂肯定不干。
关键区别:
- 绝对位置:上电即知位置,无需自学习,但硬件成本高
- 相对位置:成本低,但断电后位置丢失,必须重新校准
我在项目中遇到过一家供应商,他们用了绝对位置方案,结果因为滑轨公差太大,每次装配后绝对位置值都不一样,反而需要做一次「绝对位置标定」。嗯,这就有点本末倒置了。
4.2 上电初始位置丢失:最头疼的问题
上电初始位置丢失,这是天窗控制器最常见的故障模式。为什么会这样?
原因很简单:天窗控制器断电后,RAM里的数据全没了。如果用的是相对位置方案,MCU醒来后根本不知道天窗在哪。你想想看,如果天窗是半开状态断电的,下次上电时控制器以为天窗在关闭位置,一按关闭按钮,电机直接往关闭方向猛推——结果天窗已经关死了,电机还在转,轻则堵转保护,重则烧驱动芯片。
我曾经处理过一个售后投诉:车主停车时天窗翘起通风,第二天早上发现天窗自己关上了,还关不严。查到最后,是控制器在上电瞬间误判了位置,执行了错误的关闭动作。
避坑指南:我曾经在初版设计中,把位置数据只存在RAM里,没做EEPROM备份。结果客户做了一次断电测试,天窗就疯了。后来我强制要求:位置数据必须每100ms写入一次EEPROM,并且上电后先读取EEPROM中的位置值,再结合霍尔脉冲做校验。
解决上电位置丢失,业内主流做法是「上电自学习」。流程大致如下:
- 上电后,MCU读取EEPROM中保存的最后位置
- 如果EEPROM数据有效(有CRC校验),直接使用
- 如果EEPROM数据无效(首次上电或数据损坏),进入自学习模式
- 自学习模式下,天窗自动运行到参考点(Home位置),重新标定
4.3 参考点(Home)位置:天窗的「定海神针」
参考点位置,也叫Home位置,是天窗位置检测的基准。所有位置计算都基于这个点展开。
Home位置选在哪?我建议选在「完全关闭位置+过关闭一段距离」。为什么?因为天窗关闭时,密封条会被压缩,电机需要额外多走一段距离才能确保密封。这段「过关闭距离」就是Home位置。
举个例子:
// 参考点位置定义
#define HOME_POSITION_OFFSET 50 // 过关闭50个脉冲
#define CLOSE_POSITION 0 // 完全关闭位置
#define VENT_POSITION 200 // 翘起位置
#define OPEN_POSITION 1000 // 完全打开位置
// 判断是否到达Home位置
bool is_at_home_position(uint16_t current_pos) {
// 当前位置在Home位置±3个脉冲范围内,认为到达
if (abs(current_pos - HOME_POSITION_OFFSET) <= 3) {
return true;
}
return false;
}
我在项目中遇到过一个问题:某款天窗的Home位置选在了完全关闭位置,结果冬天密封条变硬,天窗关不严。后来我把Home位置往后移了30个脉冲,问题就解决了。你想想看,机械结构是有公差的,温度变化也会影响,Home位置必须留余量。
个人经验:Home位置检测通常用霍尔传感器配合机械挡块实现。当机械挡块触发霍尔传感器时,MCU记录当前位置为Home。我建议在Home位置附近做「防抖处理」,连续采样3次都确认到达,再更新位置值。否则一个抖动脉冲就能让位置基准偏移。
4.4 机械限位与软限位:两道防线
机械限位,就是物理上的硬挡块。天窗滑轨两端各有一个,电机再怎么转,天窗也撞不过去。这是最后一道防线,但代价是——撞上去会发出「咔」的一声,车主听着心疼,而且长期撞击会损坏机械结构。
软限位,是软件里设定的位置边界。比如我设定天窗最大打开位置是1000个脉冲,超过这个值,MCU直接切断电机驱动,不让它继续走。软限位的好处是无声、无磨损,而且可以动态调整。
我一般这样设计:
// 软限位定义
#define SOFT_LIMIT_OPEN_MAX 980 // 打开软限位,留20个脉冲余量
#define SOFT_LIMIT_CLOSE_MAX 20 // 关闭软限位,留20个脉冲余量
#define HARD_LIMIT_OPEN 1000 // 机械限位位置
#define HARD_LIMIT_CLOSE 0 // 机械限位位置
// 电机控制函数
void motor_control(uint16_t target_pos, uint16_t current_pos) {
// 检查软限位
if (target_pos > SOFT_LIMIT_OPEN_MAX) {
target_pos = SOFT_LIMIT_OPEN_MAX; // 软限位截断
set_error_flag(ERROR_SOFT_LIMIT_OPEN);
}
if (target_pos < SOFT_LIMIT_CLOSE_MAX) {
target_pos = SOFT_LIMIT_CLOSE_MAX; // 软限位截断
set_error_flag(ERROR_SOFT_LIMIT_CLOSE);
}
// 执行位置控制
pid_control(target_pos, current_pos);
}
软限位和机械限位之间,我习惯留20-50个脉冲的缓冲距离。为什么?因为电机有惯性,急刹车时可能多走几步。如果软限位和机械限位贴得太近,软限位失效时就直接撞机械限位了。
注意:软限位不能完全替代机械限位。我曾经见过一个设计,只用了软限位,结果EEPROM数据损坏导致位置值错乱,天窗直接冲出滑轨。从那以后,我坚持「软限位为主,机械限位兜底」的双保险策略。
4.5 位置检测的完整流程
把上面这些串起来,一个完整的位置检测流程是这样的:
- 上电初始化:读取EEPROM中的位置数据,校验有效性
- 位置确认:如果数据有效,直接使用;如果无效,进入自学习
- 自学习过程:天窗运行到Home位置,记录当前位置为基准
- 正常运行:基于Home位置,通过霍尔脉冲计数计算实时位置
- 限位保护:软限位优先判断,机械限位作为最终保护
- 断电保存:每100ms将当前位置写入EEPROM
嗯,这套流程我用了好几年,在三个量产项目上验证过,没出过位置相关的大问题。当然,细节上每个项目都有微调,比如EEPROM写入频率、Home位置偏移量、软限位缓冲距离,这些都需要根据实际机械结构来标定。
下一讲,咱们聊聊防夹算法的实现。防夹这东西,做不好是要出安全事故的,到时候再细说。