logo资料库

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

第1页 / 共3页
第2页 / 共3页
第3页 / 共3页
资料共3页,全文预览结束
不论是智能车还是四轴飞行器,都会遇到占空比输出影响并控制输出端控制电压得情况,如何将 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 控制而来做的。 PWMProcess(void) void { uint16 idata temp; uint16 idata UKTemp; temp = 0;
UKTemp = 0; if( Pwm.ChangeFlag_Uint8 != 0 ) //判断是否需要改变占空比 { //是否需要改变占空比和你的被控系统特性有关 Pwm.ChangeFlag_Uint8 = 0; UKTemp = PID.Uk_Uint16 + SwIn.AddValue_Uint16;//计算 UK 控制量 //控制量和计算值以及一个开关量有关,我这里的开关量是系统需要的时候叠 加在控制量上的一个变量。 if(UKTemp>999) { UKTemp = 999; 导致。 在误差以内 } //这里只所以是 999 封顶而不是 1024 是因为我的系统 PWM 的峰值电压是 12V while(1)//如果输出电压和期望电压相差 Delta,则继续调整占空比,直到 { ADChPro(UPWMADCH); if( ADPool.Value_Uint16[UPWMADCH] == UKTemp) { //测量输出电压 return; } if( ADPool.Value_Uint16[UPWMADCH] > UKTemp) //如果当前 电压大于输出电压,减小占空比 { UDELTA ) UKTemp; // if( ( ADPool.Value_Uint16[UPWMADCH] - UKTemp ) > { temp = ADPool.Value_Uint16[UPWMADCH] - temp = temp / 2; //下降可以加速下降, 所以下降参数加倍 -----/*PWM 的系数为 UK/4*/ if( Pwm.DutyCycle_Uint8 > temp ) { Pwm.DutyCycle_Uint8 = Pwm.DutyCycle_Uint8 - temp; } else { } Pwm.DutyCycle_Uint8 = 0; } else { return;
} } else { //如果当前电压小于输出电压 if( ( UKTemp - ADPool.Value_Uint16[UPWMADCH] ) > UDELTA ) ADPool.Value_Uint16[UPWMADCH]; 每次只+一半 { temp = UKTemp - temp = temp / 4; //上升处理不要超调,所以 if( (255-Pwm.DutyCycle_Uint8) > temp ) { Pwm.DutyCycle_Uint8 += (temp/2); } else { Pwm.DutyCycle_Uint8 = 255; } return; } else { } } DisPlayVoltage(); PWMChangeDuty(Pwm.DutyCycle_Uint8); //改变占空比 Delay(10,10); } } }
分享到:
收藏