#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 = 1000; // 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); delay_xms(30); 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_Init(9600); delay_xms(30); RS485_1_Send_Data(data, 8); delay_xms(30); } /** * heater power calc */ int calc_hp(float t_t, float t_c, float Error_calc, int p_hb, float pid_hp, float pid_hi) { int p_h = p_hb + pid_hp * (t_t - t_c) + pid_hi * Error_calc; if (p_h > 100) { return 100; } if (p_h < 0) { return 0; } return p_h; } /** * compressor power percent calc */ int calc_cp(float t_t, float t_c, int p_cb, float pid_cp) { int percent = p_cb + pid_cp * (t_c - t_t); if (percent > 100) { return 100; } if (percent < 0) { return 0; } return percent; } /** * compressor speed calc */ int calc_compressor_speed(int percent, int v_min, int v_max) { int v = percent * v_max / 100.0; if (v > v_max) { return v_max; } if (v < v_min) { return v_min; } return v; } void PID_Calc() // pid calc { float Kp = 19.2; float Ki = 0.08; int p_hb = 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; // } pid.Ek = pid.set_tem - pid.now_tem; pid.Pout = pid.Kp * pid.Ek; // Proportional output pid.SEk += pid.Ek; // Total historical deviation // SEk limit, updated func float delta_t = pid.set_tem - pid.now_tem; float pid_hp = Kp; float pid_hi = Ki; if (pid.SEk < - p_hb / pid_hi) { pid.SEk = - p_hb / pid_hi; } float Error_calc = pid.SEk; if (Error_calc < - (p_hb + pid_hp * delta_t) / pid_hi) { Error_calc = - (p_hb + pid_hp * delta_t) / pid_hi; } 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_hp(pid.set_tem, pid.now_tem, Error_calc, p_hb, pid_hp, pid_hi); int p_c = calc_cp(pid.set_tem, pid.now_tem, 32, Kp); int speed_count = calc_compressor_speed(p_c, 1500, 4500); // TODO:: temply, set Ki to speed count, Kd to heater_percent, use for data upload pid.Ki = speed_count; pid.Kd = heater_percent; set_compressor_power(speed_count); set_heater_power(heater_percent); }