首页 论坛 技术交流专区 物联网 大神教你如何将PID输出结果与PWM占空比一起玩起来

发帖 回复

[分享] 大神教你如何将PID输出结果与PWM占空比一起玩起来
1160 查看
2 回复
 楼主 | 发布于 2018-03-31 | 只看楼主
分享到:
不论是智能车还是四轴飞行器,都会遇到占空比输出影响并控制输出端控制电压得情况,如何将UK值与PWM占空比值对应起来,进而实现占空比输出和输出控制电压对应?这里分享一些我的经验。


先在这里说一下我的思路,后面还有论坛里面一篇很不错的增量PID教程。

前提条件:
(讨论的是输出控制的是电压,不是PWM方波。而PWM输出后要经过滤波整形再输出控制)
输出电压控制电压范围是0-10V。
给定、反馈、输出电压采样输入电压范围是0-5V(经过运放)。
使用单片机AD为10位AD芯片
那么10位AD芯片电压采集得到的数据范围就是0-1024。
PWM为 8位可调占空比方波,0对应输出占空比为0的方波,255对应输出占空比100%的方波,127对应输出50%的方波。

比如:
当前给定是2.5V,反馈电压是1V

那么经过AD采样
1、给定2.5V对应为 512
2、反馈1V对应为 205
假定经过PID计算得到的UK为400
也就意味着输出电压应当为(400*(UPWM峰值电压))/1024

那么UK对应的PWM占空比是多少呢?
我们知道,UK=1024对应占空比为100,也就是PWM的占空比系数为255。可知,PWM系数 = UK/4;
那么400就应当对应系数 400/4=100。
也就是输出电压=400*10/1024=3.9V

同时,由于采样精度以及PWM输出占空比精度控制的问题,将导致输出电压和期望值不是那么线性,所以,我在项目内加入了输出电压采样的控制。

采样AD输入为0-5V,所以,对于输出0-10V有一个缩小的比例。
输出10V则采样值对应为255
输出5V则采样之对应127
可知,3.9V对应AD结果为97
采样输出电压值,可以针对性的调整一下占空比输出,从而得到误差允许范围内的一个控制输出电压。

同时,经过一些加速控制的手段。可以比较迅速的达到控制的目的。
下文中的UK控制方法是针对增量式PID控制而来做的。


  1. void    PWMProcess(void)
  2. {
  3.     uint16 idata temp;
  4.     uint16 idata UKTemp;
  5.           temp = 0;
  6.     UKTemp = 0;
  7.    
  8.     if( Pwm.ChangeFlag_Uint8 != 0 )   //判断是否需要改变占空比
  9.                 {                  //是否需要改变占空比和你的被控系统特性有关
  10.                         Pwm.ChangeFlag_Uint8 = 0;
  11.         
  12.                         UKTemp = PID.Uk_Uint16 + SwIn.AddValue_Uint16;//计算UK控制量
  13.                         //控制量和计算值以及一个开关量有关,我这里的开关量是系统需要的时候叠加在控制量上的一个变量。
  14.                         if(UKTemp>999)
  15.                         {
  16.                                 UKTemp = 999;
  17.                         } //这里只所以是999封顶而不是1024是因为我的系统PWM的峰值电压是12V导致。
  18.                         while(1)//如果输出电压和期望电压相差 Delta,则继续调整占空比,直到在误差以内
  19.                         {
  20.                                 ADChPro(UPWMADCH);          //测量输出电压
  21.                                 if( ADPool.Value_Uint16[UPWMADCH] == UKTemp)
  22.                                 {
  23.                                         return;
  24.                                 }
  25.                                 if( ADPool.Value_Uint16[UPWMADCH] > UKTemp)   //如果当前电压大于输出电压,减小占空比
  26.                                 {
  27.                                         if( ( ADPool.Value_Uint16[UPWMADCH] - UKTemp ) > UDELTA )
  28.                                         {
  29.                                                 temp = ADPool.Value_Uint16[UPWMADCH] - UKTemp;  //
  30.                                                 temp = temp / 2;       //下降可以加速下降,所以下降参数加倍  -----/*PWM的系数为UK/4*/
  31.                                                 if( Pwm.DutyCycle_Uint8 > temp )
  32.                                                 {
  33.                      Pwm.DutyCycle_Uint8 = Pwm.DutyCycle_Uint8 - temp;
  34.                                                 }
  35.                                                 else
  36.                                                 {
  37.                     Pwm.DutyCycle_Uint8 = 0;
  38.                                                 }
  39.                                         }
  40.                                         else
  41.                                         {
  42.                   return;
  43.                                         }
  44.                                 }
  45.                                 else           //如果当前电压小于输出电压
  46.                                 {
  47.                                         if( ( UKTemp - ADPool.Value_Uint16[UPWMADCH] ) > UDELTA )
  48.                                         {
  49.                                                 temp = UKTemp - ADPool.Value_Uint16[UPWMADCH];
  50.                                                 temp = temp / 4;  //上升处理不要超调,所以每次只+一半
  51.                                                 if( (255-Pwm.DutyCycle_Uint8) > temp )
  52.                                                 {
  53.                     Pwm.DutyCycle_Uint8 += (temp/2);
  54.                                                 }
  55.                                                 else
  56.                                                 {
  57.                     Pwm.DutyCycle_Uint8 = 255;
  58.                                                 }
  59.                                         }
  60.                                         else
  61.                                         {
  62.                   return;
  63.                                         }
  64.                                 }
  65.                                 DisPlayVoltage();
  66.                                 PWMChangeDuty(Pwm.DutyCycle_Uint8);  //改变占空比
  67.                                 Delay(10,10);
  68.                         }
  69.                 }
  70. }
复制代码

最后附上一个坛子里面写的很不错的增量PID教程:
【教程】如何在STM32上实现增量式PID转
http://bbs.elecfans.com/jishu_484125_1_1.html
(0 ) (0 )
回复 举报

回复于 2018-03-31 沙发

感谢分享
(0 )
评论 (0) 举报

回复于 2018-03-31 2#

不错,多谢分享!!!
(0 )
评论 (0) 举报
  • 发表回复
    0/3000





    举报

    请选择举报类别

    • 广告垃圾
    • 违规内容
    • 恶意灌水
    • 重复发帖

    全部板块

    返回顶部