/************************************************************************************************************************ * Heaters_init.c **************************************************************************************************************************/ ////////////////////////////////State machine operation//////////////////////////////////// //the state machine operation is used to operate in runtime correct profile flow execution //by recieved esign flow of the user from the UI /////////////////////////////////////////////////////////////////////////////////////////// #include "include.h" #include "PMR/Hardware/HardwarePidControl.pb-c.h" #include "PMR/Hardware/HardwarePidControlType.pb-c.h" #include "PMR/common/MessageContainer.pb-c.h" #include "PMR/Stubs/StubHeatingTestRequest.pb-c.h" #include "PMR/Stubs/StubHeatingTestResponse.pb-c.h" #include "PMR/Stubs/StubHeatingTestPollRequest.pb-c.h" #include "PMR/Stubs/StubHeatingTestPollResponse.pb-c.h" #include "../control/control.h" #include "../control/pidalgo.h" #include "include.h" #include #include #include "heaters_ex.h" #include "heaters.h" #include "Drivers/Heater/Heater.h" #include "Drivers/Heater/TemperatureSensor.h" #include "Drivers/I2C_Communication/Head_Card/PT100/Head_PT100_ADC.h" /******************** STRUCTURES AND ENUMs ********************************************/ /*typedef enum { HeatersInitialState, HeatersInit, HeatersControlledOp, HeatersShutdown, HeatersTest, MaxHeatersStates }HEATERS_STATES_ENUM; typedef enum { HeatersCold, HeatersAtPIDStrip, HeatersOverHeat, HeatersOnTest }HEATERS_EVENTS_ENUM; */ /******************** GLOBAL PARAMETERS ********************************************/ HeaterPIDControlConfig HeaterControl[HEATER_TYPE_MAX_HEATERS] = {0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0}; bool AcHeaterConfigured[MAX_AC_HEATERS] = {0,0,0}; int NumberOFSlicesInUse = 0; uint32_t MillisecondsPerChange = 0; bool FastHeating = 1; /******************** CODE ********************************************/ /* * HeatersInit * called by: General Hardware Init * initialized all global data */ uint32_t Heaters_Init(void) { int i; //ROM_TimerDisable(Heater_timerBase, TIMER_A); FPGA_SensorInitConfig(); memset(HeaterControl,0,sizeof(HeaterControl)); for (i = 0;ihardwarepidcontroltype); //int ValidationError = 0; if (HeaterId< HEATER_TYPE_MAX_HEATERS) { HeaterControl[HeaterId].configured = true; HeaterControl[HeaterId].id = HeaterId; HeaterControl[HeaterId].outputproportionalpowerlimit = request->outputproportionalpowerlimit; HeaterControl[HeaterId].outputproportionalband = request->outputproportionalband; HeaterControl[HeaterId].IntegralErrorMultiplier = request->setpointramprateorsoftstartramp; HeaterControl[HeaterId].ProportionalErrorMultiplier = request->outputonoffhysteresisvalue; if (HeaterId == HARDWARE_PID_CONTROL_TYPE__DryerAirTemperature) { HeaterControl[HEATER_TYPE__DryerMainHeater].sensormaxvalue = request->sensormaxvalue*100; HeaterControl[HEATER_TYPE__DryerMainHeater].sensorminvalue = request->sensorminvalue*100; HeaterControl[HEATER_TYPE__DryerSecondaryHeater].sensormaxvalue = request->sensormaxvalue*100; HeaterControl[HEATER_TYPE__DryerSecondaryHeater].sensorminvalue = request->sensorminvalue*100; } HeaterControl[HeaterId].sensormaxvalue = 0; HeaterControl[HeaterId].sensorminvalue = 0; HeaterControl[HeaterId].kp = request->proportionalgain; HeaterControl[HeaterId].ki = request->integraltime; HeaterControl[HeaterId].kd = request->derivativetime; HeaterControl[HeaterId].dt = request->controloutputtype; HeaterControl[HeaterId].epsilon = request->epsilon; HeaterControl[HeaterId].pidactive = request->pidactive; //HeaterControl[HeaterId].sensorcorrectionadjustment = request->sensorcorrectionadjustment; //sensorminvalue,sensormaxvalue are used for the dryer heater as internal heater control //HeaterControl[HeaterId].sensortypeandsetpointlimits = request->sensortypeandsetpointlimits; //HeaterControl[HeaterId].setpointramprateorsoftstartramp = request->setpointramprateorsoftstartramp; //HeaterControl[HeaterId].setpointcontroloutputrate = request->setpointcontroloutputrate; //HeaterControl[HeaterId].ssrcontroloutputtype = request->ssrcontroloutputtype; //HeaterControl[HeaterId].outputonoffhysteresisvalues = request->outputonoffhysteresisvalue; //HeaterControl[HeaterId].processvariablesamplingrate = request->processvariablesamplingrate; //HeaterControl[HeaterId].pvinputfilterfactormode = request->pvinputfilterfactormode; if (HeaterId < MAX_AC_HEATERS) AcHeaterConfigured[HeaterId] = true; return OK; } return ERROR; } /* * HeaterConfigSetSharedHeatersParams - prepare the time slices for A/C heaters co-ordinated operation * called by the general hardware HWConfigurationFunc * parameters - the cycle time for the coordinated operation, the size (in MCU cycles) of a single step. */ uint32_t HeaterConfigSetSharedHeatersParams(uint32_t outputproportionalcycletime, uint32_t outputproportionalsinglestep) { int Slice_i; int Heater1000Slices,Heater200aSlices /*,Heater200bSlices Currently both 200W heaters will work together*/; //A/C Heaters Cycle time in milliseconds - one for all heaters OutputProportionalCycleTime = outputproportionalcycletime; //A/C Heaters step size from one decision point to another - in cpu clocks. 120000 = 1 millisecod OutputProportionalSingleStep = outputproportionalsinglestep; // calculate how many milliseconds is in each operating cycle (should be an integer number) MillisecondsPerChange = OutputProportionalSingleStep/120000; // calculate how many time slices are used. the total cycle time / the length of one operating cycle. (one added to put a time gap??? TBD) NumberOFSlicesInUse = (OutputProportionalCycleTime/MillisecondsPerChange); if (NumberOFSlicesInUse > MAX_TIMESLICES ) { LOG_ERROR (NumberOFSlicesInUse, "NumberOFSlicesInUse too high"); return ERROR;//NumberOFSlicesInUse = MAX_TIMESLICES; } // all numbers are rounded down. better to have carefully calculated numbers Heater1000Slices = HeaterControl[HEATER_TYPE__DryerMainHeater].outputproportionalpowerlimit * NumberOFSlicesInUse / 100; Heater200aSlices = HeaterControl[HEATER_TYPE__DryerSecondaryHeater].outputproportionalpowerlimit * NumberOFSlicesInUse / 100; if ((Heater1000Slices + Heater200aSlices +2)>NumberOFSlicesInUse) { LOG_ERROR (NumberOFSlicesInUse, "proportional time slices too high too high"); return ERROR;//NumberOFSlicesInUse = MAX_TIMESLICES; } //mark the time slices for heaters operation as empty / Heater1000 / Heater 200 memset (TimeSliceAllocation,0xFF,sizeof(TimeSliceAllocation)); for (Slice_i = 0; Slice_i < Heater1000Slices;Slice_i++ ) TimeSliceAllocation[Slice_i] = HEATER_TYPE__DryerMainHeater; for (Slice_i = Heater1000Slices+1; Slice_i <= Heater1000Slices+Heater200aSlices;Slice_i++ ) TimeSliceAllocation[Slice_i] = HEATER_TYPE__DryerSecondaryHeater; return OK; } /* * HeaterRecalculateSharedHeatersParams - * * parameters - the cycle time for the coordinated operation, the size (in MCU cycles) of a single step. */ uint32_t stub_heating_limit = 100; uint32_t HeaterRecalculateSharedHeatersParams(uint32_t deviceId, uint32_t new_outputproportionalpowerlimit) { int Slice_i; int Heater1000Slices,Heater200aSlices /*,Heater200bSlices Currently both 200W heaters will work together*/; uint32_t stub_outputproportionalpowerlimit = new_outputproportionalpowerlimit; if (NumberOFSlicesInUse > MAX_TIMESLICES ) { LOG_ERROR (NumberOFSlicesInUse, "NumberOFSlicesInUse too high"); return ERROR;//NumberOFSlicesInUse = MAX_TIMESLICES; } if (stub_outputproportionalpowerlimit > stub_heating_limit) stub_outputproportionalpowerlimit = stub_heating_limit; // all numbers are rounded down. better to have carefully calculated numbers HeaterControl[deviceId].outputproportionalpowerlimit = stub_outputproportionalpowerlimit;///100; Heater1000Slices = HeaterControl[HEATER_TYPE__DryerMainHeater].outputproportionalpowerlimit * NumberOFSlicesInUse / 100; Heater200aSlices = HeaterControl[HEATER_TYPE__DryerSecondaryHeater].outputproportionalpowerlimit * NumberOFSlicesInUse / 100; //#warning temporary disable time slice control as we are working with one heater in run time /* if ((Heater1000Slices + Heater200aSlices +2)>NumberOFSlicesInUse) { LOG_ERROR (NumberOFSlicesInUse, "proportional time slices too high too high"); return ERROR;//NumberOFSlicesInUse = MAX_TIMESLICES; } */ //mark the time slices for heaters operation as empty / Heater1000 / Heater 200 memset (TimeSliceAllocation,0xFF,sizeof(TimeSliceAllocation)); for (Slice_i = 0; Slice_i < Heater1000Slices;Slice_i++ ) TimeSliceAllocation[Slice_i] = HEATER_TYPE__DryerMainHeater; for (Slice_i = Heater1000Slices+1; Slice_i <= Heater1000Slices+Heater200aSlices;Slice_i++ ) TimeSliceAllocation[Slice_i] = HEATER_TYPE__DryerSecondaryHeater; return OK; } /* * HeaterRecalculateHeaterParams - prepare the time slices for D/C heaters operation * called by the general hardware HWConfigurationFunc * parameters - the cycle time for the coordinated operation, the size (in MCU cycles) of a single step. */ uint32_t HeaterRecalculateHeaterParams(uint32_t deviceId, uint32_t new_outputproportionalpowerlimit) { // calculate how many milliseconds is in each operating cycle (should be an integer number) //uint32_t MillisecondsPerChange = OutputProportionalSingleStep/120000; // calculate how many time slices are used. the total cycle time / the length of one operating cycle. (one added to put a time gap??? TBD) //NumberOFSlicesInUse = (OutputProportionalCycleTime/MillisecondsPerChange); if (NumberOFSlicesInUse > MAX_TIMESLICES ) { LOG_ERROR (NumberOFSlicesInUse, "NumberOFSlicesInUse too high"); return ERROR;//NumberOFSlicesInUse = MAX_TIMESLICES; } // all numbers are rounded down. better to have carefully calculated numbers if (new_outputproportionalpowerlimit > HeaterControl[deviceId].outputproportionalpowerlimit) new_outputproportionalpowerlimit = HeaterControl[deviceId].outputproportionalpowerlimit; //mark the time slices for heaters operation as empty / Heater1000 / Heater 200 DCTimeSliceAllocation[deviceId] = (new_outputproportionalpowerlimit/*/100*/ * NumberOFSlicesInUse) / 100; return OK; }