ARTICLE DETAIL

资讯详情

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

MSPM0G3507+TB6612+MG513X直流电机PID闭环控制实战指南

MSPM0G3507+TB6612+MG513X直流电机PID闭环控制实战指南 前阵子给小车项目做驱动选型的时候在MSPM0G3507和STM32之间犹豫了很久最后把MSPM0G3507、TB6612、MG513X这套组合调通之后发现这其实是一个非常适合入门到进阶的直流电机闭环控制方案。MSPM0G3507主控负责产生PWM和处理编码器反馈TB6612作为双H桥驱动芯片驱动大电流直流电机MG513X是带霍尔编码器的减速电机三者配合再加上PID调速就可以实现精准的转速闭环。这篇文章我会把整套方案从头到尾拆开讲包括为什么选这套组合、硬件怎么接线、SysConfig怎么配置、驱动代码怎么写、PID怎么调参以及我实际踩过的坑。适合正在做智能车、机器人底盘、转台或者想入门电机闭环控制的朋友参考。手里有MSPM0G3507开发板但不知道怎么下手的话这篇文章可以直接当学习路线图用。1. 方案与硬件这套组合为什么值得上手1.1 三个核心器件各司其职先分别介绍一下这套方案里的三个主角。MSPM0G3507是TI推出的一款基于Arm Cortex-M0内核的MCU主频最高80MHz片上资源在这个价位段算是相当丰富。它最吸引我的是集成了一堆适合电机控制的定时器资源包括高级定时器TIMA和通用定时器TIMG支持PWM输出、输入捕获、正交编码器接口QEI等功能。搭配TI的SysConfig图形化配置工具不需要反复翻阅寄存器手册就能把外设初始化代码自动生成出来。这一点对新手非常友好也省去了很多配置过程中的低级错误。TB6612FNG是东芝出品的双H桥电机驱动芯片额定输出电流1.2A峰值能达到3.2A左右支持电机电压4.5V到13.5V。相比经典但体积硕大的L298NTB6612的导通压降小很多发热量也低模块尺寸大概只有拇指大小。对于MG513这类额定电压12V、空载电流几百毫安的直流减速电机来说TB6612的驱动能力刚好合适。MG513X是一款带编码器的直流减速电机常见的有1:30、1:90等减速比版本。电机本体后面集成了一路AB相霍尔编码器可以输出两路相位差90度的方波信号通过判断两路信号的相位关系就能知道电机的旋转方向再配合定时器的4倍频计数可以精确测量转速和位置。这个是做PID闭环的关键没有编码器反馈PID调速就是空谈。1.2 选型对比为什么不选L298N和DRV8833很多人会问市面上电机驱动芯片那么多为什么一定要用TB6612。我最早用的是L298N相信很多做小车的人都踩过这个坑。L298N的缺点非常明显内部是双H桥结构但管子压降大12V供电的时候实际到电机两端可能只有10V出头而且大电流工况下发热量惊人必须加散热片。模块体积又大又重放在小车上很占地方。它的优势仅仅是便宜、皮实坏了不心疼。DRV8833是TI的一款双H桥驱动芯片体积更小工作电压范围也宽但问题是持续输出电流只有1.5A左右峰值约2A。MG513X这种12V减速电机在启动和堵转瞬间电流很容易超过这个值用DRV8833的话心里总不踏实而且芯片本身不带散热结构一旦堵转就面临过热烧毁风险。TB6612正好卡在两者中间体积小、内阻低持续1.2A的额定电流对于MG513X的正常工况完全够用峰值3.2A的余量也能覆盖启动瞬间的冲击电流。更重要的是TB6612的PWM频率可以支持到100kHz级别意味着我们可以选择更高频的PWM来避开电机啸叫这在后面的调试环节是个非常实用的优势。还有一点MSPM0G3507的定时器支持QEI正交解码TB6612的输入逻辑很简单只需要三根控制线就能控制一路电机方向2根使能PWM1根。整个硬件连接清爽逻辑清晰出问题了也好排查。2. 硬件接线照着连就不会烧板子2.1 TB6612引脚逻辑与接线先看TB6612模块的引脚搞清楚每个引脚的作用。模块上通常有这些引脚VM电机电源正极按MG513X的规格接12V实际6V到12V都行VCC逻辑电源接3.3V或者5V都可以我们这里接MSPM0G3507的3.3VGND电源地必须和MCU共地STBY待机控制脚必须拉高芯片才工作这是新手最容易忽略的PWMA/PWMB两路电机的PWM输入对应A路和B路AIN1/AIN2A路电机的方向控制BIN1/BIN2B路电机的方向控制AO1/AO2A路电机输出BO1/BO2B路电机输出TB6612的输入逻辑真值表特别简单以A路为例AIN1AIN2PWMA电机状态高低PWM正转低高PWM反转高高任意刹车低低任意惰行滑行任意任意低停转这里有个容易忽略的点AIN1和AIN2同为高时电机是刹车状态相当于两个下桥臂导通电机两端被短接同为低时是惰行状态电机靠惯性自由滑行。实际做PID的时候如果希望减速更快可以利用刹车逻辑但要注意机械冲击。STM32F103时代有个经典问题是引脚电压不匹配好在MSPM0G3507的大多数GPIO是5V容忍的但TB6612的VCC接3.3V后AIN1/AIN2/PWM这些输入引脚的逻辑高电平阈值大约在2.0V左右所以直接用3.3V的GPIO驱动完全没问题。2.2 MG513X电机与编码器接线MG513X电机尾部会有两组线一组是电机绕组线通常红黑两根直接接到TB6612的AO1和AO2不用区分正负方向不对的话在软件里调换或者硬调都行。另一组是编码器的线通常有4根编码器电源正极一般红色接5V编码器地一般黑色接GNDA相输出常见蓝色或白色B相输出常见绿色或黄色需要特别提醒不同批次、不同商家的MG513X编码器线序并不是完全统一的有的带霍尔传感器是13线有的是11线有的还多一根电机线。所有线序务必以实物标签或商家说明书为准。我第一次买回来的时候没有核对线序凭经验把蓝绿当AB相接上结果测速数值完全混乱排查了很久才发现是对调了相位。编码器的输出电平一般是5V或者3.3V取决于编码器供电。如果编码器用5V供电输出高电平是5V而MSPM0G3507是3.3V器件这时候必须查一下引脚是否支持5V容忍。我个人的习惯是编码器直接用3.3V供电这样信号电平天然匹配省去电平转换电路。MG513X用的霍尔编码器在3.3V供电下也能正常工作只是要注意电机在接线时让编码器电源和逻辑电源共地否则信号参考电位不一致测速就会乱跳。2.3 电源设计电机不转的隐形杀手电机驱动系统的电源设计比大多数人想象的重要得多。MG513X虽然是减速电机但启动瞬间电流很容易冲到1A以上如果电源质量不好电压会被瞬间拉低。一旦VM脚电压跌到TB6612的最低工作电压以下电机就会表现为“偶尔转一下、断断续续”或者“转速异常”。推荐的做法是电机电源和逻辑电源分开供电电机单独用12V电源或者电池组MCU用USB或者独立的3.3V稳压器供电然后把两者的GND接在一起。如果只能用一个电源必须在电机电源入口并联一个大容量的电解电容470uF以上和一个小陶瓷电容0.1uF用来吸收瞬态电流冲击。TB6612模块上的GND引脚和电机电源地实际是同一个网络MCU的GND必须和模块GND连在一起。所谓的“共地”本质上就是让MCU输出的PWM信号和TB6612内部的H桥驱动电路有统一的参考电位。如果只是忘了连GND这根线电机会表现出非常诡异的现象上电后电机不受控制地微动或者完全不动但你用示波器量PWM波形又是对的。这里分享一个我自己的接线习惯先用颜色区分种类电机线用粗线编码器信号线用细杜邦线电源线和信号线分开走线尽量避免信号线贴着电机供电线长距离并行。MG513X是直流电机虽然有减速器但电刷产生的电磁干扰依然不小信号线靠近电机电源线的话编码器脉冲容易受到干扰给后面的测速和PID带来麻烦。3. 软件配置与底层驱动3.1 SysConfig工程配置要点TI的MSPM0系列推荐用CCS或者Keil配合SysConfig来开发。SysConfig是一个图形化配置工具从MSPM0 SDK安装包里启动可以通过勾选、填参数的方式配置外设然后自动生成初始化代码。这个工程里我们需要配置四类资源第一定时器输出PWM。选一个TIMG或者TIMA实例配置成PWM模式设置频率为20kHz初始占空比为0。这里把PWM频率定在20kHz主要是为了避开人耳可闻频段20Hz-20kHz否则电机会发出刺耳的尖叫声。第二正交编码器接口QEI。选一个TIMA实例配置为QEI模式把编码器的A相和B相分别接到对应的输入引脚上计数倍频选4倍频。MSPM0G3507的TIMA是支持正交解码的这一个外设就免去了我们再用GPIO外部中断去手动数脉冲的麻烦。第三控制周期定时器。选一个TIMG实例配置成1ms周期中断用于产生PID控制节拍和系统时基。第四GPIO。配置电机方向控制引脚AIN1、AIN2为输出STBY引脚为输出并初始化为高电平另外配置一个LED引脚用于指示系统运行状态。有一点要提醒SysConfig里生成的引脚分配不是随便选的TIMA的QEI输入引脚、PWM输出引脚都有固定的GPIO映射关系。在SysConfig界面上选中外设以后它会列出所有可用的引脚点一下就能自动分配。不同封装、不同开发板能用到的引脚不一样所以我在代码里尽量用宏封装引脚操作实际移植到其他板子时只需修改配置文件即可。3.2 电机驱动控制代码基于SDK生成的工程创建一个motor.c和motor.h文件把电机相关的操作封装起来。方向控制很简单就是操作AIN1和AIN2两个引脚调速则通过修改PWM占空比实现。// motor.h #ifndef MOTOR_H #define MOTOR_H #include stdint.h void Motor_Init(void); void Motor_SetDirection(int8_t dir); // 1正转 -1反转 0停 void Motor_SetPWM(uint16_t duty); // 0~65535 void Motor_SetSpeed(int16_t speed); // speed 0正转 speed 0反转 speed 0停 void Motor_Stop(void); #endif// motor.c #include motor.h #include ti_msp_dl_config.h void Motor_Init(void) { // STBY拉高让TB6612退出待机模式 DL_GPIO_setPins(GPIOA, STBY_PIN); } void Motor_SetDirection(int8_t dir) { if (dir 0) { DL_GPIO_setPins(GPIOA, AIN1_PIN); DL_GPIO_clearPins(GPIOA, AIN2_PIN); } else if (dir 0) { DL_GPIO_clearPins(GPIOA, AIN1_PIN); DL_GPIO_setPins(GPIOA, AIN2_PIN); } else { DL_GPIO_clearPins(GPIOA, AIN1_PIN); DL_GPIO_clearPins(GPIOA, AIN2_PIN); } } void Motor_SetPWM(uint16_t duty) { DL_TimerA_setCaptureCompareValue(PWM_INST, duty, PWM_C0_IDX); } void Motor_SetSpeed(int16_t speed) { uint16_t abs_speed 0; if (speed 0) { Motor_SetDirection(1); abs_speed (speed 65535) ? 65535 : (uint16_t)speed; } else if (speed 0) { Motor_SetDirection(-1); abs_speed (speed -65535) ? 65535 : (uint16_t)(-speed); } else { Motor_SetDirection(0); } Motor_SetPWM(abs_speed); } void Motor_Stop(void) { Motor_SetDirection(0); Motor_SetPWM(0); }这套封装的思路是把方向逻辑和PWM输出解耦。PID计算出结果后如果输出量是正值就正转负值就反转绝对值作为PWM占空比这样上层控制代码非常简洁。3.3 编码器测速与转速计算正式调PID之前先把测速搞定。用TIMA的QEI模式读取编码器脉冲数然后通过定时中断周期性地计算转速。以常见的MG513电机减速比1:30、编码器为11线霍尔、QEI选择4倍频为例电机输出轴旋转一圈编码器产生的脉冲数为每圈脉冲数 11 × 30 × 4 1320也就是说输出轴每转一圈计数器累加1320。这个值一定要根据你手头实际电机的减速比和编码器线数去算不同批次可能不同。如果算错了后续PID的目标转速单位换算就会整体出错。下面是测速相关的代码// speed.h #ifndef SPEED_H #define SPEED_H #include stdint.h #define ENCODER_LINES 11 // 编码器线数 #define GEAR_RATIO 30 // 减速比 #define QEI_4X 4 #define PULSE_PER_REV (ENCODER_LINES * GEAR_RATIO * QEI_4X) void Speed_Init(void); void Speed_Poll(void); float Speed_GetRPM(void); #endif// speed.c #include speed.h #include ti_msp_dl_config.h static int32_t qei_last_count 0; static int32_t qei_delta_total 0; static volatile float rpm 0.0f; static int32_t QEI_GetCount(void) { // DL_TimerA_getTimerCount 返回当前计数器的值 return (int32_t)DL_TimerA_getTimerCount(QEI_INST); } void Speed_Init(void) { qei_last_count QEI_GetCount(); } // 在1ms定时中断中调用 void Speed_Poll(void) { int32_t now QEI_GetCount(); int32_t diff now - qei_last_count; qei_last_count now; // 处理16位计数器回绕把差值换算到有符号范围内 if (diff 32767) { diff - 65536; } else if (diff -32768) { diff 65536; } qei_delta_total diff; } // 每20ms调用一次计算实时转速 void Speed_CalcRPM(void) { int32_t pulses qei_delta_total; qei_delta_total 0; // 脉冲数 / 每圈脉冲数 当前20ms内的转数 // 转换成每分钟转速转数 * (1000 / 20) * 60 rpm (float)pulses / (float)PULSE_PER_REV * 3000.0f; } float Speed_GetRPM(void) { return rpm; }这里有几个细节值得解释。QEI计数器的位宽不一定刚好是16位但代码里按16位回绕处理是最常见的情况如果你看到计数范围不同把这个宏改一下就行。回绕处理的原理是相邻两次读取之间即使计数器发生了向上溢出或向下溢出差值仍然落在有符号范围内通过判断差值是否超过半量程来修正。另外为什么转速计算要放在20ms的节拍里而不是1ms因为MG513X在低转速下每毫秒产生的脉冲数太少1ms内可能只有零到几个脉冲测出来的转速波动非常大。20ms内累积的脉冲数更多速度测量值更平滑。但控制周期太长又会降低PID的响应速度20ms也就是50Hz的控制频率对于这种直流减速电机的速度环来说是比较折中的选择。4. PID调速从公式到能跑的代码4.1 位置式PID和增量式PID怎么选PID调速本质上就是根据目标转速和实际转速的偏差计算出一个合适的PWM占空比输出给电机。偏差大了输出大偏差小了输出小这就是比例项P在做的事。积分项I负责消除静差比如电机克服负载需要额外的PWM补偿比例项到不了那么高积分项慢慢累积上去补足。微分项D则根据偏差变化趋势进行提前修正抑制超调。代码实现上位置式PID和增量式PID是两种最常见的形态。位置式PID的输出是绝对的PWM值它需要累加所有历史偏差容易产生积分饱和而且如果单片机突然复位输出可能会跳变。增量式PID输出的是PWM的增量每次只在原来的基础上加一个delta天然具有抗积分饱和的优势很多工程实现都偏好增量式。我用的是带积分限幅和输出限幅的增量式PID// pid.h #ifndef PID_H #define PID_H typedef struct { float Kp; float Ki; float Kd; float target; float prev_error; float prev2_error; float integral; float integral_limit; float out_limit; float delta_out; } PID_t; void PID_Init(PID_t *pid, float kp, float ki, float kd); void PID_SetTarget(PID_t *pid, float target); float PID_Calc(PID_t *pid, float measured); #endif// pid.c #include pid.h void PID_Init(PID_t *pid, float kp, float ki, float kd) { pid-Kp kp; pid-Ki ki; pid-Kd kd; pid-target 0.0f; pid-prev_error 0.0f; pid-prev2_error 0.0f; pid-integral 0.0f; pid-integral_limit 1000.0f; pid-out_limit 5000.0f; pid-delta_out 0.0f; } void PID_SetTarget(PID_t *pid, float target) { pid-target target; } float PID_Calc(PID_t *pid, float measured) { float error pid-target - measured; float delta 0.0f; // 增量式PID核心公式 delta pid-Kp * (error - pid-prev_error) pid-Ki * error pid-Kd * (error - 2.0f * pid-prev_error pid-prev2_error); // 对增量做限幅防止瞬间跳变 if (delta pid-out_limit) { delta pid-out_limit; } else if (delta -pid-out_limit) { delta -pid-out_limit; } // 累积输出同时做积分限幅防止积分饱和 pid-integral delta; if (pid-integral pid-integral_limit) { pid-integral pid-integral_limit; } else if (pid-integral -pid-integral_limit) { pid-integral -pid-integral_limit; } pid-prev2_error pid-prev_error; pid-prev_error error; return pid-integral; }增量式PID的公式看起来比位置式复杂一点但理解起来不难比例项看偏差的变化量积分项看当前偏差微分项看偏差的加速度。最后输出的delta加在之前的输出上这样即使单片机重启导致integral清零电机也只是平滑恢复到初始状态不会有突兀的跳变。4.2 完整的闭环控制循环把电机驱动、编码器测速和PID串起来就是主循环的逻辑。// main.c 核心逻辑 #include ti_msp_dl_config.h #include motor.h #include speed.h #include pid.h PID_t speed_pid; volatile uint32_t sys_tick 0; volatile uint32_t speed_calc_tick 0; int main(void) { // SysConfig生成的初始化 SYSCFG_DL_init(); Motor_Init(); Speed_Init(); // Kp、Ki、Kd先给一组保守初值后面按调试结果调整 PID_Init(speed_pid, 30.0f, 5.0f, 1.0f); PID_SetTarget(speed_pid, 120.0f); // 目标转速120rpm // 使能定时器中断 NVIC_EnableIRQ(TIMG_0_INST_INT_IRQN); while (1) { // 主循环可以做串口打印、指令解析等 } } void TIMG_0_IRQHandler(void) { switch (DL_TimerG_getPendingInterrupt(TIMG_0_INST)) { case DL_TIMER_IIDX_ZERO: sys_tick; speed_calc_tick; // 每1ms累加一次编码器脉冲 Speed_Poll(); // 每20ms做一次PID计算和控制输出 if (speed_calc_tick 20) { speed_calc_tick 0; Speed_CalcRPM(); float current_rpm Speed_GetRPM(); float out PID_Calc(speed_pid, current_rpm); Motor_SetSpeed((int16_t)out); } break; default: break; } }这段代码的逻辑就是典型的周期性控制循环1ms中断负责采集脉冲20ms节拍负责算转速、算PID、更新PWM。你可能注意到PID算出来的输出直接用作了PWM占空比并没有做归一化处理。在实际工程里PWM占空比的量纲和PID输出的量纲应该统一要么把转速偏差映射到占空比范围要么把PID输出的范围限制在0到65535之间。这里我是让PID输出直接对应16位PWM值初始参数里out_limit限制在5000电机不会猛然加速比较安全。4.3 PID调参顺序与方法调参是PID里最磨人的环节。网上有很多理论方法比如齐格勒-尼科尔斯临界比例法但实际工程中大家用的还是最朴素的“先P、再加I、最后加D”的试凑法。我的调参流程是这样的第一步把所有积分项和微分项设为0只留一个很小的Kp。给一个温和的目标转速观察电机是否能转起来会不会震荡。如果电机抖动或发出嗡嗡声说明Kp太大往小调。如果电机转速离目标很远但能稳定住说明Kp有作用了可以逐渐加大Kp直到转速接近目标且没有明显超调。第二步固定Kp缓慢增加Ki。积分项的作用是消除静差你会发现加了Ki之后稳态转速慢慢向目标值靠拢。但Ki太大会引起低频振荡转速像波浪一样上下起伏这时候要适当回退。第三步如果超调很严重或者到达目标转速的时间太长再加Kd。微分项对噪声很敏感Kd不建议给太大否则电机会出现高频抖振。我整理了一个参数现象对照表调参时可以参考参数过大时的现象过小时的后果Kp转速震荡、电机啸叫响应慢、稳态偏差大Ki低频波动、转速来回摆稳态精度差、带不动负载Kd高频抖动、噪声放大超调明显、动态响应迟滞一个更实用的建议是PID的很多怪异现象其实并不是参数问题而是测量问题。比如编码器信号受到干扰、测速周期不合适导致速度反馈毛刺大这时候去调PID是永远调不好的。所以一定要先把开环测试做扎实确认PWM和测速都准确无色差再进入闭环调参。5. 调试实录我踩过哪些坑5.1 电机不转、嗡嗡叫和发热严重这类问题把电路和软件检查一遍基本都能定位。电机完全不动首先量STBY引脚是否高电平。STBY不拉高TB6612内部电路完全关闭输入任何信号都不起作用。然后是AIN1和AIN2的方向或刹车逻辑如果两个引脚同时为高电机会被刹车锁死这时候你手拧电机轴会感觉到明显的阻力。还有一种情况是PWM通道没有启动输出SysConfig配置了定时器PWM模式之后还要在代码里显式调用定时器启动函数这一点很容易漏。电机嗡嗡叫但转不起来大概率是PWM频率太低了。1kHz到几kHz的PWM正好落在人耳敏感区而且频率低的时候电流纹波大电机会出现步进式转动。把PWM频率提到15kHz到20kHz之后这种问题基本消失。模块发热严重先量一下VM电压是不是跌落得厉害再看是不是长时间堵转。如果电机卡住TB6612持续输出大电流芯片很快就会烫手。遇到这种情况我一般会加堵转保护检测PWM输出超过阈值且转速几乎为零时主动关断输出几秒。5.2 编码器数值乱跳和测速漂移编码器测速不准PID就不可能稳定。最常见的几个原因编码器电源和MCU不共地。这是接线的硬伤只要GND不连在一起示波器上看到的是脉冲波形可能就是乱的。务必检查电源地和信号地是否在同一个网络里。编码器信号线上没有上拉电阻。有的编码器输出是开漏结构需要外部上拉到VCC才能输出正常的方波。如果用MSPM0的GPIO直接读取可以把GPIO配置为内部上拉输入。QEI的A、B相接反了。接反后计数器会反向计数电机正转时测得转速为负值。低转速下可能表现为转速波动高转速下PID直接发散。判断方法是开环给电机一个固定正转PWM观察编码器计数值是增大还是减小。信号抖动导致计数异常。霍尔编码器输出信号本身比较干净但如果和电机电源线靠得太近电刷火花产生的电磁干扰会耦合进信号线。改善布线或者用双绞线传输信号也可以加一阶RC低通滤波截止频率选在编码器最大输出频率的3倍以上。另外测速周期太短也会导致速度值抖动很大。我用20ms测速周期算出来的转速比较平滑但代价是控制更新率只有50Hz。如果你的系统对响应速度要求更高可以把编码器换成更高线数、或者用1:90减速比的版本让每个控制周期内的脉冲数变多。5.3 PID发散的典型症状和处理逻辑PID跑飞或者发散的时候现象通常很有特点电机先是迅速冲到最高转速然后掉下来再冲上去像打摆子一样或者一开机就直接满速狂转完全不受控制。第一次遇到这种情况先别急着改参数想想逻辑是不是有问题。常见的逻辑错误是ICM和方向控制打架。比如PID输出为负值但电机驱动函数里没有把负值转化为反转方向和正向PWM结果负的PWM被强行赋给一个无符号变量反而变成了一个很大的正值电机当然全速正转。积分饱和也是一个常见原因。如果目标转速从0直接跳到120rpm误差长时间保持很大积分项疯狂累加输出达到限幅值并保持之后即使转速超过目标积分项要花很久才能退回来就表现为很大的超调。我的代码里加了integral_limit和out_limit两层限制本质上就是限制积分项的“惯性”。如果确认逻辑没问题再按顺序查先把Ki和Kd置零只留Kp看是否稳定Kp稳定后再加Ki最后加Kd。不要一上来就猜一组参数那样只会让问题更复杂。5.4 调试工具和技巧分享最后聊一下工具。调电机控制示波器和逻辑分析仪是两大神器。示波器用来观察PWM波形、编码器AB相波形。编码器正常工作时示波器上能看到两路占空比接近50%、相位差90度的方波。如果波形上有毛刺多半是干扰如果相位差不稳定可能是减速器内部的霍尔传感器松了或者磁环位置偏了。逻辑分析仪用来抓多路信号的时间关系。比如想同时看PWM输出、AIN1、AIN2和编码器脉冲用逻辑分析仪最方便。便宜的几十块就能买到采样率够用可以把PID的每个控制周期内发生了什么看得清清楚楚。如果没有仪器用串口打印也是一种可行的方法。把目标转速、实际转速、PID输出、编码器原始计数值通过UART以20ms为周期打印出来再用串口绘图工具画成波形也能直观地看到转速跟踪和PID输出的变化趋势。我经常在调PID的时候先用串口确认测速是否准确再进行闭环调参这样可以少走很多弯路。我个人的经验是PID调参要有耐心每次只改一个参数改完观察至少10秒钟不要看到一两秒的波动就觉得参数不行。电机控制是个“接线决定下限、代码决定上限”的活只要硬件基础牢靠软件逻辑清晰PID参数慢慢试总能试出一组合适的。这套MSPM0G3507 TB6612 MG513X的组合跑通之后不仅能用在小车底盘改改参数就能迁移到云台、转台或者任何需要直流电机速度闭环的场景。
返回列表