找回密码
 立即注册

QQ登录

只需一步,快速开始

搜索
查看: 17919|回复: 8
打印 上一主题 下一主题
收起左侧

大神教你如何将PID输出结果与PWM占空比一起玩起来

  [复制链接]
跳转到指定楼层
楼主
ID:302252 发表于 2018-4-5 01:45 | 只看该作者 回帖奖励 |倒序浏览 |阅读模式
不论是智能车还是四轴飞行器,都会遇到占空比输出影响并控制输出端控制电压得情况,如何将UK值与PWM占空比值对应起来,进而实现占空比输出和输出控制电压对应?这里分享一些我的经验。

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


分享到:  QQ好友和群QQ好友和群 QQ空间QQ空间 腾讯微博腾讯微博 腾讯朋友腾讯朋友
收藏收藏10 分享淘帖 顶 踩
回复

使用道具 举报

沙发
ID:484435 发表于 2019-8-1 09:41 | 只看该作者
谢谢楼主分享
回复

使用道具 举报

板凳
ID:511461 发表于 2019-8-1 18:56 | 只看该作者
谢谢楼主分享
回复

使用道具 举报

地板
ID:603295 发表于 2019-12-8 01:13 | 只看该作者
非常感谢楼主分享
回复

使用道具 举报

5#
ID:299193 发表于 2020-3-11 01:12 | 只看该作者
谢谢分享!
回复

使用道具 举报

6#
ID:119977 发表于 2022-1-7 16:02 | 只看该作者
也就是PWM的占空比系数为255   敢问255怎么计算出来的
回复

使用道具 举报

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

评分

参与人数 1黑币 +5 收起 理由
戡拤 + 5 赞一个!

查看全部评分

回复

使用道具 举报

8#
ID:61140 发表于 2022-5-18 12:43 | 只看该作者
hewayking 发表于 2022-1-7 16:02
也就是PWM的占空比系数为255   敢问255怎么计算出来的

计算毛线,8位单片机输出最大255,也就是一个字节.比如P1输出1111 1111B,也就等于255,还等于0xff.
回复

使用道具 举报

9#
ID:440028 发表于 2022-5-20 11:49 | 只看该作者
zhmingwang 发表于 2022-1-8 13:29
我把楼主的代码重新格式化了下, 方便阅读

这样更方便初学者了
回复

使用道具 举报

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

手机版|小黑屋|51黑电子论坛 |51黑电子论坛6群 QQ 管理员QQ:125739409;技术交流QQ群281945664

Powered by 单片机教程网

快速回复 返回顶部 返回列表