# HG changeset patch # User Ethan Zonca # Date 2017-06-26 18:19:08 # Node ID f602474ad6c6f41b04287e90c8019b5c5d9cbb56 # Parent 2b4eb31dd8da193e1aee1c699d8ccf1ef51184a2 Initial work on max31856 driver, etc diff --git a/inc/states.h b/inc/states.h --- a/inc/states.h +++ b/inc/states.h @@ -27,6 +27,7 @@ typedef union int32_t setpoint_brew; int32_t setpoint_steam; uint32_t control_mode; + uint32_t sensor_type; uint32_t plant_type; uint32_t hysteresis; } val; @@ -41,7 +42,8 @@ enum tempunits { enum state { STATE_IDLE = 0, - + + STATE_SETSENSORTYPE, STATE_SETMODE, STATE_SETPLANTTYPE, STATE_SETHYSTERESIS, @@ -89,4 +91,14 @@ enum RESET_MODE { RESET_SIZE, }; +enum SENSOR_TYPE { + SENSOR_NTC = 0, + SENSOR_TC_K, + SENSOR_TC_E, + SENSOR_TC_N, + SENSOR_TC_R, + SENSOR_TC_S, + SENSOR_TC_T, +}; + #endif diff --git a/lib/max31856/max31856.c b/lib/max31856/max31856.c new file mode 100644 --- /dev/null +++ b/lib/max31856/max31856.c @@ -0,0 +1,59 @@ +// +// MAX31856: Driver to configure and read temperature from the MAX31856 thermoouple-to-Digital IC +// + +#include "max31856.h" +#include "states.h" + +// Private variables +static float temp_latest = 0.0; +static float temp_avg = 0.0; + +static SPI_HandleTypeDef* spiport; + + +// Initialize the MAX31856 driver +void max31856_init(SPI_HandleTypeDef* spi_port, GPIO_TypeDef* cs_port, uint32_t cs_pin, uint32_t sensor_type) +{ + // Set SPI port reference + spiport = spi_port; + + // Configure the CS pin for output + GPIO_InitTypeDef GPIO_InitStruct; + GPIO_InitStruct.Pin = cs_pin; + GPIO_InitStruct.Mode = GPIO_MODE_OUTPUT_PP; + GPIO_InitStruct.Pull = GPIO_NOPULL; + GPIO_InitStruct.Speed = GPIO_SPEED_FREQ_LOW; + HAL_GPIO_Init(cs_port, &GPIO_InitStruct); + + // MAX31856 + // - set to continuous conversion mode + // - probably no filtering, we'll do that on this side of things + // - set up to read the typical open/short faults but not the high/low alarms + + uint8_t data[] = {0,0,0,0}; + HAL_SPI_Transmit(spiport, data, 1, 100); + + // sensor type - could we just mask bits off? maybe optimize the enum for this +} + +void max31856_process(void) +{ + // Read temperature from the MAX31856 (approx 10hz optimally) + uint8_t data[] = {0,0,0,0}; + HAL_SPI_Transmit(spiport, data, 1, 100); + +} + + +// Return latest temperature reading (unaveraged, deg C) +float max31856_latest_temp(void) +{ + return temp_latest; +} + +// Return average temperature reading (deg C) +float max31856_avg_temp(void) +{ + return temp_latest; +} diff --git a/lib/max31856/max31856.h b/lib/max31856/max31856.h new file mode 100644 --- /dev/null +++ b/lib/max31856/max31856.h @@ -0,0 +1,7 @@ +#ifndef MAX31856_H +#define MAX31856_H + +#include "stm32f3xx_hal.h" + + +#endif diff --git a/src/display.c b/src/display.c --- a/src/display.c +++ b/src/display.c @@ -114,7 +114,7 @@ void display_process(void) status->state = STATE_PREHEAT; break; case MODE_SETUP: - status->state = STATE_SETMODE; + status->state = STATE_SETSENSORTYPE; break; case MODE_RESET: status->state = STATE_RESET; @@ -149,6 +149,32 @@ void display_process(void) + case STATE_SETSENSORTYPE: + { + // Write text to OLED + // [ therm :: set mode ] + // [ m = ] + ssd1306_drawstring("Sensor Type", 0, 40); + ssd1306_drawlogo(); + + // change scope to global? + char* sensor_lookup[] = {"NTC", "K ", "E ", "N ", "R ", "S ", "T "}; + ssd1306_drawstring(sensor_lookup[set->val.sensor_type], 1, 60); + ssd1306_drawstring("Press to accept", 3, 40); + + // Button handler + if(SW_BTN_PRESSED) { + status->state = STATE_SETMODE; + } + else + { + user_input((uint16_t*)&set->val.hysteresis); + } + // Event Handler + // N/A + + } break; + case STATE_SETMODE: { // Write text to OLED diff --git a/src/pid.c b/src/pid.c --- a/src/pid.c +++ b/src/pid.c @@ -20,38 +20,39 @@ void pid_init() 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; + float ssr_output = 0; - if(runtime_status()->pid_enabled) - { - // Get ssr output for next time - int16_t power_percent = pid_update(); + 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; + 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; + //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; - } + // 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; + return ssr_output; } int16_t pid_update(void) @@ -59,50 +60,50 @@ 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; + // Convert temperature to fixed point number with 1/10th resolution + float temp = status->temp; - // Calculate instantaneous error - int16_t error = status->setpoint * 10 - temp; // TODO: Use fixed point fraction + // Calculate instantaneous error + int16_t error = status->setpoint * 10 - temp; // TODO: Use fixed point fraction - // Proportional component - int32_t p_term = set->val.k_p * error; + // Proportional component + int32_t p_term = set->val.k_p * error; - // Error accumulator (integrator) - state.i_state += 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; + // 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) + // 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) + 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)); + // 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; + // Save temperature for next iteration + state.last_pid_temp = temp; - int16_t result = (p_term + i_term - d_term) / 10; + 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; + // Put out tenths of percent, 0-1000. + if(result > 1000) + result = 1000; + else if(result < -1000) + result = -1000; - // Return feedback - return result; + // Return feedback + return result; } diff --git a/src/tempsense.c b/src/tempsense.c --- a/src/tempsense.c +++ b/src/tempsense.c @@ -8,13 +8,35 @@ void tempsense_init(void) { + // Maybe don't perform temp sensor setup in here, but in readtemp? + // what happens if the user changes the tempsense type while running? + // we need to re-init... + } +// Returns the latest reading from the configured temperature sensor float tempsense_readtemp(void) { - // TODO: Support multiple temperature sensors + switch(flash_getsettings()->val.sensor_type) + { + case SENSOR_TC_K: + case SENSOR_TC_E: + case SENSOR_TC_N: + case SENSOR_TC_R: + case SENSOR_TC_S: + case SENSOR_TC_T: + { + // Read MAX31856 + } break; + + case SENSOR_NTC: + { + // Read analog value from internal ADC, linearize the reading, etc + } break; + + } // either return latest reading from DMA loop (NTC, etc) // or initiate a blocking read and return it.