Changeset - 7fc667dd7f38
[Not reviewed]
default
0 6 0
Ethan Zonca - 8 years ago 2017-07-28 13:27:26
ez@ethanzonca.com
Decent working pid
6 files changed with 28 insertions and 45 deletions:
0 comments (0 inline, 0 general)
src/display.c
Show inline comments
 
@@ -488,25 +488,25 @@ void display_process(void)
 
            ssd1306_drawlogo();
 

	
 
            ssd1306_drawchar(updown(), 1, 52);
 

	
 
            char tempstr[12];
 
            snprintf(tempstr, 12, "O=%d", set->val.temp_offset);
 
            ssd1306_drawstring(tempstr, 1, 60);
 

	
 
            ssd1306_drawstring("Press to accept", 3, 40);
 

	
 
            // Button handler
 
            if(SW_BTN_PRESSED) {
 
//                flash_save(set);
 
            	flash_savesettings();
 
                status->state = STATE_IDLE;
 
            }
 
            else {
 
                user_input_signed(&set->val.temp_offset);
 
            }
 

	
 
            // Event Handler
 
            // N/A
 
 
 
        } break;
 

	
 

	
 
@@ -520,24 +520,25 @@ void display_process(void)
 
            else
 
                ssd1306_drawstring("Precooling...", 0, 0);
 

	
 
            //ssd1306_drawlogo();
 
            draw_setpoint(status);
 

	
 
            status->pid_enabled = 1;
 
            status->setpoint = set->val.setpoint_brew;
 

	
 
            // Button handler
 
            if(SW_BTN_PRESSED) {
 
                status->state = STATE_IDLE;
 
                flash_savesettings();
 
            }
 
            else {
 
                user_input_signed(&set->val.setpoint_brew);
 
            }
 

	
 
            // Event Handler
 
            if(status->temp >= status->setpoint) {
 
                status->state = STATE_MAINTAIN;
 
            }
 
 
 
        } break;
 

	
 
@@ -550,24 +551,25 @@ void display_process(void)
 
            if(set->val.plant_type == PLANT_HEATER)
 
                ssd1306_drawstring("Preheated!", 0, 0);
 
            else
 
                ssd1306_drawstring("Precooled!", 0, 0);
 

	
 
            draw_setpoint(status);
 
            status->pid_enabled = 1;
 
            status->setpoint = set->val.setpoint_brew;
 

	
 
            // Button handler
 
            if(SW_BTN_PRESSED) {
 
                status->state = STATE_IDLE;
 
                flash_savesettings();
 
            }
 
            else {
 
                user_input_signed(&set->val.setpoint_brew);
 
            }
 

	
 
            // Event Handler
 
            // N/A
 
 
 
        } break;
 

	
 
        // Thermocouple error
 
        case STATE_TC_ERROR:
src/main.c
Show inline comments
 
@@ -43,53 +43,51 @@ int main(void)
 
    pid_init();
 
    pwmout_init();
 
    flash_init();
 
	watchdog_init();
 
	tempsense_init();
 
 
	// Soft timers
 
    uint32_t last_pid = 0;
 
    uint32_t last_thermostat = 0;
 
    uint32_t last_1hz = 0;
 
    uint32_t last_5hz = 0;
 
 
	float duty = 0.0;
 
	int16_t duty = 0;
 
 
	while (1)
 
	{
 
 
		if(HAL_GetTick() - last_1hz > 750)
 
		{
 
			display_1hz();
 
			last_1hz = HAL_GetTick();
 
		}
 
 
		if(HAL_GetTick() - last_5hz > 200)
 
		{
 
			tempsense_readtemp();
 
			runtime_status()->temp = tempsense_gettemp();
 
			last_5hz = HAL_GetTick();
 
		}
 
 
        if(flash_getsettings()->val.control_mode == MODE_PID && (HAL_GetTick() - last_pid > PID_PERIOD))
 
        {
 
//        	runtime_status()->temp = tempsense_readtemp();
 
        	duty = pid_process();
 
            last_pid = HAL_GetTick();
 
        }
 
 
        // Thermostatic control
 
        if(flash_getsettings()->val.control_mode == MODE_THERMOSTAT && HAL_GetTick() - last_thermostat > SSR_PERIOD)
 
        {
 
//        	runtime_status()->temp = tempsense_readtemp();
 
        	duty = thermostat_process();
 
            last_thermostat = HAL_GetTick();
 
        }
 
 
        pwmout_process((int16_t)duty);
 
        display_process();
 
        watchdog_feed();
 
 
 
//        // Transmit temperature over USB-CDC on a regular basis
 
//        if(HAL_GetTick() - last_vcp_tx > VCP_TX_FREQ)
 
//        {
src/pid.c
Show inline comments
 
@@ -26,75 +26,80 @@ float pid_process(void)
 
//			#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)
 
		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[6];
 
		snprintf(tempstr, 6, "%g", ssr_output);
 
		ssd1306_drawstring(tempstr, 0, 90);
 
		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
 
	int16_t error = status->setpoint - temp; // TODO: Use fixed point fraction
 
	// 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) / set->val.k_i;
 
	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)
