/*! ******************************************************************************* * Controller update * \note call it once per second * \param minute_ch is true when minute is changed * \returns valve position * ******************************************************************************/ uint8_t CTL_update(bool minute_ch, uint8_t valve) { if ( minute_ch || (CTL_temp_auto==0) ) { // minutes changed or we need return to timers uint8_t t=RTC_ActualTimerTemperature(!(CTL_temp_auto==0)); if (t!=0) { CTL_temp_auto=t; if (CTL_mode_auto) { CTL_temp_wanted=CTL_temp_auto; if ((PID_force_update<0)&&(CTL_temp_wanted!=CTL_temp_wanted_last)) { PID_force_update=0; } } } } CTL_window_detection(); if (PID_update_timeout>0) PID_update_timeout--; if (PID_force_update>0) PID_force_update--; if ((PID_update_timeout == 0)||(PID_force_update==0)) { uint8_t temp; if ((CTL_temp_wanted<TEMP_MIN) || mode_window()) { temp = TEMP_MIN; // frost protection to TEMP_MIN } else { temp = CTL_temp_wanted; } //update now if (temp!=CTL_temp_wanted_last) { CTL_temp_wanted_last=temp; sumError=0; goto UPDATE_NOW; // optimization } if (PID_update_timeout == 0) { UPDATE_NOW: PID_update_timeout = (config.PID_interval * 5); // new PID pooling if (temp>TEMP_MAX) { valve = config.valve_max; } else { valve = pid_Controller(calc_temp(temp),temp_average,valve); } } PID_force_update = -1; COM_print_debug(valve); } // batt error detection if (bat_average < 20*(uint16_t)config.bat_low_thld) { CTL_error |= CTL_ERR_BATT_LOW | CTL_ERR_BATT_WARNING; } else { if (bat_average < 20*(uint16_t)config.bat_warning_thld) { CTL_error |= CTL_ERR_BATT_WARNING; CTL_error &= ~CTL_ERR_BATT_LOW; } else { CTL_error &= ~(CTL_ERR_BATT_WARNING|CTL_ERR_BATT_LOW); } } return valve; }
void PIDrun(PID_o *obj){ processValue_t processValue, control, setpoint; setpoint = obj->config.setpoint(); processValue = obj->config.getter(); control = pid_Controller(setpoint, processValue, &obj->data.algData); obj->config.supervisor(&control); obj->config.setter(control); }
int16_t pid_manager_update_pid(uint8_t pid_id, int16_t set_val, int16_t meas_val) { uint16_t ret_val; ret_val = 0; if((pid_id > 0) && (pid_id <= PID_COUNT)) { uint8_t index = pid_id - 1; if(pid_array[index].pid_created) { ret_val = pid_Controller(set_val, meas_val,&(pid_array[index].pid)); } } return ret_val; }
/*! \brief Demo of PID controller */ void main(void) { int16_t referenceValue, measurementValue, inputValue; Init(); sei(); while(1){ // Run PID calculations once every PID timer timeout if(gFlags.pidTimer) { referenceValue = Get_Reference(); measurementValue = Get_Measurement(); inputValue = pid_Controller(referenceValue, measurementValue, &pidData); Set_Input(inputValue); gFlags.pidTimer = FALSE; } } }
int main(void) { avr_init(); u08 even; // u16 i; //u08 temp; command = 45; // actualTemp = 85; // u16 temp; for(;;) { // Tasks here. // Command line reception of commands... // pass characters received on the uart (serial port) // into the cmdline processor // while(uartReceiveByte(&c)){ // vt100SetCursorPos(1, 0); // uartSendByte(c); // cmdlineInputFunc(c); // // } // bounce the character, keep to the top 3 rows... // run the cmdline execution functions vt100SetCursorPos(3, 0); cmdlineMainLoop(); // Command line reception ends here if (APP_STATUS_REG & BV(DO_SAMPLE)) { readMAX6675(&tempData); // get data to tempData variable CLEAR_SAMPLE_FLAG; //debug, invert pin PIND ^= BV(PD5); //update PID // output = pid_Controller(command, tempData, &PID_data); //invert PID // output = PHASE_ANGLE_LIMIT_HIGH - output; } if(APP_STATUS_REG & BV(DO_PID)) { #ifdef REG_PID //update PID output = pid_Controller(command, tempData, &PID_data); #ifndef CMDLINE #ifndef RX_DBG rprintf("PID raw: "); rprintfNum(10, 6, TRUE, ' ', output); rprintfCRLF(); #endif //invert & limit PID if(output > 29700) output = 700; //output = PHASE_ANGLE_LIMIT_HIGH - output; #ifndef RX_DBG rprintf("PID scaled: "); rprintfNum(10, 6, TRUE, ' ', output); rprintfCRLF(); #endif #endif #endif #ifdef REG_PD #endif // actualTemp +=10; // OCR0A = output; CLEAR_PID_FLAG; // } /* if((temp = 0xFFFF-output) > 30000) { temp = 30000;} else if (temp < 1000) { temp = 1000;} */ // Limit to within 1 half-phase: if((output > PHASE_ANGLE_LIMIT_HIGH) || (output < 0)){ #ifndef CMDLINE #ifndef RX_DBG rprintf("Max out");rprintfCRLF(); #endif #endif output = PHASE_ANGLE_LIMIT_HIGH; // don't fire the triac at all! SET_HOLD_FIRE; // set flag to not fire triac } else { CLEAR_HOLD_FIRE; // set flag to fire triac } if ((output < PHASE_ANGLE_LIMIT_LOW)){ // || (output < 0)) #ifndef CMDLINE #ifndef RX_DBG rprintf("Min out");rprintfCRLF(); #endif #endif output = PHASE_ANGLE_LIMIT_LOW; // fire the triac at zerocrozz to get complete halfwave } #ifndef WALK_PHASEANGLE OCR1A = output; #endif //OCR1A = PHASE_ANGLE_LIMIT_LOW; //OCR1A = PHASE_ANGLE_LIMIT_HIGH; } #ifdef DEBUG_SER // uartPrintfNum(10, 6, TRUE, ' ', 1234); --> " +1234" // uartPrintfNum(16, 6, FALSE, '.', 0x5AA5); --> "..5AA5" // rprintfNum(10, 4, FALSE, ' ', tempData);// rprintfCRLF(); #ifndef CMDLINE #ifndef RX_DBG if(sensorDisconnected) { rprintfProgStrM("Disconnected Probe!\r\n"); } else { rprintf("Process Value: "); rprintfNum(10, 4, FALSE, ' ', tempData); rprintfCRLF(); rprintf("Target Value: "); rprintfNum(10, 4, FALSE, ' ', command); rprintfCRLF(); // rprintf("PID Phaselimit: "); // rprintfNum(10, 6, TRUE, ' ', output); rprintfCRLF(); rprintf("OCR1A: "); rprintfNum(10, 6, FALSE, ' ', OCR1A); rprintfCRLF(); //----------- // rprintf("dummy: "); // rprintfNum(10, 6, TRUE, ' ', _DUMMY); rprintfCRLF(); rprintf("E "); rprintfNum(10, 4, TRUE, ' ', _ERROR); rprintfCRLF(); rprintf("P "); rprintfNum(10, 8, TRUE, ' ', _PTERM); rprintfCRLF(); rprintf("I "); rprintfNum(10, 8, TRUE, ' ', _ITERM); rprintfCRLF(); rprintf("D "); rprintfNum(10, 8, TRUE, ' ', _DTERM); rprintfCRLF(); //----------- } vt100SetCursorPos(3, 0); if(even++ == 10){ vt100ClearScreen(); vt100SetCursorPos(3,0); even = 0; } #endif //#ifndef RX_DBG #endif //#ifndef CMDLINE #endif //#ifdef DEBUG_SER } return(0); }