Changeset - f153d4ca027c
[Not reviewed]
default
0 4 0
Ethan Zonca - 8 years ago 2017-07-27 13:12:04
ezonca@sealandaire.com
PID control kinda working, still can't do 0percent duty
4 files changed with 18 insertions and 8 deletions:
0 comments (0 inline, 0 general)
inc/pwmout.h
Show inline comments
 
#ifndef PWMOUT_H
 
#define PWMOUT_H
 

	
 

	
 
#define SSR_PIN GPIO_PIN_7
 
#define SSR_GPIO_Port GPIOB
 
#define SSR SSR_GPIO_Port, SSR_PIN
 

	
 

	
 

	
 
void pwmout_init(void);
 
void pwmout_process(uint16_t duty);
 
void pwmout_process(int16_t duty);
 
TIM_HandleTypeDef* pwmout_get_tim(void);
 

	
 
#endif
src/main.c
Show inline comments
 
@@ -31,81 +31,82 @@ int main(void)
 
    display_startup_screen();
 
    HAL_Delay(2000);
 
    ssd1306_clearscreen();
 
	ssd1306_drawlogo();
 
 
    // Default status
 
	runtime_status()->temp = 0.0;
 
	runtime_status()->state_resume = 0;
 
	runtime_status()->state = STATE_IDLE;
 
	runtime_status()->setpoint = 70;
 
	runtime_status()->pid_enabled = 0;
 
 
    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;
 
 
	while (1)
 
	{
 
		float duty = 0.0;
 
 
		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(duty);
 
        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)
 
//        {
 
//            // Print temp to cdc
 
//            char tempstr[16];
 
//            itoa_fp(status.temp, status.temp_frac, tempstr);
 
//            uint8_t numlen = strlen(tempstr);
 
//            tempstr[numlen] = '\r';
 
//            tempstr[numlen+1] = '\n';
 
//
 
//    //        if(set.val.usb_plugged)
 
//    //            CDC_Transmit_FS(tempstr, numlen+2);
 
//           // while(CDC_Transmit_FS("\r\n", 2) == USBD_BUSY);
 
//
 
//            last_vcp_tx = HAL_GetTick();
 
//        }
 
 
	}
 
}
 
src/pid.c
Show inline comments
 
@@ -31,75 +31,75 @@ float pid_process(void)
 

	
 

	
 
	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];
 
		snprintf(tempstr, 6, "%g", ssr_output);
 
		ssd1306_drawstring(tempstr, 0, 90);
 
	}
 
	else
 
	{
 
		ssr_output = 0.0;
 
	}
 

	
 
	return ssr_output;
 
	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 * 10 - temp; // TODO: Use fixed point fraction
 
	int16_t error = status->setpoint - temp; // TODO: Use fixed point fraction
 

	
 
	// 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 * 10) / set->val.k_i;
 
	int32_t windup_guard_res = (set->val.windup_guard) / 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;
 

	
 
	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)
 
	result = 1000;
 
	else if(result < -1000)
 
	result = -1000;
 

	
 
	// Return feedback
src/pwmout.c
Show inline comments
 
@@ -65,52 +65,61 @@ void pwmout_init(void)
 
	sBreakDeadTimeConfig.DeadTime = 0;
 
	sBreakDeadTimeConfig.BreakState = TIM_BREAK_DISABLE;
 
	sBreakDeadTimeConfig.BreakPolarity = TIM_BREAKPOLARITY_HIGH;
 
	sBreakDeadTimeConfig.BreakFilter = 0;
 
	sBreakDeadTimeConfig.AutomaticOutput = TIM_AUTOMATICOUTPUT_DISABLE;
 
	if (HAL_TIMEx_ConfigBreakDeadTime(&htim17, &sBreakDeadTimeConfig) != HAL_OK)
 
	{
 
		error_assert(ERR_PERIPHINIT);
 
	}
 

	
 
    HAL_NVIC_SetPriority(TIM1_TRG_COM_TIM17_IRQn, 0, 0);
 
    HAL_NVIC_EnableIRQ(TIM1_TRG_COM_TIM17_IRQn);
 

	
 

	
 
	HAL_TIM_OC_Start_IT(&htim17, TIM_CHANNEL_1);
 
    __HAL_TIM_ENABLE_IT(&htim17, TIM_IT_UPDATE);
 

	
 
}
 

	
 

	
 
// 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(uint16_t duty)
 
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;
 

	
 
	htim17.Instance->CCR1 = duty;
 

	
 
	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
0 comments (0 inline, 0 general)