ARTICLE DETAIL

资讯详情

深耕郑州网站建设与运营推广的一线实战洞察。

基于STM32的电机状态检测:转速、电流与故障判断

基于STM32的电机状态检测:转速、电流与故障判断 做电机控制相关项目时“基于STM32单片机电机状态检测”是一类很基础也很实用的题目它不解决复杂的控制算法而是解决一个更前置的问题——电机现在到底转没转、转多快、电流大不大、有没有堵转或过温。这篇内容适合正在做课程设计、毕业设计或者准备把电机驱动接入自己项目的人看。我按实际落地顺序拆一遍从传感器选型、硬件接线、CubeMX配置到转速读取、电流采样、故障判断逻辑最后给出一套调试验证方法和排查链路。这类项目最常见的问题是程序能下载串口也有输出但转速值始终是0或者电流数值跳来跳去再或者明明是堵转却没有触发报警。这些问题大多不是单片机本身的问题而是传感器信号、配置参数和判断逻辑没有对齐。下面直接进入正题。1. 先搞清楚电机状态检测到底要检测哪些状态很多新手拿到题目就开始写代码结果写了一半发现不知道要显示什么、判断什么。我建议先列一个状态清单把检测目标和判断标准定下来再动手。1.1 转速检测霍尔、编码器、反电动势三条路线电机状态检测里转速是最核心的一项。常见做法有三种。第一种是霍尔传感器。直流电机或者无刷电机的转子上带磁铁时可以用霍尔元件检测磁场变化每经过一个磁极就输出一个脉冲。单片机通过外部中断或者定时器捕获脉冲间隔就能算出转速。第二种是编码器。电机尾部装了AB相正交编码器时STM32的定时器可以工作在编码器模式硬件自动计数程序读一个寄存器就能拿到脉冲数再根据每转脉冲数算出转速。这个方法最稳也不需要频繁进中断。第三种是反电动势法常用于无刷电机不需要额外传感器通过检测电机绕组的反电动势过零点来判断转子位置。但这个方法需要比较复杂的硬件调理电路和软件算法课程设计阶段不建议一上来就碰。从实测体验来说霍尔传感器方案接线最简单AB相编码器方案数据最稳定。如果题目没有限定传感器我建议优先考虑带霍尔或者带编码器的直流减速电机。1.2 电流、电压、温度母线参数与故障判据转速只能反映电机是否在转不能反映电机是否带载、是否吃力。要判断堵转和过流需要检测电流。电流检测的常见做法是在电机供电回路上串联一个毫欧级采样电阻把电流信号转换为电压信号再经过运放放大后送入STM32的ADC引脚。没有运放时也可以用电流传感器模块比如ACS712系列直接输出电压信号接线更简单。电压检测相对简单用电阻分压把母线电压降到ADC可测量范围内就行。电压数据可以用来判断供电是否异常也可以估算电机输入功率。温度检测一般用NTC热敏电阻配合固定电阻分压接ADC。电机外壳温度上升之后NTC阻值变化ADC读数随之变化通过查表或者线性换算得到温度值。1.3 堵转、过流、过温最常见故障怎么判断检测到的数据本身没有意义关键是把数据变成判断结果。堵转检测的核心逻辑是电机在运行状态下转速接近零但电流显著高于正常值。只判断速度为零不够因为电机可能本来就停着只判断电流过高也不够因为启动瞬间电流本来就很大。所以正确做法是组合判断。过流检测的核心是电流超过设定阈值并持续一段时间。注意“持续一段时间”很重要否则启动瞬间的浪涌电流会频繁触发误报。过温检测的核心是温度超过阈值后进入保护等温度回落到恢复阈值以下才能重新启动。这里要用迟滞逻辑避免温度在阈值附近震荡导致继电器反复吸合。我建议把这些状态定义成一个枚举类型程序里用一个状态机来管理而不是散落一堆if判断。typedef enum { MOTOR_STOP 0, MOTOR_RUNNING, MOTOR_OVERCURRENT, MOTOR_STALL, MOTOR_OVERTEMP } MotorState_t;2. 硬件准备与关键选型逻辑硬件部分决定了项目能不能稳定跑起来。不要只看单片机型号传感器、驱动模块、电源和接线质量对结果影响很大。2.1 开发板与单片机选型原则STM32系列里F103系列是课程设计最常用的一类C8T6和RCT6两个型号都能完成电机状态检测。如果只是检测一台电机的转速、电流和温度F103C8T6完全够用它有多个定时器、多个ADC通道、足够多的GPIO。如果后续要做无刷电机控制或者多电机检测建议用F103RCT6或者F407系列主要是引脚数和定时器资源更多。但初学者没必要追求高配把一块入门开发板吃透比换高配板子更有用。开发环境方面建议用STM32CubeMX先生成初始化代码再用Keil MDK编写业务逻辑。CubeMX可以做时钟树、GPIO、定时器、ADC的图形化配置生成代码后会省掉大量寄存器配置工作对于状态检测类项目足够高效。低配置环境下也能开发只要Keil能编译下载串口能输出就不会影响进度。唯一要注意的是电脑性能太差时编译时间会比较长耐心等待即可。2.2 传感器与驱动模块接线思路以直流有刷电机加霍尔传感器为例典型接线是这样的单片机PA1接霍尔传感器OUT引脚配置为外部中断输入。单片机PA2接PWM输出到电机驱动模块IN1控制电机转速。单片机PA3、PA4接驱动模块IN2和IN3控制正反转。单片机PA5接OLED或者LCD的SDAPA6接SCL用于显示状态。单片机PA7接电流传感器输出配置为ADC输入。单片机PB0接NTC分压电路输出配置为ADC输入。霍尔传感器一般用NPN开漏输出所以要接上拉电阻到3.3V。上拉电阻选10k到47k都可以太小会增加功耗太大会导致边沿不够陡峭。这里最容易踩的坑是霍尔传感器输出接了上拉但开发板内部也开了上拉两个上拉并联后电平判断仍然正常通常不影响但如果霍尔传感器输出直接接5V开发板的引脚就可能损坏IO接线前一定要确认电平。电流传感器模块一般输出0到5V或者0到3.3V模块不同输出电压范围不同。ADC引脚输入范围不能超过VREF否则会损坏单片机。如果传感器输出范围是0到5V需要加电阻分压或者选择支持5V输入的开发板引脚。2.3 电源和隔离注意事项电机启动瞬间电流很大会导致电源电压跌落。如果单片机和电机共用一个电源单片机可能因为电压跌落复位。稳妥的做法是电机用单独电源供电比如12V电池或者12V开关电源单片机用USB供电或者独立的5V/3.3V电源。驱动模块的电源地和单片机的地要共地否则信号无法正常传输。如果电机功率较大还需要考虑在电机供电端并联一个大电容滤波。容值可以从470uF到2200uF之间选择具体要根据电流大小来定。电容的作用是缓冲电机启动时的瞬态电流避免驱动模块过压或欠压。操作顺序也很重要先给单片机供电确认程序能运行再给电机通电。千万不要在电机运行时反复插拔信号线否则很容易把单片机GPIO烧坏。3. 从零搭最小工程CubeMX配置与代码框架这个项目的代码并不是越复杂越好。我先跑通最小功能再逐步加功能每加一个模块就验证一次。3.1 用CubeMX初始化时钟、GPIO、定时器、ADC打开STM32CubeMX选择STM32F103C8T6先配置RCC为外部晶振或者内部RC都行。教学环境下用内部RC也能跑但如果对串口波特率精度有要求还是用8MHz外部晶振更稳妥。GPIO配置方面霍尔输入引脚设为外部中断模式GPIO_MODE_IT_RISING也就是上升沿触发。PWM输出引脚设为复用推挽输出GPIO_MODE_AF_PP。ADC引脚设为模拟输入GPIO_MODE_ANALOG。OLED和LCD引脚根据模块要求配置一般软件I2C可以选普通推挽输出。定时器配置方面用一个定时器做1ms系统时基比如TIM2用于计时和转速计算。用一个定时器产生PWM比如TIM3的CH1输出频率设10kHz到20kHz之间占空比初始设为0。如果使用编码器把TIM4设置为Encoder Mode。ADC配置方面选择ADC1的CH1和CH2对应电流和温度两个通道。开启连续转换模式如果软件里有多种采样任务也可以使用单次转换再用定时器触发。采样周期可以设大一点比如55.5个周期提高稳定性。采样周期太小读数容易波动。配置完成后点击生成代码选择Keil MDK版本即可。3.2 转速读取编码器模式与外部中断实现外部中断方式适合霍尔传感器思路是霍尔信号每产生一个上升沿表示转子转过了固定角度在中断里记录一次脉冲。转速计算的公式是转速(RPM) 每秒脉冲数 / 每转脉冲数 × 60每转脉冲数取决于霍尔传感器安装方式。比如电机轴上有一个磁铁转盘一圈有6个磁极霍尔传感器每圈输出6个脉冲那么每转脉冲数就是6。在1ms定时中断里程序读取“当前脉冲计数”减去1秒前的脉冲计数就能得到每秒脉冲数。uint32_t pulse_count; uint32_t pulse_count_prev; uint32_t pulse_per_second; uint16_t rpm; void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim) { if (htim-Instance TIM2) { ms_counter; if (ms_counter 1000) { pulse_per_second pulse_count - pulse_count_prev; pulse_count_prev pulse_count; rpm pulse_per_second * 60 / PULSES_PER_REV; ms_counter 0; } } }为什么用1秒计数而不是测量脉冲间隔因为低速时脉冲间隔很长测量间隔会占用大量定时器资源高速时脉冲间隔太短定时器捕获容易出错。1秒计数的方式虽然刷新慢一些但更稳定适合状态检测场景。编码器方式更简单定时器工作在编码器模式后硬件自动根据AB相变化计数程序在定时器中断里读取TIM_CNT寄存器即可。编码器方式的优势是不需要在中断里频繁处理边沿CPU开销小适合转速较高的场景。3.3 电流采样ADC读取与软件滤波ADC读到的原始值是一个0到4095的数值需要转换成实际电流值。假设电流传感器输出电压0到3.3V对应0到5A那么转换关系是voltage adc_value * 3.3f / 4095.0f; current voltage / 3.3f * 5.0f;如果使用采样电阻加运放的方式转换关系要根据放大倍数重新计算。这里需要注意寄存器里的adc_value读出来可能跳几个到几十个数直接用于判断很容易误触发。我习惯先做一次简单的中位值滤波或者滑动平均滤波。比如连续采样10次去掉最大值和最小值然后取平均。这个操作在低速执行频率下成本很低收益却很直接。float read_adc_filtered(void) { uint16_t values[10]; uint16_t temp; for (int i 0; i 10; i) { HAL_ADC_Start(hadc1); HAL_ADC_PollForConversion(hadc1, 10); values[i] HAL_ADC_GetValue(hadc1); } // 冒泡排序取中间6个求平均 ... }不要在主循环里死等ADC转换完成否则程序会卡在一个点上其他任务无法执行。更合理的做法是启动ADC转换后在定时器中断里读取结果或者每50ms读取一次即可。电流变化速度相对较慢50ms的刷新周期足够用于状态检测。温度采样同理通过分压电路把NTC阻值变化转换成电压变化再查表或者用Steinhart-Hart公式换算温度。教学项目可以用线性近似只要温度范围不大误差可以接受。4. 状态判断算法与报警逻辑数据采集到位后核心工作就是写状态判断逻辑。这里的难点不是代码量而是怎么避免误报。4.1 阈值判断、迟滞和去抖不要用单一阈值直接判断。以电流检测为例假设电机正常运行时电流是0.5A堵转时是2.5A那么可以把过流阈值设在1.5A。但实际采样值会在1.2A到1.8A之间波动直接判断会导致继电器或者报警信号频繁通断。解决办法是加入迟滞触发过流保护时电流阈值设为1.5A。退出过流保护时电流要回落到1.0A以下才允许恢复。同理温度保护也有两个阈值比如85度触发保护75度恢复。迟滞逻辑的本质是让状态切换有一个缓冲区避免系统在阈值边界来回跳变。if (state MOTOR_RUNNING current OVERCURRENT_HIGH) { state MOTOR_OVERCURRENT; } else if (state MOTOR_OVERCURRENT current OVERCURRENT_LOW) { state MOTOR_RUNNING; }4.2 状态机设计停止、运行、堵转、过流、过温单独一个状态无法表达电机全貌我建议使用前面定义的状态机。状态切换规则可以这样定STOP状态下如果PWM占空比大于0进入RUNNING。RUNNING状态下如果电流超过过流阈值且持续200ms进入OVERCURRENT。RUNNING状态下如果电机给定转速大于某值但实际转速接近0且电流偏高进入STALL。RUNNING或STALL状态下如果温度超过阈值进入OVERTEMP。故障状态下PWM输出降到0电机停止。故障状态通过按键或者串口指令清除后回到STOP。这个状态机的好处是每一条路径都是明确的出现问题时串口打出一行日志就能知道当前状态、当前原因不用猜。一个关键经验是进入故障状态后不能自动恢复。比如过流持续1秒就进入保护如果电流马上回落就直接恢复那电机可能反复尝试启动导致热积累。至少等待3秒或者收到手动复位指令才允许重新启动。4.3 串口、OLED输出与调试方法状态判断做完了需要把结果展示出来。最简单的输出方式是串口打印使用printf重定向到USART1波特率设为115200。调试时打印的信息最有用的是这组数据[1000ms] stateRUNNING rpm1200 current0.53A temp32C duty40%有了这行日志可以非常清晰地把数据变化和状态切换对应起来。建议在状态切换时额外打印一条事件消息方便追溯[event] RUNNING - STALL, current3.1A, rpm10OLED显示适合最终展示。一般的0.96寸OLED可以显示四行内容建议第一行显示状态第二行显示转速第三行显示电流和温度第四行显示PWM占空比。显示驱动可以用软件I2C开发成本低接线也方便。如果使用LCD1602要重点注意对比度调节和背光接线很多项目显示不清晰是因为对比度电位器没有调好而不是I2C通信问题。5. 实测流程与结果验证程序写完不直接上真机先跑最小样例再逐步加复杂功能。实测的顺序建议按“启动电源—看串口—单条任务—批量/持续运行—故障模拟”来走。5.1 最小样例先跑通读取转速第一次上电测试只跑转速读取功能。打开串口给电机供电设置PWM占空比20%观察串口输出中转速是否为合理值。这时候不要急着调这个调那个先把“数据链路”打通。什么叫链路打通就是霍尔信号经过引脚、中断、计数、计算最终变成串口里一行数字整个流程中间没有断点。如果串口没有转速输出排查顺序应该是霍尔传感器供电是否正常。霍尔信号引脚电压是否在转动时变化。外部中断是否触发可以在中断里设置一个标志位。PWM是否让电机转起来了。每转脉冲数是否设置正确。我见过不少情况是霍尔传感器没坏程序也没写错但电机因为驱动板EN使能没拉高而根本没转。这种情况下所有检测逻辑都正常就是电机不转所以排查时先解决“电机是否转动”这个大前提。5.2 加入电流和温度后观察输出转速链路通了再打开电流采样和温度采样。先设置一个固定的PWM占空比比如50%观察电流读数的变化范围。用手按住电机轴施加阻力电流应该明显上升。温度数据如果显示在30度左右说明接线基本正常。这里有个常见问题电流ADC读数始终是0但用万用表量传感器输出确实有电压。这种情况大多数是ADC的通道配置错了比如CubeMX里配置的是ADC1_IN1但代码读取的却是ADC1_IN2。还有可能是没有配置ADC扫描模式多个通道轮流采集时没有正确切换。如果电流读数比实际值偏高或者偏低先确认分压电阻和运放放大倍数再调整转换公式。不要因为读数不对就随机改代码参数最好是先接一个可调电源或者标准恒流源用万用表标定一下。5.3 故障模拟与验证人为堵转、调高电流状态检测项目必须在现场模拟一次堵转场景否则不能算完成。我建议的验证流程是这样的电机正常运行PWM 30%记录电流和转速。用手捏住电机轴模拟堵转观察状态变成STALL是否在预期时间内。松开电机轴看状态是否保持STALL等待复位指令后恢复正常。调高PWM到80%记录电流是否超过过流阈值触发OVERCURRENT保护。用热风枪或者电烙铁靠近NTC模拟过温观察OVERTEMP触发和恢复阈值。每一步都要记录日志把状态切换时间和当时的电流、转速对应起来。如果堵塞后2秒才触发报警而项目要求是1秒内就要把判断周期改短。如果启动瞬间就误报过流就要增加持续时间滤波。故障模拟验证完成后整个项目就具备基本的实用价值了。6. 常见问题与排查链路最后整理一份针对本项目的问题排查清单。这些坑不是每个项目都会遇到但一旦遇到能快速定位能省很多时间。6.1 转速显示为零先确认电机是否真的在转听声音、看电机轴、用万用表测驱动输出。电机转了但转速读数为零重点检查三处GPIO是否正确配置为外部中断有没有在CubeMX里开启NVIC中断使能。霍尔传感器输出的电平有没有变化用万用表直流电压档量转动时电压应该会变化。每转脉冲数是否设置得过大导致1秒内没有产生足够多的脉冲。如果霍尔传感器输出是5V电平而STM32引脚工作在3.3V信号可能无法被正确识别。这时候需要确认STM32引脚的容忍电压或者加电平转换。6.2 电流读数跳变ADC读数跳变的原因很多最常见的是采样时间太短电容充电不充分。电源纹波太大参考电压不稳定。电流传感器和单片机不共地。没有滤波代码直接拿单次采样值使用。处理方案是加滤波代码、加去耦电容、检查共地、把采样时间调长。按这个顺序来而不是先去换传感器。如果电流在0.1A到0.3A之间波动但实际电流应该很稳定优先怀疑电源问题而不是算法问题。先把示波器或者万用表接到传感器输出端确认原始信号再决定改软件还是改硬件。6.3 误报警和程序卡死误报警大多数是判断逻辑的问题。启动瞬间电流大导致的过流保护误报可以通过增加持续时间判断解决温度在阈值附近波动导致的过温误报可以通过迟滞逻辑解决。程序卡死时先看串口是否还有输出。如果没有输出大概率是死循环或者中断优先级配置错误。这时先把所有中断注释掉只保留一个串口输出看程序是否正常运行再一个模块一个模块加回来。如果程序在进入某状态后卡住通常是某个函数里的等待超时太短比如HAL_ADC_PollForConversion的超时时间设为10ms而ADC实际没有启动就会卡死在等待中。解决方法是把超时时间调大或者在等待前先启动ADC。6.4 断电重启后状态异常有些项目在上电瞬间会误触发一次过流保护原因是单片机上电瞬间ADC还没有稳定读到的是随机值。处理办法是上电后先延时200ms等待电源和ADC稳定再进行ADC校准。或者加一个“初始化窗口”上电后1秒内不进行故障判断只允许状态初始化。如果闭环控制项目中有EEPROM保存参数要防止断电时写坏参数。状态检测类项目一般不需要频繁保存参数可以省去EEPROM但如果是保存阈值或者校准值就要考虑写入失败和掉电保护的问题。排查顺序可以总结为先看现象再看输入信号再看供电和共地再看ADC配置最后看判断逻辑。很多项目看起来是单片机问题实际是传感器信号或者电源问题所以不要一上来就改软件参数。电机状态检测这个主题本身不难难点在于把转速、电流、温度、状态判断串成一个完整的闭环。只要先把最小链路跑通再逐步叠加功能和故障保护就能稳定交付一个真正可演示、可验收的项目。如果后续要做接口化或者上位机可以先把状态数据通过串口JSON格式输出再用Python或者Qt做一个简单监控界面这些都属于同一套架构的自然扩展。
返回列表