src/pwmout.c
Show inline comments
 
@@ -83,54 +83,24 @@ void pwmout_init(void)
 

	
 

	
 
// freaking integral term isn't compatible with both heating and cooling... due to the discard
 
// functionality. this is a problem.
 

	
 
// also duty cycling isn't working correctly...
 
void pwmout_process(int16_t duty)
 
{
 
	if(duty == 0)
 
	{
 
		HAL_GPIO_WritePin(SSR, 0);
 
		HAL_GPIO_WritePin(LED, 0);
 
		// TODO: Disable timer
 
	}
 
	if(duty < 0)
 
		duty = -duty;
 
		duty = 0;
 

	
 

	
 
	htim17.Instance->CCR1 = duty; //duty;
 
//	HAL_GPIO_TogglePin(SSR_GPIO_Port, SSR_PIN);
 

	
 
//	uint32_t ssr_output = duty; // meh
 
//
 
//	// Kill SSR once the desired on-time has elapsed
 
//	if(flash_getsettings()->val.control_mode == MODE_PID && ((HAL_GetTick() - last_ssr_on > ssr_output) || ssr_output <= 0))
 
//	{
 
//		HAL_GPIO_WritePin(SSR, 0);
 
//		HAL_GPIO_WritePin(LED, 0);
 
//	}
 
//
 
//
 
//	// Every 200ms, set the SSR on unless output is 0
 
//	if(flash_getsettings()->val.control_mode == MODE_PID && HAL_GetTick() - last_ssr_on > SSR_PERIOD)
 
//	{
 
//		// Heat or cool, if we need to
 
//		if(ssr_output > 0)
 
//		{
 
//			HAL_GPIO_WritePin(SSR, 1);
 
//			HAL_GPIO_WritePin(LED, 1);
 
//			last_ssr_on = HAL_GetTick();
 
//		}
 
//		else {
 
//			// Make sure everything is off
 
//			HAL_GPIO_WritePin(SSR, 0);
 
//			HAL_GPIO_WritePin(LED, 0);
 
//		}
 
//
 
//	}
 
}
 

	
 
TIM_HandleTypeDef* pwmout_get_tim(void)
 
{
 
	return &htim17;
 
}
src/system/flash.c
Show inline comments
 
@@ -60,26 +60,26 @@ void flash_restoresettings(void)
 
	if(eeprom_emulation[FLASH_MAGIC_LOC] == FLASH_MAGIC_VALUE)
 
	{
 
		// Read page of flash into settings structure
 
		uint16_t readctr = 0;
 
		for(readctr = 0; readctr < 128; readctr++)
 
		{
 
			settings.data[readctr] = eeprom_emulation[readctr];
 
		}
 
	}
 
	// No data in flash! Set defaults here
 
	else
 
	{
 
		settings.val.k_p = 10;
 
		settings.val.k_i = 0;
 
		settings.val.k_p = 100;
 
		settings.val.k_i = 2;
 
		settings.val.k_d = 0;
 
		settings.val.windup_guard = 300;
 
		settings.val.sensor_type = 1;
 
		//torestore.values.can_id = 22;
 
	}
 
}
 
 
 
// Accessor to retrieve settings structure
 
inline therm_settings_t* flash_getsettings(void)
 
{
 
	return &settings;
src/system/interrupts.c
Show inline comments
 
@@ -64,17 +64,25 @@ void HAL_TIM_PWM_PulseFinishedCallback(T
 
{
 
	if(htim == pwmout_get_tim())
 
	{
 
		HAL_GPIO_WritePin(SSR, 0);
 
		HAL_GPIO_WritePin(LED, 0);
 
	}
 
}
 
 
void HAL_TIM_PeriodElapsedCallback(TIM_HandleTypeDef *htim)
 
{
 
	if(htim == pwmout_get_tim())
 
	{
 
		HAL_GPIO_WritePin(LED, 1);
 
		HAL_GPIO_WritePin(SSR, 1);
 
		if(htim->Instance->CCR1 == 0)
 
		{
 
			HAL_GPIO_WritePin(LED, 0);
 
			HAL_GPIO_WritePin(SSR, 0);
 
		}
 
		else
 
		{
 
			HAL_GPIO_WritePin(LED, 1);
 
			HAL_GPIO_WritePin(SSR, 1);
 
		}
 
	}
 
}
 
0 comments (0 inline, 0 general)