查看: 3205|回复: 0

PID与PWM的占空比之间的关系

[复制链接]

该用户从未签到

发表于 2011-4-4 18:45: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。(KP,KI,KD等系数略,关于PID算法的整数实现我在前文中有论述如何实现)。  

那么经过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控制而来做的。  
/****************************************************/  
void PWMProcess(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) //如果当前电压大于输出电压,减小占空比  
{  
if( ( ADPool.Value_Uint16【UPWMADCH】 - UKTemp ) > UDELTA )  
{  
temp = ADPool.Value_Uint16【UPWMADCH】 - UKTemp; //  
temp = temp / 2; //下降可以加速下降,所以下降参数加倍  
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 )  
{  
temp = UKTemp - ADPool.Value_Uint16【UPWMADCH】;  
temp = temp / 4; //上升处理不要超调,所以每次只+一半  
if( (255-Pwm.DutyCycle_Uint8) > temp )  
{  
Pwm.DutyCycle_Uint8 += (temp/2);  
}  
else  
{  
Pwm.DutyCycle_Uint8 = 255;  
}  
}  
else  
{  
return;  
}  
}  
DisPlayVoltage();  
PWMChangeDuty(Pwm.DutyCycle_Uint8); //改变占空比  
Delay(10,10);  

}  
}  
}
回复

使用道具 举报

您需要登录后才可以回帖 注册/登录

本版积分规则

关闭

站长推荐上一条 /2 下一条



手机版|小黑屋|与非网

GMT+8, 2024-12-25 00:40 , Processed in 0.117030 second(s), 15 queries , MemCache On.

ICP经营许可证 苏B2-20140176  苏ICP备14012660号-2   苏州灵动帧格网络科技有限公司 版权所有.

苏公网安备 32059002001037号

Powered by Discuz! X3.4

Copyright © 2001-2024, Tencent Cloud.