# HG changeset patch # User matthewreed # Date 2015-12-23 22:37:10 # Node ID db81b1787e6eb44aa20c3d860eb12ac08cea7706 # Parent b41e2aea6dd8d3f4bc289a34580a01ec1045428f Cleaned up pid code and several other todos diff --git a/display.c b/display.c --- a/display.c +++ b/display.c @@ -335,7 +335,7 @@ void display_process(therm_settings_t* s status->state = STATE_IDLE; } else { - user_input_signed((int16_t*)(&set->val.temp_offset)); + user_input_signed(&set->val.temp_offset); } // Event Handler @@ -354,7 +354,7 @@ void display_process(therm_settings_t* s draw_setpoint(status); status->pid_enabled = 1; - status->setpoint = set->val.setpoint_brew; + status->setpoint = set->val.setpoint_brew; // Button handler if(SW_BTN_PRESSED) { @@ -380,7 +380,7 @@ void display_process(therm_settings_t* s //ssd1306_drawlogo(); draw_setpoint(status); status->pid_enabled = 1; - status->setpoint = set->val.setpoint_brew; + status->setpoint = set->val.setpoint_brew; // Button handler if(SW_BTN_PRESSED) { @@ -567,4 +567,10 @@ static void draw_setpoint(therm_status_t temp_last = status->temp; } +void display_startup_screen() { + ssd1306_clearscreen(); + ssd1306_drawstring("therm v0.2", 1, 40); + ssd1306_drawstring("protofusion.org/therm", 3, 0); +} + // vim:softtabstop=4 shiftwidth=4 expandtab diff --git a/display.h b/display.h --- a/display.h +++ b/display.h @@ -15,6 +15,7 @@ #include "max31865.h" #endif +void display_startup_screen(); void display_process(therm_settings_t* set, therm_status_t* status); #endif diff --git a/gpio.c b/gpio.c --- a/gpio.c +++ b/gpio.c @@ -21,17 +21,19 @@ void user_input(uint16_t* to_modify) // Increment/decrement signed variable with up/down buttons -void user_input_signed(int16_t* to_modify) +void user_input_signed(int32_t* to_modify) { - // TODO: Bounds check on int16_t + //fixme: need to cast to 16/32 bits correctly if(CHANGE_ELAPSED) { if(!HAL_GPIO_ReadPin(SW_UP) ) { CHANGE_RESET; - (*to_modify)++; + if (*to_modify < 32768) + (*to_modify)++; } else if(!HAL_GPIO_ReadPin(SW_DOWN)) { CHANGE_RESET; - (*to_modify)--; + if (*to_modify >= -32768) + (*to_modify)--; } } } diff --git a/gpio.h b/gpio.h --- a/gpio.h +++ b/gpio.h @@ -12,7 +12,7 @@ void user_input(uint16_t* to_modify); -void user_input_signed(int16_t* to_modify); +void user_input_signed(int32_t* to_modify); void gpio_init(void); #endif diff --git a/main.c b/main.c --- a/main.c +++ b/main.c @@ -5,11 +5,10 @@ #include "pid.h" #include "states.h" #include "ssd1306.h" -#ifdef MAX31855_TC_SENSOR -#include "max31855.h" -#endif #ifdef MAX31865_RTD_SENSOR #include "max31865.h" +#else +#include "max31855.h" #endif #include "gpio.h" #include "spi.h" @@ -22,6 +21,7 @@ therm_settings_t set; therm_status_t status; +pid_state_t pid_state; int main(void) { @@ -53,13 +53,16 @@ int main(void) // Init SPI busses spi_init(); + // Init RTD chip #ifdef MAX31865_RTD_SENSOR max31865_config(spi_get()); #endif // Init OLED over SPI ssd1306_init(); - ssd1306_clearscreen(); + + // Startup screen + display_startup_screen(); // Default status status.temp = 0; @@ -69,20 +72,16 @@ int main(void) status.setpoint = 70; status.pid_enabled = 0; + pid_init(&pid_state); + // Go to brew instead of idle if configured thusly if(set.val.boottobrew) status.state = STATE_PREHEAT; - // Startup screen - ssd1306_drawstring("therm v0.2", 1, 40); - ssd1306_drawstring("protofusion.org/therm", 3, 0); - - HAL_Delay(1000); - // Restore settings from flash memory flash_restore(&set); - HAL_Delay(1000); + HAL_Delay(2000); ssd1306_clearscreen(); // Soft timers @@ -104,21 +103,27 @@ int main(void) if((HAL_GetTick() - last_pid > PID_PERIOD)) { - #ifdef MAX31855_TC_SENSOR - max31855_readtemp(spi_get(), &set, &status); // Read MAX31855 - #endif #ifdef MAX31865_RTD_SENSOR max31865_readtemp(spi_get(), &set, &status); - #endif + #else + max31855_readtemp(spi_get(), &set, &status); // Read MAX31855 + #endif if(status.pid_enabled) { // Get ssr output for next time - int16_t power_percent = pid_update(set.val.k_p, set.val.k_i, set.val.k_d, status.temp, status.temp_frac, status.setpoint, &set, &status); + int16_t power_percent = pid_update(&set, &status, &pid_state); //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 { @@ -138,12 +143,10 @@ int main(void) // Every 200ms, set the SSR on unless output is 0 if(HAL_GetTick() - last_ssr_on > SSR_PERIOD) { + // Only support heating (ssr_output > 0) right now if(ssr_output > 0) { - char tempstr[6]; - itoa(ssr_output, tempstr, 10); - ssd1306_drawstring(tempstr, 0, 90); HAL_GPIO_WritePin(SSR_PIN, 1); HAL_GPIO_WritePin(LED_POWER, 1); @@ -157,7 +160,7 @@ int main(void) } - // Transmit temperature over USB-CDC on a regulat basis + // Transmit temperature over USB-CDC on a regular basis if(HAL_GetTick() - last_vcp_tx > VCP_TX_FREQ) { // Print temp to cdc diff --git a/max31865.c b/max31865.c --- a/max31865.c +++ b/max31865.c @@ -53,14 +53,8 @@ void max31865_clear_errors(SPI_HandleTyp // Grab temperature reading from MAX31865 void max31865_readtemp(SPI_HandleTypeDef* hspi1, therm_settings_t* set, therm_status_t* status) { - /////////////////////////////////// - // This is duplicated from MAX31855, update for MAX31865 registers/etc - /////////////////////////////////// - // TODO: Set configuration register based on params in config.h (2-wire, 4-wire, etc RTD). This is register 0x00. - // 2-wire RTC or 2-wire (duh) NTC thermistor will be the only options - // Need option for resistance of RTD - // These options should be stored in the set structure and should be menu-selectable + // TODO: Set RTD ref resistance in set struct // Assert CS HAL_GPIO_WritePin(MAX_CS, 0); diff --git a/pid.c b/pid.c --- a/pid.c +++ b/pid.c @@ -1,22 +1,24 @@ -#include "stm32f0xx_hal.h" -#include "states.h" +#include "pid.h" // PID implementation -// TODO: Make struct that has the last_temp and i_state in it, pass by ref. Make struct that has other input values maybe. -static int16_t last_pid_temp = 0; -static uint8_t last_pid_temp_frac = 0; -static int32_t i_state = 0; -int16_t pid_update(uint16_t k_p, uint16_t k_i, uint16_t k_d, int16_t temp, uint8_t temp_frac, int16_t setpoint, therm_settings_t* set, therm_status_t* status) +void pid_init(pid_state_t* state) +{ + 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) { // Calculate instantaneous error - int16_t error = setpoint - temp; // TODO: Use fixed point fraction + int16_t error = status->setpoint - status->temp; // TODO: Use fixed point fraction // Proportional component - int32_t p_term = k_p * error; + int32_t p_term = set->val.k_p * error; // Error accumulator (integrator) - i_state += error; + state->i_state += error; // to prevent the iTerm getting huge from lots of // error, we use a "windup guard" @@ -24,22 +26,22 @@ int16_t pid_update(uint16_t k_p, uint16_ // 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 / k_i; + int32_t windup_guard_res = set->val.windup_guard / set->val.k_i; // Calculate integral term with windup guard - if (i_state > windup_guard_res) - i_state = windup_guard_res; - else if (i_state < -windup_guard_res) - 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 = k_i * i_state; + int32_t i_term = set->val.k_i * state->i_state; // Calculate differential term (slope since last iteration) - int32_t d_term = (k_d * (status->temp - last_pid_temp)); + int32_t d_term = (set->val.k_d * (status->temp - state->last_pid_temp)); // Save temperature for next iteration - last_pid_temp = status->temp; - last_pid_temp_frac = status->temp_frac; + state->last_pid_temp = status->temp; + state->last_pid_temp_frac = status->temp_frac; int16_t result = p_term + i_term - d_term; diff --git a/pid.h b/pid.h --- a/pid.h +++ b/pid.h @@ -1,8 +1,16 @@ #ifndef PIDS_H #define PIDS_H +#include "stm32f0xx_hal.h" #include "states.h" -int16_t pid_update(uint16_t k_p, uint16_t k_i, uint16_t k_d, int16_t temp, uint8_t temp_frac, int16_t setpoint, therm_settings_t* set, therm_status_t* status); +typedef struct { + int16_t last_pid_temp; + uint8_t last_pid_temp_frac; + int32_t i_state; +} pid_state_t; + +void pid_init(pid_state_t* state); +int16_t pid_update(therm_settings_t* set, therm_status_t* status, pid_state_t* state); #endif