亿迅智能制造网
工业4.0先进制造技术信息网站!
首页 | 制造技术 | 制造设备 | 工业物联网 | 工业材料 | 设备保养维修 | 工业编程 |
home  MfgRobots >> 亿迅智能制造网 >  >> Manufacturing Technology >> 制造工艺

掌握直流电机控制:PID 与 PWM 专家技巧全解析

元器件与物料

应用与在线服务

项目简介

基于 PID 控制器和 PWM 输出的直流电机转速与方向控制

引言

几乎所有项目都希望同时控制电机转速和方向,但大多直接将 PWM 信号发送给电机(即使通过驱动电路)。这种方法在需要精确匹配目标转速时总会失败,因为“摩擦”和“惯性”这对“孪生兄弟”会干扰控制。惯性让事物在行动前“思考”,摩擦限制加速度和速度。如果“功率”不在完全控制之下,它就“一无是处”。

直接用 PWM 控制转速时,实际转速永远无法达到设定值,存在显著误差(见上图)。因此我们需要另一种方法——PID 控制。

PID 控制器原理

想象开车:起步时需深踩油门,匀速时只需补偿速度损失,加速过快时则稍松油门。这正是“高效驾驶”的方式,也是 PID 控制器的工作原理。

PID 控制器读取设定值与实际输出的差值“误差信号 (e)”,包含三个分量:

Arduino 程序中的 PID 函数实现如下:

float controllerPID(float _E, float _Eprev, float _dT, float _Kp, float _Ki, float _Kd) {
  float P, I, D;
  /* 基础公式: U = _Kp * ( _E + 0.5*(1/_Ki)*(_E+_Eprev)*_dT + _Kd*(_E-_Eprev)/_dT ); */
  P = _Kp * _E;                           // 比例分量
  I = _Kp * 0.5 * _Ki * (_E+_Eprev) * _dT; // 积分分量
  D = _Kp * _Kd * (_E-_Eprev) / _dT;      // 微分分量
  return (P+I+D);
}

最终输出值 = 当前输出 + PID 控制器输出。主程序片段:

/* 误差信号、PID控制器输出和最终输出(PWM)给电机 */
E = RPMset - RPM;
float cPID = controllerPID(E, Eprev, dT, Kp, Ki, Kd);
if (RPMset == 0) OutputRPM = 0;
else OutputRPM = OutputRPM + cPID;
if (OutputRPM < _minRPM) OutputRPM = _minRPM;

直流电机供电电路

绝不建议直接从 Arduino 输出驱动直流电机,电机电流远超控制器输出能力。通常驱动继电器线圈,但继电器有机械触点,长期使用会失效。因此改用晶体管。直流电机由电流驱动而非电压,故采用晶体管控制电流。必须选择能承受电机电流的晶体管:先将电机直接接电源测量最大工况电流,或参考厂家规格书。

作者使用四只 BC307A PNP 三极管组成“桥式”电路改变电流方向(NPN BC337 更佳,因集电极电流耐受更高,但手头没有)。因电流流过发射极-集电极,需挑选直流电流增益 (hfe) 近似的三极管。测试电路如图所示,需考虑:

基极电阻计算公式:R = (VT - VBEon) * hfe / IM
作者案例:电机电流 70mA,BC307A hfe≈140,VBEon=0.62V,触发电压 3.3V(Arduino Due PWM),算得 R≈5360Ω,选用 4.9kΩ(2.2k+2.7k串联),PWM 引脚仅消耗 ~0.6mA,设计合理。

反转方向与重要注意事项

反转直流电机只需改变电流方向。原理图中 PWM 输出 #2 驱动 T1A/T1B,PWM 输出 #3 驱动 T2A/T2B,从而改变电机线圈电流方向。

关键问题: 电机启动瞬间会吸取远大于额定电流的浪涌电流(小功率电机约 130% 额定电流)。若在运行中直接反向供电,电机未完全停止会吸取极大电流,可能烧毁电源或线圈。使用晶体管驱动时,晶体管已限制电流,可避免此问题。无论如何,程序中加入保护逻辑:检测到方向改变时,先将两路 PWM 输出置零,等待电机完全停止后再切换方向。

