Files
@ 7fc667dd7f38
Branch filter:
Location: therm-ng/src/pid.c - annotation
7fc667dd7f38
2.7 KiB
text/plain
Decent working pid
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 | 72630eaa8151 72630eaa8151 72630eaa8151 72630eaa8151 a710d1e0fc2a 2b4eb31dd8da a710d1e0fc2a a710d1e0fc2a a710d1e0fc2a 2b4eb31dd8da 2b4eb31dd8da 2b4eb31dd8da 2b4eb31dd8da a710d1e0fc2a 2b4eb31dd8da 2b4eb31dd8da 2b4eb31dd8da a710d1e0fc2a a710d1e0fc2a 2b4eb31dd8da a710d1e0fc2a a710d1e0fc2a f602474ad6c6 2b4eb31dd8da 2b4eb31dd8da 2b4eb31dd8da 2b4eb31dd8da 2b4eb31dd8da 2b4eb31dd8da f602474ad6c6 2b4eb31dd8da 2b4eb31dd8da f602474ad6c6 f602474ad6c6 f602474ad6c6 f602474ad6c6 2b4eb31dd8da 7fc667dd7f38 f602474ad6c6 2b4eb31dd8da f602474ad6c6 f602474ad6c6 2b4eb31dd8da f602474ad6c6 f602474ad6c6 7fc667dd7f38 7fc667dd7f38 7fc667dd7f38 f602474ad6c6 f602474ad6c6 f602474ad6c6 f602474ad6c6 f602474ad6c6 2b4eb31dd8da f153d4ca027c 2b4eb31dd8da 2b4eb31dd8da 2b4eb31dd8da 2b4eb31dd8da 2b4eb31dd8da 2b4eb31dd8da 2b4eb31dd8da f602474ad6c6 f602474ad6c6 a710d1e0fc2a f602474ad6c6 7fc667dd7f38 7fc667dd7f38 a710d1e0fc2a f602474ad6c6 f602474ad6c6 a710d1e0fc2a f602474ad6c6 f602474ad6c6 a710d1e0fc2a f602474ad6c6 f602474ad6c6 f602474ad6c6 f602474ad6c6 f602474ad6c6 f602474ad6c6 7fc667dd7f38 a710d1e0fc2a f602474ad6c6 f602474ad6c6 2b4eb31dd8da f602474ad6c6 2b4eb31dd8da a710d1e0fc2a 7fc667dd7f38 7fc667dd7f38 7fc667dd7f38 7fc667dd7f38 f602474ad6c6 a710d1e0fc2a f602474ad6c6 f602474ad6c6 a710d1e0fc2a f602474ad6c6 f602474ad6c6 a710d1e0fc2a f602474ad6c6 a710d1e0fc2a f602474ad6c6 f602474ad6c6 f602474ad6c6 f602474ad6c6 f602474ad6c6 a710d1e0fc2a f602474ad6c6 f602474ad6c6 a710d1e0fc2a a710d1e0fc2a a710d1e0fc2a | //
// PID: proportional/integral/derivative controller
//
#include "pid.h"
#include "flash.h"
// PID implementation
static pid_state_t state;
void pid_init()
{
state.i_state = 0;
state.last_pid_temp = 0;
state.last_pid_temp_frac = 0;
}
float pid_process(void)
{
// #ifdef MAX31865_RTD_SENSOR
// max31865_readtemp(spi_get(), &set, &status);
// #else
// max31855_readtemp(spi_get(), &set, &status); // Read MAX31855
// #endif
float ssr_output = 0;
if(runtime_status()->pid_enabled)
{
// Get ssr output for next time
int16_t power_percent = pid_update();
if(flash_getsettings()->val.plant_type == PLANT_COOLER)
power_percent *= -1;
//power-percent is 0-1000?
ssr_output = power_percent; //(((uint32_t)SSR_PERIOD * (uint32_t)10 * (uint32_t)100) * power_percent) / (uint32_t)1000000;
// put ssr output on display
ssd1306_drawstring(" ", 0, 90); //fixme: this is bad, but I can't get the old digits to clear otherwise
char tempstr[8];
snprintf(tempstr, 8, "%4.1f%%", ssr_output/10.0);
ssd1306_drawstring(tempstr, 0, 85);
}
else
{
ssr_output = 0.0;
}
return ssr_output; //ssr_output;
}
int16_t pid_update(void)
{
therm_status_t* status = runtime_status();
therm_settings_t* set = flash_getsettings();
// Convert temperature to fixed point number with 1/10th resolution
float temp = status->temp;
// Calculate instantaneous error
// EMZ FIXME: was regulating to 1 degree below the setpoint! +1 accomadates for this
int16_t error = (status->setpoint+1) - temp;
// Proportional component
int32_t p_term = set->val.k_p * error;
// Error accumulator (integrator)
state.i_state += error;
// to prevent the iTerm getting huge from lots of
// error, we use a "windup guard"
// (this happens when the machine is first turned on and
// it cant help be cold despite its best efforts)
// not necessary, but this makes windup guard values
// relative to the current iGain
int32_t windup_guard_res = (set->val.windup_guard * 10) / set->val.k_i;
// Calculate integral term with windup guard
if (state.i_state > windup_guard_res)
state.i_state = windup_guard_res;
else if (state.i_state < -windup_guard_res)
state.i_state = -windup_guard_res;
// Discard I if we've achieved the setpoint (TODO: add setting disable/enable)
if(error <= 0)
state.i_state = 0;
int32_t i_term = set->val.k_i * state.i_state;
// Calculate differential term (slope since last iteration)
int32_t d_term = (set->val.k_d * (temp - state.last_pid_temp));
// Save temperature for next iteration
state.last_pid_temp = temp;
int16_t result = (p_term + i_term - d_term) / 10;
// Put out tenths of percent, 0-1000.
if(result > 1000)
result = 1000;
else if(result < -1000)
result = -1000;
// Return feedback
return result;
}
|