本帖最后由 fktry 于 2019-2-25 21:32 编辑
在做一个恒温控制系统,使用灯泡加热温度,DS18B20采集实时温度。
下面这张图片是在出现超调之后,温度自然下降的过程当中,出现的一个问题。像是程序出现的bug。
PID参数参数值
从左到右第一个数值是PID的最终输出,P代表P值,依次类推。
这是主函数:
#include "sys.h"
#include "delay.h"
#include "usart.h"
#include "led.h"
#include "lcd.h"
#include "ds18b20.h"
#include "pid.h"
#include "timer.h"
#include "key.h"
#include "exti.h"
u8 SetValue=30;
PID pid;
int main(void)
{
u8 t=0,key;
short temperature;
float temperature1;
NVIC_PriorityGroupConfig(NVIC_PriorityGroup_2);//设置系统中断优先级分组2
delay_init(168); //初始化延时函数
uart_init(115200); //初始化串口波特率为115200
TIM3_Int_Init(100,8400-1); //定时器3初始化,每两百毫秒更新一次数据
KEY_Init(); //按键初始化
EXTIX_Init(); //中断初始化
PID_Init(); //PID初始化
LED_Init(); //初始化LED
LCD_Init(); //LCD初始化
POINT_COLOR=RED; //设置字体为红 {MOD}
LCD_ShowString(30,70,200,16,16,"Set Value:"); //显示设置值提示字母
LCD_ShowString(30,110,200,16,16,"Current Value:"); //显示当前值提示字母
LCD_ShowString(30,150,200,16,16,"PID OUT:"); //显示PID值
while(DS18B20_Init()) //DS18B20初始化
{
LCD_ShowString(30,30,200,16,16,"DS18B20 Error");
delay_ms(200);
LCD_Fill(30,30,239,130+16,WHITE);
delay_ms(200);
}
LCD_ShowString(30,30,200,16,16,"DS18B20 OK");
POINT_COLOR=BLUE;//设置字体为蓝 {MOD}
LCD_ShowString(140,110,200,16,16," . C");
while(1)
{
key=KEY_Scan(0);
if(key)
{
switch(key)
{
case 1: SetValue+=5; break; //设定值自加5
case 2: SetValue-=5; break; //设定值自减5
case 3: SetValue=30; break; //回到原来的设定值
}
}
pid.Sv=SetValue; //将设定值赋给结构体
LCD_ShowNum(110,70,SetValue,2,16); //显示设定值
if(t%10==0)//每100ms读取一次
{
temperature=DS18B20_Get_Temp();
temperature1= DS18B20_Get_Temp(); //将当前值赋给结构体
pid.Pv=temperature1/10;
if(temperature<0)
{
LCD_ShowChar(100+40,110,'-',16,0); //显示负号
temperature=-temperature; //转为正数
}else LCD_ShowChar(100+40,110,' ',16,0); //去掉负号
LCD_ShowNum(100+40+8,110,temperature/10,2,16); //显示正数部分
LCD_ShowNum(100+40+32,110,temperature%10,1,16); //显示小数部分
}
delay_ms(10);
t++;
if(t==40)
{
t=0;
LED0=!LED0;
PID_Calc(); //每200毫秒,计算PID
LCD_ShowNum(100,150,pid.OUT,2,16); //显示整数部分
// LCD_ShowNum(100,190,pid.Iout,2,16);
printf("%2.1F
",pid.OUT);
printf(" P:%2.2F
",pid.Pout);
printf(" I:%2.2F
",pid.Iout);
printf(" D:%2.2F
",pid.Dout);
}
}
}
这是PID.C里边的代码
#include "pid.h"
#include "sys.h"
void PID_Init(void)//PID参数初始化函数
{
pid.Kp=50; //比例系数
pid.T=500; //PID计算周期
pid.Ti=5000; //积分时间
pid.Td=1500; //微分时间
pid.OUT0=2;
}
void PID_Calc(void) //pid计算函数
{
float Dk;
float OUT;
pid.Ek=pid.Sv-pid.Pv; //得到当前偏差值
pid.Pout=pid.Kp*pid.Ek; //比例输出
pid.SEk+=pid.Ek; //历史偏差总和
Dk=pid.Ek-pid.Ek_1; //最近两次偏差之差
pid.Iout=pid.Kp*pid.T/pid.Ti*pid.SEk; //积分输出
pid.Dout=pid.Kp*pid.Td/pid.T*Dk; //微分输出
//
OUT=pid.Pout+pid.Iout+pid.Dout+pid.OUT0; //本次的计算结果
if(OUT>90) //PID输出限幅
{
OUT=90;
}
if(OUT<10)
{
OUT=10;
}
pid.OUT=OUT;
pid.Ek_1=pid.Ek; // 更新偏差
}
一周热门 更多>