1. 先说清楚:电机到底在“听”什么
做电机这些年,我经常被问一个问题:电机不都是通电就转吗?转得快慢由电压大小决定,力气大小由电流大小决定,这话对不对?
对,但只对了一半。
如果你只看课本上的直流电机模型,确实可以这么理解。但放到实际工程项目里,电机是有“性格”的。有的电机你给它一个目标转速,它自己就知道怎么调;有的电机你给它一股力,它自己就知道该转多快。这两种性格,对应的是电机控制领域最基础也最核心的两大流派:速度控制(听“目标”)和转矩控制(听“力气”)。
听“目标”的电机,常见于风机、水泵、传送带这类负载相对稳定的场景。你要它转1500转,它就稳稳守住1500转,负载变重了它会多出力,负载变轻了它会少出力,目的只有一个:转速不能掉。
听“力气”的电机,常见于电动汽车、机器人关节、伺服压机这类场景。你要它输出5牛·米的转矩,它就是输出5牛·米,哪怕外部把它堵住不转,它也得保持这5牛·米。转速反而成了“随缘”的东西。
为什么会有这种区别?因为电机的电磁转矩方程本身就写着:转矩和电流成正比,转速和电压(反电动势)相关。你控制哪个物理量,电机就听哪个“指令”。控制电流,就是控制转矩;控制电压,就是在间接控制转速。两种思路,背后是两种完全不同的控制策略:标量控制(V/F)和矢量控制(FOC)。
这篇文章我不会把标题展开成教科书式的原理宣讲,而是想结合我自己做过的几个实际项目,把“听目标”和“听力气”这两类电机各自的控制思路、硬件选型、调试方法、踩坑记录,一五一十写清楚。无论你是刚接触电机控制的初学者,还是已经在用STM32、ESP32C3做驱动板的嵌入式工程师,这套思路都能直接落地。
2. 听“目标”的电机:速度控制的底层逻辑
2.1 最简单的“目标”:开环V/F控制
很多入门项目里,控制电机最粗暴的方式就是PWM开环控制。比如用STM32输出一路PWM,接到TB6612电机驱动模块的PWMA引脚,占空比给50%,电机就转半速;占空比给100%,电机就全速。这是不是听“目标”?勉强算,因为你在给它一个速度目标——只不过,它能不能守住这个目标,电机自己说了算,你的控制程序完全不管。
开环控制的典型问题是:负载加重,转速就掉。你明明PWM占空比没变,电机却从1500转掉到1100转。这在风机、泵类负载上还能忍,但在要求严格的场合就完全不行。
这时候就要上闭环速度控制。把编码器装到电机轴上,实时测量转速,再把测量值和目标值做差,用PID把差值压回去。这就是所谓“听目标”的完整形态:控制器不断问电机“你现在多少转?目标1500,你现在只有1300,误差200,加大电流!”。
2.2 闭环里的核心:PID参数到底怎么调
PID调参是我见过劝退新手最多的环节。我给你一个最容易上手的实操流程,前提是电机带编码器,且调速范围在额定转速的10%到100%之间。
第一步,只加P。把积分I设成0,微分D设成0。P从0开始,每次加0.5,观察转速阶跃响应。你会发现:P太小时,转速到不了目标,静态误差明显;P逐渐加大,到达目标的速度变快,但开始出现超调;P继续加大,转速开始震荡,甚至出现啸叫声。
第二步,在响应速度能接受、超调不大的P值基础上,加I。I的作用是消掉静态误差。每加一档,观察稳态转速和目标值的差距。注意I不是越大越好,I太大会导致低频振荡,转速呈现周期的忽快忽慢。
第三步,加D。D的作用是抑制超调。但实际上,编码器反馈数据本身就带噪声,D放大噪声的能力比抑制超调的能力还要明显。我在实际项目中,多数情况D是设为0的。
一个非常实用的经验公式:先把P调到临界振荡值(转速持续等幅振荡),记下这个值Kp_crit,再把P设为Kp_crit的0.6倍,I设为1.2倍Kp_crit除以振荡周期。这是Ziegler-Nichols整定法的最简化版本。实测下来,这个起点参数已经相当能打,后续微调幅度不大。
2.3 速度闭环容易忽略的坑
速度闭环不是调完PID就完事。有几个坑,我认为是所有人都会踩的:
第一,编码器线数不够。电机带200线的编码器,测速分辨率在低转速时非常差。比如电机只有100转/分,编码器每转200个脉冲,每秒只有333个脉冲,PID周期是1ms的话,每个周期平均不到0.3个脉冲,量化误差极大,转速反馈全是台阶状。解决方案有两个:一是用M法测速(单位时间内的脉冲数),转速高时精度好;二是用T法测速(测两个脉冲之间的时间),转速低时精度好。实际项目我建议直接用MT法,低速高速兼顾。
第二,PWM频率和PID频率的关系。PWM频率决定电流的开关纹波,PID频率决定控制环的响应速度。PID频率至少要大于PWM频率的1/10。比如PWM是20kHz,PID至少2kHz。这个比例太低,控制环会被PWM周期拉低,转速响应会“一顿一顿”的。
第三,启动瞬间的堵转问题。速度闭环在电机启动瞬间,因为反电动势还没建立起来,电流会很大,PID输出一下顶到饱和。这时候如果不加限幅,轻则过流保护,重则烧驱动。实现上可以在PID输出后面加一个软启动斜坡——让目标转速不是阶跃,而是从一个较低值按固定斜率缓缓爬升。这就是标题里“缓启动”的工程意义。
3. 听“力气”的电机:转矩控制的实现路径
3.1 为什么要用电流控制来做力
扭转思路:转矩控制的目标是电流,因为电机的电磁转矩公式 T = Kt × I,力矩常数Kt基本是固定的,只要控制好电流I,转矩就被精确控制了。
但电流控制有个前提——你必须能实时准确地感知电流。这就不是“给PWM、测转速”这么简单了,你要在硬件上加电流采样电阻,或者用霍尔电流传感器,把电机相电流读回来,然后做控制闭环。
如果你用的是直流有刷电机,转矩控制还相对简单:一个H桥驱动电路,一个电流采样电阻,一个电流环PID,就能让电机输出恒定力矩。但如果你用BLDC(无刷直流电机)或者PMSM(永磁同步电机),事情就复杂了——因为三相电流是交替变化的,你必须在正确的时刻、正确的相位上注入正确的电流。这就引入了矢量控制。
3.2 FOC矢量控制:让电机“听力气”的核心技术
FOC全称Field-Oriented Control,中文叫磁场定向控制。它的核心思想是:把三相电机的电流通过坐标变换,从静止坐标系变换到旋转坐标系下,分解成两个独立的变量——d轴电流(励磁分量)和q轴电流(转矩分量)。然后你只需要控制q轴电流,就能直接控制转矩。
打个比方:如果说速度控制是“管人”,那FOC就是“把人按到操场上,告诉他往哪个方向跑、跑多快,然后精确喂饭”。系统里的Clarke变换和Park变换,本质上就是数学上的坐标旋转,把三个交织在一起的交流量,解耦成两个独立的直流量。解耦之后,两个电流环PID可以各自独立控制,控制效果就好像你同时握住了两个旋钮——一个管励磁,一个管转矩。
我在项目里实际用的FOC实现流程是这样的:
- 采样三相电流(Ia, Ib,Ic可以由Ia+Ib+Ic=0算出来,省一个采样通道)
- 做Clarke变换,得到Ialpha、Ibeta
- 读编码器角度,做Park变换,得到Id、Iq
- 把Id的目标值设为0(表贴式电机不需要额外的励磁),把Iq的目标值设为你要的转矩对应的电流值
- 两个电流环PID分别计算输出电压Ud、Uq
- 做逆Park变换,得到Ualpha、Ubeta
- 用SVPWM生成三相占空比,输出到逆变桥
这里面每一步都有专门的工具和参数。我调试FOC的时候,最喜欢做的事就是拿示波器看Id、Iq的波形。如果Id、Iq两条曲线平稳,没有大幅脉动,那基本上说明电流环已经调通了一半。
3.3 关于“零序分量注入”和“无稀土电机”那些新词
热词里有“零序分量注入”和“无稀土电机”,这两个词值得展开说下,因为它们和“听力气”的电机关联很深。
零序分量注入是SVPWM的一种优化策略。三相逆变器的母线电压利用率,在多轴输出时往往受限,注入一个零序分量(三次谐波)到三相调制波里,可以让调制波处于更合理的工作区间,从而提升母线电压利用率。这个技巧在三相电机驱动里比较常见,属于“用数学手段榨干硬件性能”的典型操作。我在调试高转速BLDC时,如果不做零序注入,转速上限会明显被拉低,因为反电动势太高,PWM的调制度达到饱和,无法继续升压供电。
无稀土电机则是一个材料层面的新方向。传统PMSM用了钕铁硼永磁体,成本高、供应链受制于稀土资源。无稀土电机用铁氧体或者电励磁电机方案,牺牲了一部分转矩密度,换来的是成本大幅下降和供应链更安全。我在做低成本的机器人关节时,确实关注过这个方向——转矩密度低了,那就在设计上增大电机直径,或者用减速比去换。从系统层面看,有时候是值得的。
4. 两个“性格”如何在硬件驱动上体现
4.1 听“目标”的电机:V/F驱动+速度闭环的典型硬件
一套最简单的速度闭环硬件,大概是这个搭配:
- 电机:直流有刷电机,12V、带霍尔编码器(如MG513P30_12V这种自带减速箱+编码器的型号,学生项目里非常常见)
- 驱动:TB6612电机驱动模块,内置H桥,峰值电流1.2A,逻辑电压3.3V/5V都能兼容
- 主控:STM32F103或者ESP32C3,输出PWM和控制方向信号
- 反馈:编码器输出AB相脉冲,接定时器的编码器模式
接线时注意,TB6612的PWMA和PWMB分别控制两个通道的PWM占空比,AIN1/AIN2决定方向。ESP32C3驱动电机时,PWM引脚最好选带指定定时器的IO,不然PWM波形不稳定,频率抖动会让电流噪声变大。
这套硬件我用下来的体会是:TB6612很“娇贵”。它的额定电流虽然标了1.2A,但实际连续运行时最好控制在0.8A以内,不然芯片温度上升很快。另外,它的逻辑电源VCC和电机电源VM必须分开,VM的电压不能低于VCC。有次我图省事共用一个电源,结果电机一启动,逻辑电平被拉低,单片机不断复位。
4.2 听“力气”的电机:BLDC驱动的完整硬件链路
FOC驱动BLDC,硬件链路比直流有刷复杂至少一个量级:
- 主控:STM32F405或更高端,带高级定时器,支持六路互补PWM输出和刹车功能
- 逆变桥:三个半桥,常见选用DRV8301、DRV8353这类集成栅极驱动+电流放大器的芯片,或者分开用IR2104+MOS管
- 电流采样:低阻采样电阻加运放,接到主控ADC。采样时机非常关键,必须在PWM波形的固定相位处触发ADC,否则采样到的电流不是相电流的真实瞬时值
- 编码器:磁编码器MA730或者AS5600,推荐用SPI接口读16位原始角度的型号,比I2C速度快很多。I2C读AS5600在高速场合实时性不够
ESP32C3做FOC也不是不行,但受限比较明显。它没有高级定时器的刹车功能,且ADC是12位,采样精度和触发灵活性都弱于STM32的16位ADC同步采样。我在一个快速原型项目里试过ESP32C3+三层H桥驱动BLDC,低速转矩控制能做出来,但高速切换和弱磁控制明显力不从心。
硬件选型的原则,我用一句话总结:如果你想快速验证算法,STM32F405+DRV8353+MA730这套黄金组合能覆盖绝大多数FOC开发场景。淘宝的D24A电机驱动板就是这个思路的成熟产品,很多开源固件都直接支持,省掉自己画板的麻烦。
5. 实操环节:从建模到代码,把“目标”和“力气”都调出来
5.1 先用仿真验证思路:Maxwell和电机模型的区别
我强烈建议在打板写代码之前,先用仿真把算法验证一遍。电机控制的仿真工具,圈内常用的是Maxwell和Simulink,以及各种电机等效模型。
Maxwell是做电磁场有限元仿真的,可以精确算出电机的电感、磁链、齿槽转矩、反电动势谐波这些参数。拿到这些参数以后,可以用于做电机控制仿真,因为FOC算法里面需要电机的电气参数——定子电阻、电感、反电动势系数、极对数,这些参数直接影响电流环的PI参数设计。
而电机模型(电机控制仿真模型)通常指dq轴方程或三相静止方程,属于控制类的“行为模型”。你控制参数写下去,仿真出来的转速、转矩曲线,能看出系统稳定性问题,但看不到磁场饱和、齿槽抖动这类电磁细节。
我的建议是:用Maxwell求参数,用Simulink跑控制。参数的获取不一定要实测拆机,Maxwell的仿真精度已经足够工程设计使用。尤其是极对数这个参数,直接决定电角度和机械角度的换算,弄错了FOC完全没法转。示波器也能测极对数:给电机任意两相通电,手动旋转一周,观察反电动势的换向次数,数出来除以2就是极对数。这个方法很土,但极其有效。
5.2 一个完整可复用的速度控制例程(STM32+TB6612)
下面我贴一个简化但完整的速度控制代码框架,用的是STM32标准外设库。这不是商业代码,但是所有基础工程都能跑通。
// 定时器2编码器模式配置 void Encoder_Init(void) { RCC_APB1PeriphClockCmd(RCC_APB1Periph_TIM2, ENABLE); RCC_APB2PeriphClockCmd(RCC_APB2Periph_GPIOA, ENABLE); GPIO_InitTypeDef GPIO_InitStructure; GPIO_InitStructure.GPIO_Pin = GPIO_Pin_0 | GPIO_Pin_1; GPIO_InitStructure.GPIO_Mode = GPIO_Mode_IN_FLOATING; GPIO_Init(GPIOA, &GPIO_InitStructure); TIM_EncoderInterfaceConfig(TIM2, TIM_EncoderMode_TI12, TIM_ICPolarity_Rising, TIM_ICPolarity_Rising); TIM_SetCounter(TIM2, 32768); TIM_Cmd(TIM2, ENABLE); } // 1ms定时器中断,做PID运算 void TIM3_IRQHandler(void) { if (TIM_GetITStatus(TIM3, TIM_IT_Update) != RESET) { TIM_ClearITPendingBit(TIM3, TIM_IT_Update); int16_t encoder_count = (int16_t)TIM_GetCounter(TIM2) - 32768; TIM_SetCounter(TIM2, 32768); // 由脉冲数计算转速:脉冲/4倍频/线数/减速比 = 圈数 float speed_rpm = (float)encoder_count * 60.0f / (4.0f * 200.0f * 30.0f * 0.001f); // PID float error = target_rpm - speed_rpm; integral += error * dt; derivative = error - last_error; float output = Kp * error + Ki * integral + Kd * derivative; last_error = error; // 输出限幅 + PWM更新 if (output > 999) output = 999; if (output < -999) output = -999; if (output > 0) { GPIO_SetBits(GPIOB, GPIO_Pin_12); // AIN1=1 GPIO_ResetBits(GPIOB, GPIO_Pin_13); // AIN2=0 TIM_SetCompare1(TIM1, (uint16_t)output); } else { GPIO_ResetBits(GPIOB, GPIO_Pin_12); GPIO_SetBits(GPIOB, GPIO_Pin_13); TIM_SetCompare1(TIM1, (uint16_t)(-output)); } } }注意代码里几个关键点:编码器用了4倍频模式,实际分辨率是200线×4=800脉冲/圈;减速比是30,所以转速换算要除以30;PID积分项必须加限幅,不然长时间堵转后积分饱和,PWM会一直满输出,电机恢复转动时非常危险。这些细节,教科书不写,但实际工程全在这里面。
5.3 FOC控制的实现骨架(以SimpleFOC为例)
如果你不想从零写Clarke/Park变换,用开源库会快很多。SimpleFOC是目前最成熟的开源FOC方案之一,支持STM32、ESP32等多种平台。它默认把电流环的PI参数和速度环的PI参数分开,内部实现已经做了坐标变换、SVPWM、角度读取的一整套封装。
在SimpleFOC里实现一个“听力气”的电机,核心步骤是:
- 初始化BLDCMotor对象,设定极对数(phase_resistance、phase_inductance等电机参数)
- 初始化编码器,设定分辨率
- 调用motor.linkDriver()链接驱动,linkEncoder()链接编码器
- motor.voltage_pid、motor.current_pid是电流环和速度环的PID对象
- 调用motor.initFOC(),完成电角度校准
- 在主循环里调用motor.loopFOC(),然后走motor.move()控制转速或转矩
在线调试时,可以用SimpleFOC的串口指令发送电流目标值。我给一个典型命令序列:
# 设置q轴电流目标为0.5A set current 0.5 # 使能电机 enable如果电机在零速下能持续输出0.5A的堵转电流,说明“听力气”的核心功能已经实现。这个状态下,你用手去拧电机轴,它会像一只僵硬的胳膊一样抵抗你——这就是转矩模式最直观的体感。
6. 热词里的真实世界:无人机、仿真、开源固件
6.1 无人机电机选型:为什么它既听“目标”又听“力气”
大疆这类无人机上用的电机,从控制器角度说是转速环,但本质上它是一个“力气优先”的系统——你给螺旋桨一个升力需求,控制器算出需要的转速,然后驱动电机达到对应转速。升力和转速的二次方成正比关系,而转速又与转矩平衡相关,所以无人机电机既要精确控制转速,又要在受风扰时快速输出额外转矩。
无人机电机选型,核心参数有三个:电机重量、最大推力、转速常数Kv值。我踩过的坑是:一味选大推力电机,结果电机本身太重,续航反而下降。电机推重比(最大推力/自重)至少要做到6以上,整机才有比较宽裕的操控裕度。Kv值太低,螺旋桨转速上不去,做不了暴力机动;Kv值太高,换向频率太高,驱动器的开关损耗和反电动势波动都会变大。
另外,无人机电机基本都是外转子结构,转子转动惯量大,反过来构成了天然的“陀螺效应”,对姿态控制有一定帮助。但如果电机在低转速下飞行,外转子结构散热很差,长时间悬停可能导致绕组过热退磁。
6.2 方波控制与FOC在BLDC驱动里的博弈
很多开源无人机固件默认用的是方波控制(六步换向),而车用驱动电机、机器人关节则更偏向FOC。方波控制的优点是算法极简——只需按转子角度顺序换相,不需要复杂坐标变换;缺点是有换相转矩脉动,低速时噪声大,效率和动态响应低。
我做机器人关节时,一开始用了方波BLDC驱动,结果低速力矩模式下,电机发出明显的“咔咔”声,位置精度也差。换成FOC以后,低速转矩完全平稳了。原因很简单——FOC让三相电流连续变化,转矩输出近似恒定;而方波控制在60度电角度内只有两种开关状态,转矩波动是天然存在的。
如果你只想做无人机飞控级别的推力控制,并且追求极简,方波控制完全够用。如果想做精密伺服或者车身驱动,FOC绕不开。
6.3 从VESC到Moteus:开源电机控制固件的选型心得
热词里提到“电机控制开源固件入门指南:VESC与Moteus”,这俩是我见过的最具代表性的开源固件方案。
VESC(开源ESC固件),底层是FOC,用到ARM Cortex-M4级别的单片机,支持电流环速度环双闭环,还带无感FOC、弱磁、有感启动等一系列高级功能。社区资料极其丰富,很多电滑板、电动轮毂项目直接用VESC改参数就行。
Moteus则是一个更聚焦“关节伺服”的固件方案,他的优势在于把编码器、驱动、控制算法、通信(CAN)整合得很完整,适合做机器人关节。它内置的PID调节器和前馈控制都很强,能够实现极低延迟的转矩响应。
我的建议是:
- 如果你在做一个电动滑板或DIY电动工具,直接上VESC,省时省力;
- 如果你在做四足机器人或者机械臂关节,优先看Moteus;
- 如果你只是想学习FOC原理和底层代码,两个都可以读源码,但先从SimpleFOC开始更容易上手。
6.4 硬件调试技巧:示波器正确用法
示波器在电机调试里是“照妖镜”,但很多人用错了。我来分享几个我屡试不爽的抓波形技巧:
第一,抓PWM波。把探头接到驱动芯片的M1输出,看AB相对GND的波形。正常情况下PWM占空比随目标值变化,频率稳定。如果波形抖动严重,八成是PWM定时器配置有问题,或者电源纹波干扰了高速开关。
第二,抓电流波形。必须要用差分探头或者用电流钳。普通探头夹采样电阻的两端,会因为参考地问题引入噪声,我踩过这个坑。后来我直接用带霍尔传感器的电流钳,量低压电机相电流特别干净。
第三,抓Id/Iq内部变量。FOC调试时,通过DAC输出或者串口打印实时数据,在示波器上看Id/Iq曲线比看相电流更直观。如果Iq稳态有周期性波动,说明转子角度读取有误差;如果Id不为0,说明电角度补偿没做对,或者有强弱的磁阻转矩没有消除。
7. 易错排查清单与速查表
我整理了一份快速定位问题的表,实际操作时可以直接对照排查:
| 现象 | 可能原因 | 排查优先级 |
|---|---|---|
| 电机启动转不起来 | PWM占空比太小、启动死区、堵转保护触发 | 高 |
| 转速抖动、不稳 | 编码器线数不足、PID周期太长、电流饱和 | 高 |
| 空载正常,带载转速掉落 | 速度闭环I积分不够、电流限幅设太小 | 中 |
| FOC调但电机转向反 | 编码器方向和电机相序接反 | 高 |
| 电机啸叫 | PWM频率在可听频段、PID超调 | 中 |
| 电机发热严重 | 相电流谐波过大、散热不良、长时间堵转 | 中 |
| 驱动板冒烟 | VM反接、VM与GND短路、尖峰吸收缺失 | 高 |
| 转速有台阶 | 编码器反馈数字滤波太强、M法在低速下量化误差大 | 低 |
实际项目里,我认为最高频的坑就是“相序接反”和“编码器方向错误”,几乎每个新手第一次搭FOC都会遇到。解决方法是先把编码器的方向在程序里固定,然后用电机开环强制旋转,对比编码器数据和目标运动方向。如果反了,要么交换两相线,要么在软件里把编码器方向取反。这个校准流程,所有FOC库都提供了现成函数,但很多人不去用,结果浪费一整天。
再补一个很隐蔽的坑:低速大转矩下,电流采样电阻的位置不同,采到的电流不对称。电阻在低边采样时,PWM死区期间采样窗口非常窄,容易采到尖峰。解决方式是加硬件滤波电容,或者在软件里避开死区时间采样。我见过很多人在低速力矩模式下采样电流毛刺严重,最终都是靠调整采样时机解决的。
8. 两种性格背后,其实是对物理量控制的选择
回到最开始的比喻。电机听“目标”,就是把转速方程当成第一控制目标;电机听“力气”,就是把转矩方程当成第一控制目标。两者的本质,就是你对被控对象选择了不同的物理量作为闭环变量。
我这些年做下来,越来越认同一个观点:控制电机,不是说哪个方案“先进”,哪个方案“落后”。你得先问自己,你的系统到底需要什么?如果你只是做一个调速风扇,折腾FOC纯属浪费;但如果你做的是四足机器人关节,那么“听力气”才是运动能力的基础。选错了控制目标,就是在电机这个齿轮上装反了整个系统的传动逻辑。
另外,我还想特别提醒一件事:电机控制的代码,90%的时间不是花在算法公式上,而是花在标定、滤波、限幅、故障保护这些“脏活”上面。不要小看这些脏活。没有积分限幅的PID,就是一个会爆炸的定时炸弹;没有软启动斜坡的驱动器,就是一台容易过流的硬起动机;没有母线电容预充的驱动板,上电那一刻就可能烧掉保险丝。
写这篇文章之前,我也翻过很多博客。博客园上一篇“直流有刷电机控制”的系列文章,虽然年代久远,代码风格老,但里面的很多细节——比如编码器测速的量化误差分析、TB6612的VM电压下限、堵转电流的实测数据——到现在看依然非常值得一读。很多新的教程,反而把这些细节藏在了“软件库帮你做了什么”的阴影里,导致大家只学会了调用,没学会原理。
所以我真心建议你,假如想长期待在电机控制这个领域,一定要花一个下午,自己手写一次编码器测速程序,自己手算一次电动车轮毂电机的极对数,自己用示波器抓一次相电流波形。这些基础动作做完以后,再回头用任何开源固件、任何高级驱动芯片,你都清清楚楚知道它在干什么,而不是像一个盲人一样瞎调参数。
电机就是这样一种东西:你越懂它,它越听话。听“目标”也好,听“力气”也好,核心都在于你亲手把反馈闭环搭正确,把每一个物理量维护在自己的预期通道里。