/************************************************************************************************************************ * 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" /******************** 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[MAX_HEATERS_NUM] = {0}; HeaterControlConfig_t HeaterPIDConfig[MAX_HEATERS_NUM] = {0}; uint32_t HeaterId2PT100Id[MAX_HEATERS_NUM] = {ANALOG_DRYER_TEMP1,ANALOG_DRYER_TEMP2,ANALOG_DRYER_TEMP3,TEMP_SENSE_ANALOG_DYEINGH_TEMP1,TEMP_SENSE_ANALOG_DYEINGH_TEMP2,TEMP_SENSE_ANALOG_DYEINGH_TEMP3,TEMP_SENSE_ANALOG_DYEINGH_TEMP4,ANALOG_MIXCHIP_TEMP}; bool AcHeaterConfigured[MAX_AC_HEATERS] = {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) { //ROM_TimerDisable(Heater_timerBase, TIMER_A); FPGA_SensorInitConfig(); return OK; } char stubToken[36] = {0}; void HeatingTestRequest(MessageContainer* requestContainer) { //#ifdef DEBUG_TEST_FUNCTIONS MessageContainer responseContainer; uint8_t* container_buffer; uint32_t status = 0; HardwarePidControlType HeaterId1,HeaterId2; StubHeatingTestRequest* request = stub_heating_test_request__unpack(NULL, requestContainer->data.len, requestContainer->data.data); HeaterId1 = request->hardwarepidcontrol1->hardwarepidcontroltype; status += HeaterConfigRequestMessage(request->hardwarepidcontrol1); HeaterId2 = request->hardwarepidcontrol2->hardwarepidcontroltype; status += HeaterConfigRequestMessage(request->hardwarepidcontrol2); if (request->has_dryerzone1temp) { if (request->dryerzone1temp) status |= HeaterCommandRequestMessage( HeaterId1, true, request->dryerzone1temp); else status |= HeaterCommandRequestMessage( HeaterId1, false, request->dryerzone1temp); } if (request->has_dryerzone2temp) { if (request->dryerzone2temp) status |= HeaterCommandRequestMessage( HeaterId2, true, request->dryerzone2temp); else status |= HeaterCommandRequestMessage( HeaterId2, false, request->dryerzone2temp); } HeaterConfigSetSharedHeatersParams(1000,120000*12); ControlStart(); StubHeatingTestResponse response = STUB_HEATING_TEST_RESPONSE__INIT; responseContainer = createContainer(MESSAGE_TYPE__StubHeatingTestResponse, requestContainer->token, false, &response, &stub_heating_test_response__pack, &stub_heating_test_response__get_packed_size); container_buffer = malloc(message_container__get_packed_size(&responseContainer)); if (status) { responseContainer.has_error = true; responseContainer.error = (ErrorCode)status; } size_t container_size = message_container__pack(&responseContainer, container_buffer); free(responseContainer.data.data); //USBCDCD_sendData(container_buffer, container_size,10); SendChars(container_buffer, container_size); //free(container_buffer); //free(requestContainer); stub_heating_test_request__free_unpacked(request,NULL); //#else // LOG_ERROR (-1, "Heating Control not on debug"); // return ERROR; //#endif } void HeatingTestPollRequest(MessageContainer* requestContainer) { //uint8_t* container_buffer; StubHeatingTestPollRequest* request = stub_heating_test_poll_request__unpack(NULL, requestContainer->data.len, requestContainer->data.data); strcpy (stubToken, requestContainer->token); /* StubHeatingTestPollResponse response = STUB_HEATING_TEST_POLL_RESPONSE__INIT; responseContainer = createContainer(MESSAGE_TYPE__StubHeatingTestPollResponse, requestContainer->token, false, &response, &stub_heating_test_poll_response__pack, &stub_heating_test_poll_response__get_packed_size); container_buffer = malloc(message_container__get_packed_size(&responseContainer)); if (status) { responseContainer.has_error = true; responseContainer.error = (ErrorCode)status; } size_t container_size = message_container__pack(&responseContainer, container_buffer); free(responseContainer.data.data); SendChars(container_buffer, container_size); //free(container_buffer);*/ // free(requestContainer); // free(request); stub_heating_test_poll_request__free_unpacked(request,NULL); } void HeatingTestSendResonse(uint32_t status, bool last,bool heater1Active,bool heater2Active, int temperature1, int temperature2,int Heater1Percentage,int Heater2Percentage, char* Message) { MessageContainer responseContainer; uint8_t* container_buffer; // uint8_t container_buffer[50]; if (stubToken[0] == 0) return; StubHeatingTestPollResponse response = STUB_HEATING_TEST_POLL_RESPONSE__INIT; /* protobuf_c_boolean has_heatergroupid; uint32_t heatergroupid; protobuf_c_boolean has_zone1temp; uint32_t zone1temp; protobuf_c_boolean has_zone2temp; uint32_t zone2temp; protobuf_c_boolean has_heater1active; protobuf_c_boolean heater1active; protobuf_c_boolean has_heater2active; protobuf_c_boolean heater2active; protobuf_c_boolean has_heater1percentage; uint32_t heater1percentage; protobuf_c_boolean has_heater2percentage; uint32_t heater2percentage; void HeatingTestSendResonse(uint32_t status, bool last,bool heater1Active,bool heater2Active, int temperature1, int temperature2,int Heater1Percentage,int Heater2Percentage) */ response.has_heater1active = true; response.heater1active = heater1Active; response.has_heater1percentage = true; response.heater1percentage = Heater1Percentage; response.has_zone1temp = true; response.zone1temp = temperature1; response.has_heater2active = true; response.heater2active = heater2Active; response.has_heater2percentage = true; response.heater2percentage = Heater2Percentage; response.has_zone2temp = true; response.zone2temp = temperature2; response.infomessage = Message; responseContainer = createContainer(MESSAGE_TYPE__StubHeatingTestPollResponse, stubToken, last, &response, &stub_heating_test_poll_response__pack, &stub_heating_test_poll_response__get_packed_size); //setContainerContinuous responseContainer.continuous = true; container_buffer = malloc(message_container__get_packed_size(&responseContainer)); if (status) { responseContainer.has_error = true; responseContainer.error = (ErrorCode)status; } size_t container_size = message_container__pack(&responseContainer, container_buffer); free(responseContainer.data.data); //USBCDCD_sendData(container_buffer, container_size,10); SendChars(container_buffer, container_size); //free(container_buffer); // stubToken[0] = 0; } uint32_t HeaterConfigRequestMessage(HardwarePidControl* request) { //uint32_t status = OK; HardwarePidControlType HeaterId; HeaterId = request->hardwarepidcontroltype; int ValidationError = 0; if (HeaterId< MAX_HEATERS_NUM) { HeaterControl[HeaterId].configured = true; HeaterControl[HeaterId].id = HeaterId; //strncpy (HeaterControl[HeaterId].name, request->name, 20); HeaterControl[HeaterId].outputproportionalpowerlimit = request->outputproportionalpowerlimit; HeaterControl[HeaterId].outputproportionalband = request->outputproportionalband; HeaterControl[HeaterId].integraltime = request->integraltime; HeaterControl[HeaterId].derivativetime = request->derivativetime; HeaterControl[HeaterId].sensorcorrectionadjustment = request->sensorcorrectionadjustment; //HeaterControl[HeaterId].sensortypeandsetpointlimits = request->sensortypeandsetpointlimits; HeaterControl[HeaterId].setpointramprateorsoftstartramp = request->setpointramprateorsoftstartramp; HeaterControl[HeaterId].setpointcontroloutputrate = request->setpointcontroloutputrate; HeaterControl[HeaterId].controloutputtype = request->controloutputtype; HeaterControl[HeaterId].ssrcontroloutputtype = request->ssrcontroloutputtype; HeaterControl[HeaterId].outputonoffhysteresisvalues = request->outputonoffhysteresisvalue; HeaterControl[HeaterId].processvariablesamplingrate = request->processvariablesamplingrate; HeaterControl[HeaterId].pvinputfilterfactormode = request->pvinputfilterfactormode; //HeaterControl[HeaterId].kp = 0.5; //HeaterControl[HeaterId].ki = 0.1; //HeaterControl[HeaterId].kd = 0.0; HeaterControl[HeaterId].kp = request->proportionalgain; HeaterControl[HeaterId].ki = request->integraltime; HeaterControl[HeaterId].kd = request->derivativetime; if (HeaterId < MAX_AC_HEATERS) AcHeaterConfigured[HeaterId] = true; //check if all A/C heaters are defined. if they are - validate the configuration if (((HeaterId == HARDWARE_PID_CONTROL_TYPE__DryerHeater1000w)||(HeaterId == HARDWARE_PID_CONTROL_TYPE__DryerHeater200w1)) &&HeaterControl[HARDWARE_PID_CONTROL_TYPE__DryerHeater1000w].configured &&HeaterControl[HARDWARE_PID_CONTROL_TYPE__DryerHeater200w1].configured /*&&HeaterControl[HARDWARE_PID_CONTROL_TYPE__DryerHeater200w2].id*/) { if (HeaterControl[HARDWARE_PID_CONTROL_TYPE__DryerHeater1000w].outputproportionalpowerlimit + HeaterControl[HARDWARE_PID_CONTROL_TYPE__DryerHeater200w1].outputproportionalpowerlimit /*+ HeaterControl[HARDWARE_PID_CONTROL_TYPE__DryerHeater200w2].outputproportionalpowerlimit*/> 100) ValidationError += 2; if (ValidationError) { LOG_ERROR (ValidationError, "Validation Error in Heaters Control"); return ERROR; } else { HeaterConfigSetSharedHeatersParams(1000,120000*12); // initial setting 50Mhz } } 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[HARDWARE_PID_CONTROL_TYPE__DryerHeater1000w].outputproportionalpowerlimit * NumberOFSlicesInUse / 100; Heater200aSlices = HeaterControl[HARDWARE_PID_CONTROL_TYPE__DryerHeater200w1].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] = HARDWARE_PID_CONTROL_TYPE__DryerHeater1000w; for (Slice_i = Heater1000Slices+1; Slice_i <= Heater1000Slices+Heater200aSlices;Slice_i++ ) TimeSliceAllocation[Slice_i] = HARDWARE_PID_CONTROL_TYPE__DryerHeater200w1; return OK; } /* * 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 HeaterRecalculateSharedHeatersParams(uint32_t deviceId, uint32_t new_outputproportionalpowerlimit) { int Slice_i; int Heater1000Slices,Heater200aSlices /*,Heater200bSlices Currently both 200W heaters will work together*/; 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 HeaterControl[deviceId].outputproportionalpowerlimit = new_outputproportionalpowerlimit; Heater1000Slices = HeaterControl[HARDWARE_PID_CONTROL_TYPE__DryerHeater1000w].outputproportionalpowerlimit * NumberOFSlicesInUse / 100; Heater200aSlices = HeaterControl[HARDWARE_PID_CONTROL_TYPE__DryerHeater200w1].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] = HARDWARE_PID_CONTROL_TYPE__DryerHeater1000w; for (Slice_i = Heater1000Slices+1; Slice_i <= Heater1000Slices+Heater200aSlices;Slice_i++ ) TimeSliceAllocation[Slice_i] = HARDWARE_PID_CONTROL_TYPE__DryerHeater200w1; 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 HeaterControl[deviceId].outputproportionalpowerlimit = new_outputproportionalpowerlimit; //mark the time slices for heaters operation as empty / Heater1000 / Heater 200 DCTimeSliceAllocation[deviceId] = HeaterControl[deviceId].outputproportionalpowerlimit * NumberOFSlicesInUse / 10000; return OK; }