if (Direction != prevDirection) {
  analogWrite(_chMotorCmdCCW,0);
  analogWrite(_chMotorCmdCW,0);
  do { RPM = 60*(float)readFrequency(_chSpeedRead,4)/_DiscSlots; }
  while (RPM > _minRPM);
}

测速原理

使用廉价 HC-020K 测速传感器,输出脉冲电平等于供电电压(数据手册标称 5V),但 Arduino Due 只能接受 3.3V。作者直接用 Due 的 3.3V 供电传感器,实测可工作。读取频率的函数如下:

int readFrequency(int _DI_FrequencyCounter_Pin, float _ReadingSpeed) {
  pinMode(_DI_FrequencyCounter_Pin,INPUT);
  byte _DigitalRead, _DigitalRead_Previous = 0;
  unsigned long _Time = 0, _Time_Init;
  float _Frequency = 0;
  if ( (_ReadingSpeed<=0) || (_ReadingSpeed>10) ) return (-1);
  else {
    _Time_Init = micros();
    do {
      _DigitalRead = digitalRead(_DI_FrequencyCounter_Pin);
      if ( (_DigitalRead_Previous==1) && (_DigitalRead==0) ) _Frequency++;
      _DigitalRead_Previous = _DigitalRead;
      _Time = micros();
    } while ( _Time < (_Time_Init + (1000000/_ReadingSpeed)) );
  }
  return (_ReadingSpeed * _Frequency);
}

HC-020K 编码轮有 20 个槽,读取频率除以 20 得每秒转数,再乘 60 得 RPM:RPM = 60 * (float)readFrequency(_chSpeedRead,4) / _DiscSlots;

图形界面美化

使用 Makeblock Me TFT LCD 显示输入与结果,编写 CommandToTFT() 函数发送指令,便于切换串口连接点。另编写 Cartesian_Setup()、Cartesian_ClearPlotAreas()、Cartesian_Line() 绘制坐标系、清除绘图区、绘制曲线。详细图形函数说明请参阅 Makeblock 手册,此处不赘述。

结语

代码分为带图形界面版和纯控制版两份,方便单独研究 PID 控制实现。正常情况下无负载直流电机最低转速只能降至额定转速的 10-20%,但使用 PID 控制启动后可降至近 5%。

补充 (2018.02.25): 若改用 NPN 三极管,注意电流方向相反:PNP 导通时电流从发射极流向集电极,NPN 则从集电极流向发射极。因此 PNP 极性为 E(+) C(-),NPN 应为 C(+) E(-)。

代码

完整代码(含图形界面版和纯控制版)请见附件或项目页面。

原理图

这是一个原型,用于解释使用 PID 控制器进行直流电机调速及反转时的注意事项。(原文包含原理图图片)

制造工艺

  1. Satellite CCRMA 套件:构建传感器驱动的音频效果器
  2. Arduino Nano + 摇杆控制双步进电机:Visuino 图形化教程
  3. Arduino Uno驱动MAX7219级联8×8 LED矩阵:从入门到动画显示
  4. 校园智能体温监测系统 - 精准、实时、安全的学生健康守护方案
  5. Arduino 8 位并行 IO 端口库:一行代码实现 8 位数字读写
  6. Arduino 64 键原型键盘矩阵:用移位寄存器打造全自定义键盘
  7. Arduino Nano 专用 2.8 英寸 TFT 扩展板 – 320×240 SPI 显示屏
  8. 为Arduino构建隔离模拟输入电路
  9. 低成本 Arduino 闪电探测器制作指南
  10. 适用于 Arduino 项目的智能室内导航机器人套件
  11. 基于 ACS712 传感器的 Arduino 交流电流精准测量(真有效值)
  12. 钨铜合金提升直流电机性能