FOC 位置环 PI 调参实战:让电机指哪停哪
阅读约 11 分钟 | 适合电流环和速度环都调好了想让电机精确控制角度的兄弟一、速度环稳了但你能让电机停在 37度 吗上篇我们把速度环调好了。给定一个转速电机转得稳稳当当加负载也不掉速。你的电机终于像个听话的伺服了。现在老板说让电机转到 37度误差不超过 0.5度。你设了个目标位置电机转过去了——然后它越过 37度冲到 45度又倒回来又冲过去来回晃了七八次才勉强停住。或者更惨根本停不住一直在目标附近来回抽搐。你的速度环没问题你的位置环没调。速度环只管转多快。它不在乎停在哪。但真要精确停在某个角度必须上位置环。二、位置环在三环结构里的位置目标角度 θ_ref │ ▼ ┌─────────────────┐ │ 位置环 (P) │ ← 最外层最慢 │ 输入角度误差 │ │ 输出速度指令 │ └────────┬────────┘ omega_ref │ ▼ ┌─────────────────┐ │ 速度环 (PI) │ ← 中层 │ 输入速度误差 │ │ 输出电流指令 │ └────────┬────────┘ i_q_ref │ ▼ ┌─────────────────┐ │ 电流环 (PI) │ ← 最内层最快 │ 输入电流误差 │ │ 输出电压 → SVPWM → 电机 └────────┬────────┘ │ ▼ 编码器反馈角度、速度关键理解位置环的输出是速度环的目标值。目标角度 37度当前角度 0度误差 37度位置环输出 omega_ref 20 rad/s让速度环用这个速度转过去接近目标时位置环自动降低 omega_ref减速到达 37度位置环输出 omega_ref 0停住位置环是导航员速度环是司机电流环是油门。三、位置环为什么只需要 P大多数情况电流环用 PI速度环用 PI——惯性思维觉得位置环也该用 PI。错。大多数伺服应用里位置环只需要 P 控制器。为什么不用 I位置误差的积分意味着如果电机被挡了一下没转到目标I 项会一直累积。障碍物消失时I 项已经积得巨大电机会猛冲过去撞到机械限位。这叫积分饱和Integral Windup在位置环里破坏力最强。那没有 I位置误差怎么消除靠速度环的 I 项接力位置误差小 → 位置环 P 输出小 → 速度环收到很小的速度指令 → 速度环 P 也输出小但速度环 I 持续积分 → I 项积累出额外的转矩把最后那点角度误差推过去换句话说位置环 P 把电机带到附近速度环 I 负责推进门里。两个环分工协作不需要位置环自己再叠一个 I。位置环 P 负责大方向速度环 I 负责精细到位。四、位置环 P 值怎么调4.1 物理含义P_position 角度误差 1 rad 时输出多大的速度指令。物理量纲rad/s ÷ rad 1/s单位是 Hz。如果你的速度环额定转速是 50 rad/s希望在 0.5 rad (≈28.6°) 的误差时位置环输出满速 50 rad/s → P 50 / 0.5 100P 值越大相同角度误差下速度指令越大 → 转得越快 → 到位越快。但如果 P 太大惯性会让电机冲过目标来回振荡。SimpleFOC 代码// 位置环 P 控制器配置motor.controllerMotionControlType::angle;motor.PID_angle.P20;// 位置环 P 增益从 5 开始试motor.PID_angle.I0;// 绝大多数情况不需要 Imotor.PID_angle.D0;// 位置环一般不加 Dmotor.velocity_limit50;// 速度限幅保护电机不过速4.2 三步调 PStep 0验证下层环。先确认速度环在工作、编码器读数正常。Step 1从小 P 开始。P5 时看表现慢慢转到位无过冲 - P偏小翻倍。快速到位 - 接近了微调。Step 2找到临界震荡值。每次翻倍5-10-20-40-80。P 太大时电机会位置过冲振荡肉眼可见的低频晃动。记下 P_osc取 40%P_final P_osc * 0.4 位置环比速度环更保守Step 3速度前馈Feedforward。纯 P 的缺点越接近目标越慢最后几度跟蜗牛爬。加前馈后到位时间直接砍半。// 速度前馈给位置环输出加一个预估速度偏置floatff_velocity5.0;// 根据目标距离估算的前馈速度motor.move(ff_velocity);// SimpleFOC 的 move() 支持直接传速度值// 注意move(vel) 会绕过位置环需要自己在外层叠加 P 控制五、实战完整代码#includeSimpleFOC.h// 硬件配置BLDCMotor motorBLDCMotor(7);// 7对极BLDCDriver3PWM driverBLDCDriver3PWM(9,10,11);// PWM引脚MagneticSensorI2C sensorMagneticSensorI2C(AS5600);// 磁编码器// 串口调参Commander commandCommander(Serial);voiddoTarget(char*cmd){command.motor(motor,cmd);}voidsetup(){// 1. 初始化编码器sensor.init();motor.linkSensor(sensor);// 2. 初始化驱动driver.voltage_power_supply12;driver.init();motor.linkDriver(driver);// 3. 位置环配置motor.controllerMotionControlType::angle;motor.PID_angle.P20;// 位置环 P → 从 5 开始按 4.2 节步骤调motor.PID_angle.I0;// 不加 Imotor.velocity_limit50;// 速度限幅 rad/s取额定转速 80%// 4. 启动motor.useMonitoring(Serial);motor.init();motor.initFOC();// 校准传感器零位// 5. 串口命令command.add(T,doTarget,target angle);Serial.println(FOC Position Control Ready.);Serial.println(Commands: T3.14 (set target to pi rad 180°));Serial.println( P30 (change P to 30));}voidloop(){motor.loopFOC();// 执行 FOC 电流控制motor.move();// 执行位置环 速度环command.run();// 处理串口命令}在线调参串口直接敲T3.14设目标180度P30改P值。六、三个常见翻车现场6.1 定位精度不够总差一点点现象转到目标后差 0.5~2 度回不来。原因纯 P 的静差被摩擦力和齿槽转矩吃掉了。对策按优先级加很小的 II0.5不超过 P 的 10%注意是 I 不是 P别加错了提高电流环增益让极低速也能稳定出力换高分辨率编码器6.2 大角度转动时过冲到离谱现象转 360 度冲到 420 度才回来。原因大角度误差 x P 值 超大速度指令速度环来不及减速。对策设合理限幅limit 速度环额定转速 80%启用 output_ramp限制输出变化率6.3 停住以后来回抖现象到目标后在几度范围内来回摆。原因编码器分辨率不够 P 太大。对策降 P 到不抖为止加死区误差小于阈值时不输出七、位置环合格标准测试项合格标准0-180度 阶跃0.3s 到位过冲 5度0-10度 小步进0.1s 到位不过冲加手指阻力偏移后自动恢复不震静止抖动 0.2度连续正反转不丢步累积误差 1度八、三环总结环路控制器作用带宽出问题表现电流环PI控制转矩抵抗反电动势最高(1kHz)电机啸叫、抖动速度环PI控制转速抵抗负载扰动中(100~500Hz)掉速、震荡位置环P(FF)控制角度抵抗位置扰动最低(10~50Hz)过冲、静差、震荡记住优先级电流环是地基不稳则全塌。速度环是骨架不硬则无力。位置环是外皮不准则白费。调参顺序永远从内到外电流环 - 速度环 - 位置环。九、下一步三环调完你的电机已经是完整伺服系统。进阶方向轨迹跟踪S 曲线加减速力矩控制力反馈方向盘多电机协同双驱 AGV无感 FOC不装编码器反电动势估算角度先把三环跑稳你已经是一个合格的 FOC 玩家了。下一篇FOC三环联调实战手搓一个指哪打哪的伺服电机关注「困困困困好困啊」嵌入式干货 定时更新。