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.
286 lines
5.7 KiB
286 lines
5.7 KiB
#include <math.h>
|
|
#include <stdlib.h>
|
|
#include "PID.h"
|
|
#include "Relays.h"
|
|
#include "USART.h"
|
|
#include "rs485.h"
|
|
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 = 2000;
|
|
int max_speed_count = 4800;
|
|
|
|
/**
|
|
* PID init
|
|
*/
|
|
void PID_Init()
|
|
{
|
|
// // 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.Ek = 0;
|
|
pid.Ek_prev = 0;
|
|
pid.SEk = 0;
|
|
pid.Pout = 0;
|
|
pid.Iout = 0;
|
|
pid.Dout = 0;
|
|
pid.OUT = 0;
|
|
pid.OUT0 = 0;
|
|
|
|
pid.h_percent = 0;
|
|
pid.c_speed = 0;
|
|
|
|
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;
|
|
|
|
pid.max_compressor_tem = 30;
|
|
|
|
|
|
|
|
pid.hp_h = 6;
|
|
pid.hi_h = 0.02;
|
|
pid.hd_h = 0;
|
|
pid.h_base_h = 0;
|
|
|
|
pid.hp_l = 7.2;
|
|
pid.hi_l = 0.04;
|
|
pid.hd_l = 0;
|
|
pid.h_base_l = 53;
|
|
|
|
pid.cp = 4;
|
|
pid.ci = 0.01;
|
|
pid.cd = 0;
|
|
pid.c_base = 37;
|
|
|
|
|
|
|
|
|
|
}
|
|
|
|
/**
|
|
* 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 > max_speed_count) {
|
|
speed = max_speed_count;
|
|
}
|
|
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 delta_t, float Error_calc, float DelEk, int p_hb, float pid_hp, float pid_hi, float pid_hd) {
|
|
int p_h = p_hb + pid_hp * delta_t + pid_hi * Error_calc + pid_hd * DelEk;
|
|
if (p_h > 100) {
|
|
return 100;
|
|
}
|
|
if (p_h < 0) {
|
|
return 0;
|
|
}
|
|
return p_h;
|
|
}
|
|
|
|
/**
|
|
* compressor power percent calc
|
|
*/
|
|
int calc_cp(float delta_t, float Error_calc, float DelEk, int cb, float cp, float ci, float cd) {
|
|
int percent = cb - cp * delta_t + ci * Error_calc + cd * DelEk;
|
|
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
|
|
{
|
|
// int min_speed_count = 1800;
|
|
// int max_speed_count = 4800;
|
|
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;
|
|
// }
|
|
|
|
float delta_t = pid.set_tem - pid.now_tem;
|
|
|
|
float hp = pid.hp_h;
|
|
float hi = pid.hi_h;
|
|
float hd = pid.hd_h;
|
|
int h_base = pid.h_base_h;
|
|
|
|
// if now temp is close to set temp, the heater will be less power
|
|
if (pid.set_tem - pid.now_tem < 3) {
|
|
hp = pid.hp_h * 0.6;
|
|
}
|
|
if (pid.set_tem - pid.now_tem < 1) {
|
|
hp = pid.hp_h * 0.3;
|
|
}
|
|
|
|
// l mode
|
|
if (pid.set_tem <= pid.max_compressor_tem) {
|
|
hp = pid.hp_l;
|
|
hi = pid.hi_l;
|
|
hd = pid.hd_l;
|
|
h_base = pid.h_base_l;
|
|
}
|
|
|
|
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_prev; // The difference between the last two deviations
|
|
|
|
// no integral when the deviation is too large
|
|
if (pid.now_tem < pid.set_tem - 3) {
|
|
pid.SEk = 0;
|
|
}
|
|
|
|
|
|
|
|
// SEk limit, updated func, remain a little heater power when the compressor is running in full state
|
|
if (pid.SEk < - (h_base / 2) / hi) {
|
|
pid.SEk = - (h_base / 2) / hi;
|
|
}
|
|
if (pid.c_speed == max_speed_count) {
|
|
pid.SEk = 0;
|
|
}
|
|
float Error_calc = pid.SEk;
|
|
if (Error_calc < - (h_base + hp * delta_t) / hi) {
|
|
Error_calc = - (h_base + hp * delta_t) / hi;
|
|
}
|
|
if (pid.c_speed == max_speed_count) {
|
|
Error_calc = 0;
|
|
}
|
|
|
|
|
|
|
|
// 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;
|
|
}
|
|
|
|
// When the target tem is greater then max compressor tem, the compressor will stop
|
|
if (pid.set_tem > pid.max_compressor_tem) {
|
|
pid.c_speed = 0;
|
|
} else {
|
|
// if outer temp is got, we calc pid by outer temp
|
|
if (abs(pid.out_tem) > 1e-5) {
|
|
pid.cp = (pid.out_tem - pid.set_tem) / 4.3 + 0.7;
|
|
}
|
|
// use nagetive error and error diff when calc compressor power
|
|
int p_c = calc_cp(delta_t, - Error_calc, - DelEk, pid.c_base, pid.cp, pid.ci, pid.cd);
|
|
pid.c_speed = calc_compressor_speed(p_c, min_speed_count, max_speed_count);
|
|
}
|
|
|
|
// heater percent
|
|
pid.h_percent = calc_hp(delta_t, Error_calc, DelEk, h_base, hp, hi, hd);
|
|
// close heater when compressor is running in full state
|
|
if (pid.c_speed == max_speed_count) {
|
|
pid.h_percent = 0;
|
|
}
|
|
|
|
set_compressor_power(pid.c_speed);
|
|
set_heater_power(pid.h_percent);
|
|
|
|
|
|
pid.Ek_prev = pid.Ek; // udpate difference
|
|
pid.C1ms = 0;
|
|
|
|
}
|