You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
incubator_embeded/HARDWARE/PID.c

142 lines
3.4 KiB

This file contains ambiguous Unicode characters!

This file contains ambiguous Unicode characters that may be confused with others in your current locale. If your use case is intentional and legitimate, you can safely ignore this warning. Use the Escape button to highlight these characters.

#include "PID.h"
#include "Relays.h"
#include "USART.h"
extern u16 tem;
float cold_tem = 0;
float red_tem = 0;
float ti;
float ki = 0.001;
float kd = 340;
extern u8 hot_clod_flag;
extern u8 gpio_state;
extern int T;
unsigned int num = 0;
PID pid;
u8 rs485speed[8] = {0x01, 0x06, 0x60, 0x00, 0x00, 0x09, 0xBB, 0xAA}; // speed control for compressor controller
int min_speed_count = 1500;
int max_speed_count = 6000;
void PID_Init()
{
// pid.set_tem=tem;//用户设定温度
pid.Kp = 110;
pid.Ki = 0.001;
pid.Kd = 340;
pid.t = 500; // PID计算周期
// pid.Ti=5000000;//积分时间
// pid.Td=1000;//微分时间
pid.pwmcycle = 200; // pwm周期200
pid.OUT0 = 1;
pid.C1ms = 0;
}
void PID_Calc() // pid计算
{
float DelEk; // 最近两次偏差之差
// float td;
float out;
if (pid.C1ms < (pid.t)) // 计算周期未到
{
return;
}
if (pid.set_tem > pid.now_tem)
{
pid.Ek = pid.set_tem - pid.now_tem;
}
else
{
pid.Ek = pid.now_tem - pid.set_tem;
}
pid.Pout = pid.Kp * pid.Ek; // 比例输出
pid.SEk += pid.Ek; // 历史偏差总和
DelEk = pid.Ek - pid.Ek_1; // 最近两次偏差之差
// ti=pid.t/pid.Ti;
// ki=ti*pid.Kp;
pid.Iout = pid.Ki * pid.SEk; // 积分输出
// td=pid.Td/pid.t;
// kd=pid.Kp*td;
pid.Dout = pid.Kd * DelEk; // 微分输出
if (pid.Dout < 0)
{
pid.Dout = 0 - pid.Dout;
}
// out= pid.Pout+pid.Iout+ pid.Dout;
out = pid.Pout;
if (out > pid.pwmcycle)
{
pid.OUT = pid.pwmcycle;
}
else if (out <= 0)
{
pid.OUT = pid.OUT0;
}
else
{
pid.OUT = out;
}
pid.Ek_1 = pid.Ek; // 更新偏差
pid.C1ms = 0;
if (pid.set_tem > pid.now_tem + 1)
{
// 得到当前的偏差值设置温度大于实际温度1℃加热close compressoropen heater
/*GPIO1->报警铃 GPIO3->heater GPIO4—>新风风扇 GPIO5->加湿器 GPIO6->compressor */
HC595_Send_Byte(gpio_state &= 0xDF);//close compressor &=1101 1111 0xDF
num = 0;
TIM_SetCompare3(TIM3, 0);
HC595_Send_Byte(gpio_state |= 0x04); // open heater |=0000 0100 0x04
hot_clod_flag = 2;
pid.Iout = 0;
} else if (pid.now_tem > pid.set_tem)
{
// 得到当前的偏差值设置温度小于实际温度制冷open compressorclose heater
HC595_Send_Byte(gpio_state &= 0xFB); // close heater &=1111 1011 0xFB
// 0-200对应0-100%如果pid.out=50,占空比就是25%//num=50*400/200=100100/400=25%
num = (((pid.OUT * 400) / pid.pwmcycle) - 1); // pid.OUT与pwm占空比的值换算
TIM_SetCompare3(TIM3, num / 4);
// printf("%d\r\n",num);
HC595_Send_Byte(gpio_state|=0x20);//open compressor |=0010 0000
hot_clod_flag = 1;
// pid.Iout=0;
}
if (hot_clod_flag == 1 && T <= tem - 3) // 制冷过程中温度下降低于设定温度0.3℃
{
HC595_Send_Byte(gpio_state&=0xDB);// close compressor and heater &=1101 1011 0xDB
num = 0;
TIM_SetCompare3(TIM3, 0); // close compressor
hot_clod_flag = 0;
}
if (hot_clod_flag == 2 && T >= tem) // while heat, T above tem
{
HC595_Send_Byte(gpio_state&=0xDB);//close compressor and heater &=1101 1011 0xDB
num = 0;
TIM_SetCompare3(TIM3, 0); // close compressor
hot_clod_flag = 0;
}
int out1 = pid.OUT;
// speed count
int speed_count = out1 / 200.0 * (max_speed_count - min_speed_count) + min_speed_count;
if (speed_count > 6000) {
speed_count = 6000;
}
rs485speed[4] = speed_count / 256;
rs485speed[5] = speed_count % 256;
RS485_3_Init(9600);
delay_xms(100);
RS485_3_Send_Data(rs485speed, 8);
// RS485_1_Send_Data_1(rs485speed, 8);
delay_xms(200);
RS485_1_Init(9600);
// HC595_Send_Byte(gpio_state&=0xDB);// close compressor and heater &=1101 1011 0xDB
}