/************************************************************************************************************************
* 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 <driverlib/timer.h>
#include <DataDef.h>
#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,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)
{
//ROM_TimerDisable(Heater_timerBase, TIMER_A);
FPGA_SensorInitConfig();
return OK;
}
void HeatingTestRequest(MessageContainer* requestContainer)
{
//#ifdef DEBUG_TEST_FUNCTIONS
MessageContainer responseContainer;
uint8_t* container_buffer;
uint32_t status = 0;
StubHeatingTestRequest* request = stub_heating_test_request__unpack(NULL, requestContainer->data.len, requestContainer->data.data);
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 = my_malloc(message_container__get_packed_size(&responseContainer));
//if (status)
{
responseContainer.has_error = true;
responseContainer.error = ERROR_CODE__JOB_UNSPECIFIED_ERROR;
}
size_t container_size = message_container__pack(&responseContainer, container_buffer);
my_free(responseContainer.data.data);
//USBCDCD_sendData(container_buffer, container_size,10);
SendChars(container_buffer, container_size);
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);
StubHeatingTestPollResponse response = STUB_HEATING_TEST_POLL_RESPONSE__INIT;
MessageContainer responseContainer;
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 = my_malloc(message_container__get_packed_size(&responseContainer));
{
responseContainer.has_error = true;
responseContainer.error = ERROR_CODE__JOB_UNSPECIFIED_ERROR;
}
size_t container_size = message_container__pack(&responseContainer, container_buffer);
my_free(responseContainer.data.data);
SendChars(container_buffer, container_size);
stub_heating_test_poll_request__free_unpacked(request,NULL);
}
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;
HeaterControl[HeaterId].outputproportionalpowerlimit = request->outputproportionalpowerlimit;
HeaterControl[HeaterId].outputproportionalband = request->outputproportionalband;
if (HeaterId == HARDWARE_PID_CONTROL_TYPE__DryerAirTemperature)
{
HeaterControl[HARDWARE_PID_CONTROL_TYPE__DryerHeaterMain].sensormaxvalue = request->sensormaxvalue;
HeaterControl[HARDWARE_PID_CONTROL_TYPE__DryerHeaterMain].sensorminvalue = request->sensorminvalue;
HeaterControl[HARDWARE_PID_CONTROL_TYPE__DryerHeaterSecondary].sensormaxvalue = request->sensormaxvalue;
HeaterControl[HARDWARE_PID_CONTROL_TYPE__DryerHeaterSecondary].sensorminvalue = request->sensorminvalue;
}
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;
//check if all A/C heaters are defined. if they are - validate the configuration
/*if (((HeaterId == HARDWARE_PID_CONTROL_TYPE__DryerHeaterMain)||(HeaterId == HARDWARE_PID_CONTROL_TYPE__DryerHeaterSecondary))
&&HeaterControl[HARDWARE_PID_CONTROL_TYPE__DryerHeaterMain].configured
&&HeaterControl[HARDWARE_PID_CONTROL_TYPE__DryerHeaterSecondary].configured)
{
if (HeaterControl[HARDWARE_PID_CONTROL_TYPE__DryerHeaterMain].outputproportionalpowerlimit
+ HeaterControl[HARDWARE_PID_CONTROL_TYPE__DryerHeaterSecondary].outputproportionalpowerlimit > 100)
LOG_ERROR (ValidationError, "Validation Error in Heaters Control");
return ERROR;
}*/
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__DryerHeaterMain].outputproportionalpowerlimit * NumberOFSlicesInUse / 100;
Heater200aSlices = HeaterControl[HARDWARE_PID_CONTROL_TYPE__DryerHeaterSecondary].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__DryerHeaterMain;
for (Slice_i = Heater1000Slices+1; Slice_i <= Heater1000Slices+Heater200aSlices;Slice_i++ ) TimeSliceAllocation[Slice_i] = HARDWARE_PID_CONTROL_TYPE__DryerHeaterSecondary;
return OK;
}
/*
* HeaterRecalculateSharedHeatersParams -
*
* 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;///100;
Heater1000Slices = HeaterControl[HARDWARE_PID_CONTROL_TYPE__DryerHeaterMain].outputproportionalpowerlimit * NumberOFSlicesInUse / 100;
Heater200aSlices = HeaterControl[HARDWARE_PID_CONTROL_TYPE__DryerHeaterSecondary].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] = HARDWARE_PID_CONTROL_TYPE__DryerHeaterMain;
for (Slice_i = Heater1000Slices+1; Slice_i <= Heater1000Slices+Heater200aSlices;Slice_i++ ) TimeSliceAllocation[Slice_i] = HARDWARE_PID_CONTROL_TYPE__DryerHeaterSecondary;
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/*/100*/ * NumberOFSlicesInUse) / 100;
return OK;
}