diff --git a/src/pid.c b/src/pid.c --- a/src/pid.c +++ b/src/pid.c @@ -3,23 +3,64 @@ // #include "pid.h" +#include "flash.h" // PID implementation -void pid_init(pid_state_t* state) +static pid_state_t state; + + +void pid_init() { - state->i_state = 0; - state->last_pid_temp = 0; - state->last_pid_temp_frac = 0; + state.i_state = 0; + state.last_pid_temp = 0; + state.last_pid_temp_frac = 0; } -int16_t pid_update(therm_settings_t* set, therm_status_t* status, pid_state_t *state) +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_HEATER) + 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[6]; + itoa(ssr_output, tempstr, 10); + ssd1306_drawstring(tempstr, 0, 90); + } + else + { + ssr_output = 0.0; + } + + return 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 - int8_t temp_frac = status->temp_frac > 9 ? status->temp_frac / 10 : status->temp_frac; - temp_frac = status->temp > 0 ? temp_frac : temp_frac * -1; - int32_t temp = (status->temp * 10) + temp_frac; + float temp = status->temp; // Calculate instantaneous error int16_t error = status->setpoint * 10 - temp; // TODO: Use fixed point fraction @@ -28,7 +69,7 @@ int16_t pid_update(therm_settings_t* set int32_t p_term = set->val.k_p * error; // Error accumulator (integrator) - state->i_state += error; + state.i_state += error; // to prevent the iTerm getting huge from lots of // error, we use a "windup guard" @@ -39,18 +80,18 @@ int16_t pid_update(therm_settings_t* set 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; + 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; - int32_t i_term = set->val.k_i * state->i_state; + 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)); + int32_t d_term = (set->val.k_d * (temp - state.last_pid_temp)); // Save temperature for next iteration - state->last_pid_temp = temp; + state.last_pid_temp = temp; int16_t result = (p_term + i_term - d_term) / 10;