Changeset - f602474ad6c6
[Not reviewed]
default
0 4 2
Ethan Zonca (ethanzonca) - 8 years ago 2017-06-26 18:19:08
e@ethanzonca.com
Initial work on max31856 driver, etc
6 files changed with 181 insertions and 54 deletions:
0 comments (0 inline, 0 general)
inc/states.h
Show inline comments
 
@@ -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
lib/max31856/max31856.c
Show inline comments
 
new file 100644
 
//
 
// 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;
 
}
lib/max31856/max31856.h
Show inline comments
 
new file 100644
 
#ifndef MAX31856_H
 
#define MAX31856_H
 

	
 
#include "stm32f3xx_hal.h"
 

	
 

	
 
#endif
src/display.c
Show inline comments
 
@@ -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
src/pid.c
Show inline comments
 
@@ -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;
 
}
 

	
 

	
src/tempsense.c
Show inline comments
 
@@ -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.
0 comments (0 inline, 0 general)