|
本帖最后由 STCunio 于 2014-9-19 23:59 编辑
快点来排队吧,PID库开源了
http://www.geek-workshop.com/thread-10890-1-1.html
PID库
3.9.1 pidbegin(int a,int b,int c)
概述
pidbegin函数的作用是将a、b、c三个参数进行赋值,这三个参数的定义参考上述内容。一般的kp、ki、kd是浮点数,那么a、b、c也是浮点型,所以要在使用pidbegin函数之前需要将a、b、c三个参数进行Q15格式化,即左移15次转换成int,最后我们只需将结果右移15次即可还原。如果使用浮点数来进行PID运算也是可以的,但是浮点数运算会占用大量的时间和存储空间,无论是MCU还是DSP选择整型运算要比浮点运算优越很多。
语法
pidbegin(int a,int b,int c)
参数
a:Q15(Kp + Ki + Kd),int型
b:Q15(-(Kp + 2*Kd),int型
c:Q15(Kd),int型
返回值
无
boostpower.c
#define PID_BOOST_KP 0.23
#define PID_BOOST_KI 0.03
#define PID_BOOST_KD 0.00
//Q15格式转换,无需用float型计算PID
#define PID_BOOST_A Q15(PID_BOOST_KP + PID_BOOST_KI + PID_BOOST_KD)
#define PID_BOOST_B Q15(-1 *(PID_BOOST_KP + 2 * PID_BOOST_KD))
#define PID_BOOST_C Q15(PID_BOOST_KD)
#define BOOST_ADC_ERROR 0x00//采样误差
#if VCC_Vol==VCC3V3
#define PID_BOOST_VOLTAGE_REFERENCE 284 - BOOST_ADC_ERROR//电阻比为:10K/(100K+10K),基准电压为10V
#elif VCC_Vol==VCC5V0
#define PID_BOOST_VOLTAGE_REFERENCE 187 - BOOST_ADC_ERROR//电阻比为:10K/(100K+10K),基准电压为10V
#endif
unsigned int BoostMeasuredOutput = 0;
unsigned int BoostSoftstartIncrement = 0;
extern u16 j;
int referenceInput;
void BoostVoltageLoop(void)
{
pidbegin(PID_BOOST_A,PID_BOOST_B,PID_BOOST_C); //准备PID运算
}
void BoostSoftStartRoutine(void)
{
BoostMeasuredOutput =analogRead(0);//保留第一次采样值
referenceInput=BoostMeasuredOutput;
ADC_CONTR = (ADC_CONTR & 0xe0) | ADC_START | 0;//再次启动AD采样,从此将进入AD中断处理,analogRead不再使用
EADC=1;//打开AD采样中断
PADC = 1;//AD中断高优先级
BoostSoftstartIncrement = ((PID_BOOST_VOLTAGE_REFERENCE - BoostMeasuredOutput) / 50 );//软启动
while(referenceInput<=PID_BOOST_VOLTAGE_REFERENCE)
{
delay_ms(1);
referenceInput+=BoostSoftstartIncrement;//慢慢将电压升起来
}
referenceInput=PID_BOOST_VOLTAGE_REFERENCE;
}
主程序
/*外部变量声明*/
extern long controlOutput;
extern int referenceInput;
/*变量声明*/
int val;
u16 pwm0;
u16 j;
void main()
{
u8 i;
u16 m;
Serialbegin(2400);//打开串口
SPIbegin();//SPI功能暂时没用上,使用的是shiftOut来驱动液晶
SPIsetBitOrder(MSBFIRST);
SPIsetClockDivider(SPI_CLOCK_DIV16);
SPIsetDataMode(SPI_MODE1);
SPIend();
backlight_on;
initial_lcd();
clear_screen(); //clear all dots
display_string_8x16(4,10,"Hello STCunio!");/*在第4 页,第16 列显示字符串*/
delay_ms(3000);
clear_screen(); //clear all dots
display_string_8x16(1,20,"STCunio R1");/*在第4 页,第16 列显示字符串*/
display_string_8x16(4,10,"ADCvalue:");/*在第3 页,第10 列显示字符串*/
display_string_8x16(6,10,"voltage:");/*在第5 页,第10 列显示字符串*/
pinMode(5,OutPP);//将PWM输出设为推挽
digitalWrite(5,0);//启动时先将PWM拉低,关掉MOSFET
analogWrite(5,0,PCA_Clock_1T); //设定pwm的频率为主时钟/256,主时钟频率为33.1776MHz时PWM频率为12.96K
BoostVoltageLoop();
BoostSoftStartRoutine();
loop()
{
val = j; // read the input pin
i=val/1000+'0';//分离千位
display_string_8x16(4,(10+8*9),&i);
i=val%1000/100+'0';//分离百位
display_string_8x16(4,(10+8*10),&i);
i=val%100/10+'0';//分离十位
display_string_8x16(4,(10+8*11),&i);
i=val%10+'0';//分离个位
display_string_8x16(4,(10+8*12),&i);
m=val;
m=(m*5*11*5)>>9;
i=m/100+'0';//分离百位
display_string_8x16(6,(10+8*9),&i);
i=m%100/10+'0';//分离十位
display_string_8x16(6,(10+8*10),&i);
display_string_8x16(6,(10+8*11),".");
i=m%10+'0';//分离个位
display_string_8x16(6,(10+8*12),&i);
display_string_8x16(6,(10+8*13),"V");
//delay_ms(50);//延时50ms
}
}
//========================================================================
// 函数: void ADC_int(void) interrupt ADC_VECTOR
// 描述: ADC中断函数.
// 参数: none.
// 返回: none.
// 版本: V1.0, 2012-10-22
//========================================================================
void ADC_int (void) interrupt ADC_VECTOR
{
//long controlOutput1=0;
ADC_CONTR &= ~ADC_FLAG;//清标志位
j = (u16)(ADC_RES & 3);//读出AD值
j = (j << 8) | ADC_RESL;
if((j<200)&&(j>37))
{
pid(referenceInput,j);
pwm0=controlOutput>>15;//Q15格式还原
if (pwm0>150)pwm0=150; //设定上限值
}
else
{
controlOutput=0;
pwm0=0;
}
if(pwm0==0)
{
PWM0_OUT_0();//PWM的值为0
pwm0=1;
}
else
PWM0_NORMAL();
UpdatePwm(0,256-pwm0);//更新PWM的值,pwm0为低电平的值,最大255,最小0
ADC_CONTR = (ADC_CONTR & 0xe0) | ADC_START | 0; //每次AD中断完都要启动一次AD转换来进行下一下中断
} |
本帖子中包含更多资源
您需要 登录 才可以下载或查看,没有帐号?注册
x
|