#include "PID.h" #include "Relays.h" #include "USART.h" #include "rs485.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; int min_speed_count = 1500; int max_speed_count = 6000; void PID_Init() { // pid.set_tem=tem;// user set temperature // if flash have not a vaild value, just set a default value if (pid.Kp < 1e-7) { pid.Kp = 9.6; } if (pid.Ki < 1e-7) { pid.Ki = 0.01; } if (pid.Kd < 1e-7) { pid.Kd = 340; } if (pid.tem_threshold < 0.0001) { pid.tem_threshold = 0.2; } pid.t = 5000; // PID calc period // pid.Ti=5000000;// integral time // pid.Td=1000;// differential time pid.pwmcycle = 200; // pwm cycle 200 pid.OUT0 = 1; pid.C1ms = 0; } /** * set compressor speed count * range of speed count: 0-6000, if speed count lower than 1500, the compressor will stop */ void set_compressor_power(int speed) { u8 data[8] = {0x01, 0x06, 0x60, 0x00, 0x00, 0x09, 0xBB, 0xAA}; // speed control for compressor controller if (speed > 6000) { speed = 6000; } if (speed < 0) { speed = 0; } data[4] = speed / 256; data[5] = speed % 256; GetCRC16(data, 6, data + 6, data + 7); RS485_3_Init(9600); RS485_3_Send_Data(data, 8); delay_xms(30); RS485_1_Init(9600); } /** * set heater percent * range of heater percent: 0-100 */ void set_heater_power(int percent) { u8 data[8] = { 0x10, 0x06, 0x00, 0x01, 0x00, 0x00, 0x00, 0x00 }; if (percent > 100) { percent = 100; } if (percent < 0) { percent = 0; } data[4] = percent / 256; data[5] = percent % 256; GetCRC16(data, 6, data + 6, data + 7); RS485_1_Send_Data(data, 8); delay_xms(30); } /** * heater power calc */ int calc_p(float t_t, float t_c, float error, int p_b, float pid_p, float pid_i) { int p = p_b + pid_p * (t_t - t_c) + pid_i * error; if (p > 100) { return 100; } if (p < 0) { return 0; } return p; } void PID_Calc() // pid calc { pid.Kp = 19.2; pid.Ki = 0.02; int p_base = 52; float DelEk; // The difference between the last two deviations // float td; float out; if (pid.C1ms < (pid.t)) // The calculation cycle has not yet arrived { 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.Ek = pid.now_tem - pid.set_tem; pid.Ek = pid.set_tem - pid.now_tem; pid.Pout = pid.Kp * pid.Ek; // Proportional output pid.SEk += pid.Ek; // Total historical deviation DelEk = pid.Ek - pid.Ek_1; // The difference between the last two deviations // ti=pid.t/pid.Ti; // ki=ti*pid.Kp; pid.Iout = pid.Ki * pid.SEk; // integral output // td=pid.Td/pid.t; // kd=pid.Kp*td; pid.Dout = pid.Kd * DelEk; // difference output 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; // udpate difference pid.C1ms = 0; // heater percent int heater_percent = calc_p(pid.set_tem, pid.now_tem, pid.SEk, p_base, pid.Kp, pid.Ki); // TODO:: temply, set Kd to heater_percent, use for data upload pid.Kd = heater_percent; // speed count // int speed_count = pid.OUT / 200.0 * (max_speed_count - min_speed_count) + min_speed_count; // if (speed_count > 6000) { // speed_count = 6000; // } int speed_count = 1500; // if (pid.now_tem < pid.set_tem + pid.tem_offset - pid.tem_threshold) // { // // Obtain the current deviation value // // when the target temperature is 1 degree Celsius higher than the actual temperature, heat up // // close compressor open heater // /*GPIO1->Alarm bell GPIO3->heater GPIO4->Fresh air fan GPIO5->humidifier GPIO6->compressor */ // // HC595_Send_Byte(gpio_state &= 0xDF);//close compressor &=1101 1111 0xDF // HC595_Send_Byte(gpio_state |= 0x04); // open heater |=0000 0100 0x04 // speed_count = 1500; // hot_clod_flag = 2; // pid.Iout = 0; // } else if (pid.now_tem > pid.set_tem + pid.tem_offset - pid.tem_threshold && pid.now_tem < pid.set_tem + pid.tem_offset + pid.tem_threshold) // { // HC595_Send_Byte(gpio_state &= 0xFB); // close heater &=1111 1011 0xFB // speed_count = 1000; // close compressor // hot_clod_flag = 0; // // pid.Iout=0; // } else if (pid.now_tem > pid.set_tem + pid.tem_offset + pid.tem_threshold) // { // // Obtain the current deviation value // // when the target temperature is lower than the actual temperature, refrigerate // // open compressor close heater // HC595_Send_Byte(gpio_state &= 0xFB); // close heater &=1111 1011 0xFB // // // 0-200 correspond 0-100%, if pid.out=50, percentage means 25% //num=50*400/200=100 100/400=25% // // num = (((pid.OUT * 400) / pid.pwmcycle) - 1); // Conversion of pid.OUT and PWM Duty Cycle Values // // 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; // } set_compressor_power(speed_count); set_heater_power(heater_percent); // if (hot_clod_flag == 1 && T <= tem - 3) // During the refrigeration process, the actual temperature drops by 0.3 degrees Celsius below the set temperature // { // HC595_Send_Byte(gpio_state&=0xDB);// close compressor and heater &=1101 1011 0xDB // // num = 0; // // TIM_SetCompare3(TIM3, 0); // close compressor // speed_count = 1000; // 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; // } // HC595_Send_Byte(gpio_state&=0xDB);// close compressor and heater &=1101 1011 0xDB }