/************************************************************************** * * Copyright (c) 2024-2024 Diality Inc. - All Rights Reserved. * * THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, IN PART OR IN * WHOLE, WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. * * @file Heaters.c * * @author (last) Sean Nash * @date (last) 20-Dec-2024 * * @author (original) Sean Nash * @date (original) 20-Dec-2024 * ***************************************************************************/ #include // Used for mathematical operations #include "FpgaRO.h" #include "Heaters.h" #include "Level.h" #include "MessageSupport.h" #include "Messaging.h" //#include "NVDataMgmt.h" #include "OperationModes.h" #include "PersistentAlarm.h" #include "PIControllers.h" #include "SafetyShutdown.h" #include "TaskGeneral.h" #include "TaskPriority.h" #include "TemperatureSensors.h" #include "Timers.h" #include "Utilities.h" /** * @addtogroup Heaters * @{ */ // ********** private definitions ********** #define HEATERS_MAX_DUTY_CYCLE 1.00F ///< Heaters max duty cycle (100%) or ON state #define HEATERS_MIN_DUTY_CYCLE 0.00F ///< Heaters minimum duty cycle (0.00%) or OFF state #define HEATER_ON_CTRL_DUTY_CYCLE 1.00F ///< Heater ON control duty cycle. #define HEATERS_DISINFECT_DUTY_CYCLE 0.80F ///< Heaters disinfect cycle. #define HEATERS_DISINFECT_TRANSFER_DUTY_CYCLE 0.60F ///< Heaters disinfect transfer duty cycle. #define HEATERS_DISINFECT_TEMPERATURE_DRIFT_C 3.0F ///< Heaters disinfect temperature drift in C. #define HEATERS_ZERO_DELTA_TEMP_C 0.0F ///< Heaters zero delta temperature in C. #define HEATERS_DUTY_CYCLE_CONVERSION_FACTOR 100.0F ///< Heaters duty cycle 0: OFF, 100: 100% duty cycle. #define HEATER_P_COEFFICIENT 1.0F ///< P Term for primary heater control. #define HEATER_I_COEFFICIENT 1.0F ///< I Term for primary heater control. #define HEATER_DATA_PUBLISH_INTERVAL ( MS_PER_SECOND / TASK_PRIORITY_INTERVAL ) ///< Heater data publish interval. #define HEATER_TEMP_CONTROL_TOLERANCE 2.0F ///< Primary Heater temp tolerance for ON/Off control #define HEATER_TARGET_TEMPERATURE_MIN 10.0F ///< Minimum allowed target temperature for the heaters. #define HEATER_TARGET_TEMPERATURE_MAX 90.0F ///< Maximum allowed target temperature for the heaters. #define HEATER_ON_NO_FLUID_TIMEOUT_MS ( 10 * MS_PER_SECOND ) ///< Heater on with no flow time out in milliseconds. #define HEATER_MAX_OPERATING_VOLTAGE_V 24.0F ///< Heater max operating voltage in volts. #define HEATER_VOLTAGE_OUT_OF_RANGE_TIMEOUT_MS ( 2 * MS_PER_SECOND ) ///< Heater voltage out of range time out in milliseconds. #define HEATER_MAX_VOLTAGE_OUT_OF_RANGE_TOL 0.2F ///< Heater max voltage out of range tolerance. #define HEATER_CONTROL_INTERVAL_COUNT ( ( 1 * MS_PER_SECOND ) / TASK_GENERAL_INTERVAL ) ///< Heatereater control interval count. #define DATA_PUBLISH_COUNTER_START_COUNT 70 ///< Data publish counter start count. //static const F32 HEATER_VOLTAGE_TOLERANCE_V = HEATERS_MAX_OPERATING_VOLTAGE_V * HEATERS_MAX_VOLTAGE_OUT_OF_RANGE_TOL; ///< Heater voltage tolerance in volts. /// Heater exec states typedef enum Heater_Exec_States { HEATER_EXEC_STATE_OFF = 0, ///< Heater controller state off. HEATER_EXEC_STATE_RAMP_TO_TARGET, ///< Heater controller state ramp to target. HEATER_EXEC_STATE_CONTROL_TO_TARGET, ///< Heater controller state control to target. HEATER_EXEC_STATE_CONTROL_TO_DISINFECT_TARGET, ///< Heater controller state control to disinfect (heat) target. NUM_OF_HEATER_STATES, ///< Number of heater states. } HEATER_STATE_T; /// Heaters data structure typedef struct { HEATER_STATE_T state; ///< Heater state. BOOL startHeaterSignal; ///< Heater start indication flag. BOOL heaterOnState; ///< Heater on/off status flag. F32 targetFlowLPM; ///< Heater target flow in L/min to calculate the duty cycle. F32 nomTargetFlowLPM; ///< Heater nominal target flow in L/min. BOOL hasTargetTempChanged; ///< Heater target temperature change flag indicator. U32 controlIntervalCounter; ///< Heater control interval counter. BOOL isThisFirstControl; ///< Heater is this first control interval. F32 prevDiaTargetFlowLPM; ///< Heater previous target dialysate flow in L/min. } HEATER_STATUS_T; /// Payload record structure for heaters start request typedef struct { U32 heaterID; ///< Heater ID (0: Primary, 1: Trimmer) U32 startStop; ///< Heater Start:1 and Stop: 0 F32 temperature; ///< Temperature range ( 10.0 to 90.0 deg ) } HEATER_START_CMD_PAYLOAD_T; // ********** private data ********** static HEATER_STATUS_T heatersStatus; ///< Heaters status. static OVERRIDE_F32_T targetTempC; ///< Heater target temperature. static OVERRIDE_F32_T control; ///< Heater control ( Primary : On/Off, Trimmer : Dutycycle). static U32 dataPublicationTimerCounter; ///< Data publication timer counter. static OVERRIDE_U32_T heaterDataPublishInterval; ///< Heater data publish time interval. // ********** private function prototypes ********** static HEATER_STATE_T handleHeaterStateOff( void ); static HEATER_STATE_T handleHeaterStateRampToTarget( void ); static HEATER_STATE_T handleHeaterStateControlToTarget( void ); static HEATER_STATE_T handleHeaterStateControlToDisinfectTarget( void ); static void setHeaterControl( void ); static F32 getHeaterControl( void ); static void publishHeatersData( void ); //static void monitorHeatersVoltage( void ); /*********************************************************************//** * @brief * The initHeater initializes the heaters controller unit. * @details \b Inputs: none * @details \b Outputs: Heaters unit variables initialized. * @return none *************************************************************************/ void initHeater( void ) { dataPublicationTimerCounter = DATA_PUBLISH_COUNTER_START_COUNT; targetTempC.data = 0.0F; targetTempC.ovData = 0.0F; targetTempC.ovInitData = 0.0F; targetTempC.override = OVERRIDE_RESET; heaterDataPublishInterval.data = HEATER_DATA_PUBLISH_INTERVAL; heaterDataPublishInterval.ovData = HEATER_DATA_PUBLISH_INTERVAL; heaterDataPublishInterval.ovInitData = HEATER_DATA_PUBLISH_INTERVAL; heaterDataPublishInterval.override = OVERRIDE_RESET; control.data = HEATERS_MIN_DUTY_CYCLE; control.ovData = HEATERS_MIN_DUTY_CYCLE; control.ovInitData = HEATERS_MIN_DUTY_CYCLE; control.override = OVERRIDE_RESET; heatersStatus.state = HEATER_EXEC_STATE_OFF; heatersStatus.startHeaterSignal = FALSE; heatersStatus.heaterOnState = FALSE; heatersStatus.targetFlowLPM = 0.0F; heatersStatus.nomTargetFlowLPM = 0.0F; heatersStatus.hasTargetTempChanged = FALSE; heatersStatus.controlIntervalCounter = 0; heatersStatus.isThisFirstControl = TRUE; heatersStatus.prevDiaTargetFlowLPM = 0.0F; setHeaterControl(); // // Initialize the primary controller PI controller // initializePIController( PI_CONTROLLER_ID_PRIMARY_HEATER, HEATERS_MIN_DUTY_CYCLE, PRIMARY_HEATER_P_COEFFICIENT, PRIMARY_HEATER_I_COEFFICIENT, // HEATERS_MIN_DUTY_CYCLE, HEATERS_MAX_DUTY_CYCLE ); // // // Initialize the trimmer heater PI controller // initializePIController( PI_CONTROLLER_ID_TRIMMER_HEATER, HEATERS_MIN_DUTY_CYCLE, TRIMMER_HEATER_P_COEFFICIENT, TRIMMER_HEATER_I_COEFFICIENT, // HEATERS_MIN_DUTY_CYCLE, HEATERS_MAX_DUTY_CYCLE ); // Initialize the persistent alarms //initPersistentAlarm( ALARM_ID_DD_PRIMARY_HEATER_VOLTAGE_OUT_OF_RANGE, 0, HEATERS_VOLTAGE_OUT_OF_RANGE_TIMEOUT_MS ); //initPersistentAlarm( ALARM_ID_DD_TRIMMER_HEATER_VOLTAGE_OUT_OF_RANGE, 0, HEATERS_VOLTAGE_OUT_OF_RANGE_TIMEOUT_MS ); // initPersistentAlarm( ALARM_ID_RO_FLUID_TOO_LOW_WHILE_HEATER_IS_ON, 0, HEATER_ON_NO_FLUID_TIMEOUT_MS ); } /*********************************************************************//** * @brief * The setHeaterTargetTemperature function sets the target temperature of * the heater. * @details \b Inputs: none * @details \b Outputs: heaterStatus * @param targetTemperature: target temperature of that the heater has to * heat the fluid * @return TRUE if the temperature was set, otherwise FALSE *************************************************************************/ BOOL setHeaterTargetTemperature( F32 targetTemperature ) { BOOL result = FALSE; // Assume the target temperature has not changed heatersStatus.hasTargetTempChanged = FALSE; // Check if the requested temperature is within the allowed range if ( ( targetTemperature >= HEATER_TARGET_TEMPERATURE_MIN ) && ( targetTemperature <= HEATER_TARGET_TEMPERATURE_MAX ) ) { targetTempC.data = targetTemperature; heatersStatus.hasTargetTempChanged = TRUE; result = TRUE; } return result; } /*********************************************************************//** * @brief * The getHeaterTargetTemperature function returns the heater target * temperature. * @details \b Inputs: none * @details \b Outputs: targetTempC * @return the heater target temperature *************************************************************************/ F32 getHeaterTargetTemperature( void ) { F32 targetTemp = getF32OverrideValue( &targetTempC ); return targetTemp; } /*********************************************************************//** * @brief * The isHeaterOn function returns the heater status whether it is on or off. * @details \b Inputs: heaterStatus * @details \b Outputs: none * @return heater on/off status *************************************************************************/ BOOL isHeaterOn( void ) { return heatersStatus.heaterOnState; } /*********************************************************************//** * @brief * The startHeater function starts the given heater by setting the flag. * @details \b Inputs: heatersStatus * @details \b Outputs: startHeaterSignal * @return None *************************************************************************/ void startHeater( void ) { if ( HEATER_EXEC_STATE_OFF == heatersStatus.state ) { heatersStatus.startHeaterSignal = TRUE; } } /*********************************************************************//** * @brief * The stopHeater function stops the heater. * @details \b Inputs: none * @details \b Outputs: heaterStatus, control * @return none *************************************************************************/ void stopHeater( void ) { heatersStatus.startHeaterSignal = FALSE; heatersStatus.heaterOnState = FALSE; control.data = HEATERS_MIN_DUTY_CYCLE; heatersStatus.state = HEATER_EXEC_STATE_OFF; // update duty cycle setHeaterControl(); } /*********************************************************************//** * @brief * The execHeaterMonitor function monitors the status of the heater. * The internal temperature sensors and the voltages of the heater are * monitored. The floater level is continuously checked and if there is no * fluid at defined level, the heaters are turned off. * @details \b Inputs: heaterStatus * @details \b Outputs: heaterStatus * @return none *************************************************************************/ void execHeaterMonitor( void ) { // Check if the heater is on and if it is, check the level sensor status // if ( TRUE == heatersStatus[ heater ].heaterOnState ) // { // BOOL isLevelLow = ( ( getLevelStatus() != 0 )? FALSE : TRUE ); // // checkPersistentAlarm( ALARM_ID_RO_FLUID_TOO_LOW_WHILE_HEATER_IS_ON, isLevelLow, 0.0F, 0.0F ); // } // else // { // checkPersistentAlarm( ALARM_ID_RO_FLUID_TOO_LOW_WHILE_HEATER_IS_ON, FALSE, 0.0F, 0.0F ); // } // Monitor heater voltage //monitorHeatersVoltage(); // Check for data publication publishHeatersData(); } /*********************************************************************//** * @brief * The execHeatersControl function executes the heaters state machine. * @details \b Inputs: heaterStatus * @details \b Outputs: heaterStatus * @details \b Alarms: ALARM_ID_RO_SOFTWARE_FAULT when invalid heater * executive state found. * @return none *************************************************************************/ void execHeatersControl( void ) { switch( heatersStatus.state ) { case HEATER_EXEC_STATE_OFF: heatersStatus.state = handleHeaterStateOff(); break; case HEATER_EXEC_STATE_RAMP_TO_TARGET: heatersStatus.state = handleHeaterStateRampToTarget(); break; case HEATER_EXEC_STATE_CONTROL_TO_TARGET: heatersStatus.state = handleHeaterStateControlToTarget(); break; case HEATER_EXEC_STATE_CONTROL_TO_DISINFECT_TARGET: heatersStatus.state = handleHeaterStateControlToDisinfectTarget(); break; default: // The heater is in an unknown state. Alarm, turn heater off and switch to off state SET_ALARM_WITH_2_U32_DATA( ALARM_ID_RO_SOFTWARE_FAULT, SW_FAULT_ID_HEATER_INVALID_EXEC_STATE, (U32)heatersStatus.state ); stopHeater(); break; } // Check if the heater is requested to be off if ( FALSE == heatersStatus.heaterOnState ) { // stop the heater stopHeater(); } } /*********************************************************************//** * @brief * The handleHeaterStateOff function handles the heater off state and transitions * to heater On condition when the heater start flag is set to true. * @details \b Inputs: heaterStatus * @details \b Outputs: heaterStatus * @return next state of the heater control state machine *************************************************************************/ static HEATER_STATE_T handleHeaterStateOff( void ) { HEATER_STATE_T state = HEATER_EXEC_STATE_OFF; if ( TRUE == heatersStatus.startHeaterSignal ) { heatersStatus.heaterOnState = TRUE; heatersStatus.startHeaterSignal = FALSE; // proceed to ramp state state = HEATER_EXEC_STATE_RAMP_TO_TARGET; } return state; } /*********************************************************************//** * @brief * The handleHeaterStateRampToTarget function handles the heaters' control * while they are ramping to target temperature. * @details \b Inputs: heaterStatus * @details \b Outputs: heaterStatus * @return next state of the heater control state machine *************************************************************************/ static HEATER_STATE_T handleHeaterStateRampToTarget( void ) { HEATER_STATE_T state = HEATER_EXEC_STATE_RAMP_TO_TARGET; RO_OP_MODE_T opMode = getCurrentOperationMode(); F32 targetTemperature = getHeaterTargetTemperature(); // if ( RO_MODE_HEAT != opMode ) { control.data = HEATER_ON_CTRL_DUTY_CYCLE; state = HEATER_EXEC_STATE_CONTROL_TO_TARGET; } // else // { // // TODO : Calculate required duty cycle // state = HEATER_EXEC_STATE_CONTROL_TO_DISINFECT_TARGET; // } setHeaterControl(); return state; } /*********************************************************************//** * @brief * The handleHeaterStateControlToTarget function handles the heaters' control * to target while the heater is targeting to reach to temperature. * @details \b Inputs: heaterStatus * @details \b Outputs: heaterStatus * @return next state of the state machine *************************************************************************/ static HEATER_STATE_T handleHeaterStateControlToTarget( void ) { HEATER_STATE_T state = HEATER_EXEC_STATE_CONTROL_TO_TARGET; F32 targetTemperature = getHeaterTargetTemperature(); F32 measuredTemperature = 0.0F; if( ++heatersStatus.controlIntervalCounter > HEATER_CONTROL_INTERVAL_COUNT ) { measuredTemperature = getTemperatureValue( TEMP_SENSOR_TRO1 ); if ( measuredTemperature >= targetTemperature ) { // Turn off heater control.data = HEATERS_MIN_DUTY_CYCLE; } else { // Turn On heater control.data = HEATER_ON_CTRL_DUTY_CYCLE; } //control = runPIController( PI_CONTROLLER_ID_PRIMARY_HEATER, targetTemperature, measuredTemperature ); heatersStatus.hasTargetTempChanged = FALSE; heatersStatus.controlIntervalCounter = 0; setHeaterControl(); } return state; } /*********************************************************************//** * @brief * The handleHeaterStateControlToDisinfectTarget function handles the * heaters' control to target while the operation mode is heat or chemical * disinfects. * @details \b Inputs: heaterStatus * @details \b Outputs: heaterStatus * @param heater: The heater Id that its on state is handled * @return next state of the state machine *************************************************************************/ static HEATER_STATE_T handleHeaterStateControlToDisinfectTarget( void ) { HEATER_STATE_T state = HEATER_EXEC_STATE_CONTROL_TO_DISINFECT_TARGET; //TODO : update dutycycle for the heat disinfect state setHeaterControl(); return state; } /*********************************************************************//** * @brief * The setHeaterControl function sets the duty cycle of a heater. * @details \b Inputs: control * @details \b Outputs: FPGA heater control * @return none *************************************************************************/ static void setHeaterControl( void ) { F32 ctrl; ctrl = getHeaterControl(); // setFPGACPrimaryHeaterOnOffControl( (BOOL)ctrl ); // TODO ctrl is F32 - why casting as BOOL???? // TODO - implement FPGA set function } /*********************************************************************//** * @brief * The getHeaterControl function returns the heater's duty cycle. * @details \b Inputs: heaterStatus * @details \b Outputs: none * @return PWM duty cycle for the heater *************************************************************************/ static F32 getHeaterControl( void ) { F32 duty = getF32OverrideValue( &control ); return duty; } /*********************************************************************//** * @brief * The monitorHeatersVoltage function monitors the heaters' voltages * @details \b Inputs: Voltage range * @details \b Outputs: none * @details \b Alarms: ALARM_ID_DD_MAIN_PRIMARY_HEATER_VOLTAGE_OUT_OF_RANGE when * primary heater voltage found out of range. * @details \b Alarms: ALARM_ID_DD_TRIMMER_HEATER_VOLTAGE_OUT_OF_RANGE when * trimmer heater voltage found out of range. * @return none *************************************************************************/ //static void monitorHeatersVoltage( void ) //{ // F32 mainPriVoltage = getMonitoredLineLevel( MONITORED_LINE_24V_GND_MAIN_PRIM_HTR_V ); // F32 trimmerVoltage = getMonitoredLineLevel( MONITORED_LINE_24V_GND_TRIM_HTR_V ); // // // Voltage to PWM is reverse. If PWM = 0 -> V = 24V // F32 mainPriDC = getHeaterControl( DD_PRIMARY_HEATER ); // F32 trimmerDC = getHeaterControl( DD_TRIMMER_HEATER ); // // // The expected voltage is the inverse of the duty cycle // F32 mainPriExpectedVoltage = HEATERS_MAX_OPERATING_VOLTAGE_V * ( 1.0F - mainPriDC ); // F32 trimmerExpectedVoltage = HEATERS_MAX_OPERATING_VOLTAGE_V * ( 1.0F - trimmerDC ); // // BOOL isMainPriOut = FALSE; // BOOL isTrimmerOut = FALSE; // // // If the system is DVT, check the FPGA persistent alarm of the main primary heater's voltage ADC // checkFPGAPersistentAlarms( FPGA_PERS_ERROR_MAIN_PRIMARY_HEATER_VOLTAGE_ADC, getFPGAHeaterGateADCReadCount() ); // // isMainPriOut = ( fabs( mainPriExpectedVoltage - mainPriVoltage ) > HEATERS_VOLTAGE_TOLERANCE_V ? TRUE : FALSE ); // isTrimmerOut = ( fabs( trimmerExpectedVoltage - trimmerVoltage ) > HEATERS_VOLTAGE_TOLERANCE_V ? TRUE : FALSE ); // // if ( getCurrentOperationMode() != DD_MODE_INIT ) // { // checkPersistentAlarm( ALARM_ID_DD_MAIN_PRIMARY_HEATER_VOLTAGE_OUT_OF_RANGE, isMainPriOut, mainPriDC, HEATERS_VOLTAGE_TOLERANCE_V ); // checkPersistentAlarm( ALARM_ID_DD_TRIMMER_HEATER_VOLTAGE_OUT_OF_RANGE, isTrimmerOut, trimmerDC, HEATERS_VOLTAGE_TOLERANCE_V ); // } //} /*********************************************************************//** * @brief * The publishHeatersData function publishes the heaters data info * at the defined time interval. * @details \b Inputs: dataPublicationTimerCounter * @details \b Outputs: dataPublicationTimerCounter * @details \b Message \b Sent: MSG_ID_DD_HEATERS_DATA to publish * heaters data. * @return none *************************************************************************/ static void publishHeatersData( void ) { if ( ++dataPublicationTimerCounter >= getU32OverrideValue( &heaterDataPublishInterval ) ) { HEATERS_DATA_T data; data.heaterHroDC = getHeaterControl(); data.heaterHroTargetTemp = getHeaterTargetTemperature(); data.heaterHroState = heatersStatus.state; data.heaterHroControlCounter = heatersStatus.controlIntervalCounter; dataPublicationTimerCounter = 0; broadcastData( MSG_ID_RO_HEATER_DATA, COMM_BUFFER_OUT_CAN_RO_BROADCAST, (U08*)&data, sizeof( HEATERS_DATA_T ) ); } } /************************************************************************* * TEST SUPPORT FUNCTIONS *************************************************************************/ /*********************************************************************//** * @brief * The testHeatersDataPublishIntervalOverride function overrides the * heaters data publish interval. * @details \b Inputs: heaterDataPublishInterval * @details \b Outputs: heaterDataPublishInterval * @param Override message from Dialin which includes the interval * (in ms) to override the heaters data broadcast interval to. * @return TRUE if override successful, FALSE if not *************************************************************************/ BOOL testHeatersDataPublishIntervalOverride( MESSAGE_T *message ) { BOOL result = u32BroadcastIntervalOverride( message, &heaterDataPublishInterval, TASK_PRIORITY_INTERVAL ); return result; } /*********************************************************************//** * @brief * The testHeaterDutyCycleOverride function overrides the heater's * duty cycle. * @details \b Inputs: heatersStatus * @details \b Outputs: heatersStatus * @param message Override message from Dialin which includes the duty cycle * of the heater. * @return TRUE if the override was successful otherwise FALSE *************************************************************************/ BOOL testHeaterDutyCycleOverride( MESSAGE_T *message ) { BOOL result = f32Override( message, &control ); return result; } /*********************************************************************//** * @brief * The testHeaterTargetTemperatureOverride function overrides the heater's * target temperature. * @details \b Inputs: targetTempC * @details \b Outputs: targetTempC * @param message Override message from Dialin which includes the target * temperature of the heater. * @return TRUE if the override was successful otherwise FALSE *************************************************************************/ BOOL testHeaterTargetTemperatureOverride( MESSAGE_T *message ) { BOOL result = f32Override( message, &targetTempC ); return result; } /*********************************************************************//** * @brief * The testHeaterStartStopOverride function starts/stops a given heater * at mentioned temperature. * @details \b Inputs: tester logged in * @details \b Outputs: heatersStatus[] * @param message set message from Dialin which includes the heater to set * and the state to set the heater to. * @return TRUE if set request is successful, FALSE if not *************************************************************************/ BOOL testHeaterStartStopOverride( MESSAGE_T *message ) { BOOL result = FALSE; // // Verify tester has logged in with TD // if ( TRUE == isTestingActivated() ) // { // // Verify payload length is valid // if ( sizeof( HEATER_START_CMD_PAYLOAD_T ) == message->hdr.payloadLen ) // { // HEATER_START_CMD_PAYLOAD_T payload; // // memcpy( &payload, message->payload, sizeof(HEATER_START_CMD_PAYLOAD_T) ); // // if ( (DD_HEATERS_T)payload.heaterID < NUM_OF_DD_HEATERS ) // { // // Handle start command // if ( ( TRUE == payload.startStop ) && // ( ( payload.temperature >= HEATER_TARGET_TEMPERATURE_MIN ) && ( payload.temperature <= HEATER_TARGET_TEMPERATURE_MAX ) ) ) // { // setHeaterTargetTemperature( (DD_HEATERS_T)payload.heaterID, payload.temperature ); // startHeater( (DD_HEATERS_T)payload.heaterID ); // result = TRUE; // } // // //Handle stop command // if ( FALSE == payload.startStop ) // { // stopHeater( (DD_HEATERS_T)payload.heaterID ); // result = TRUE; // } // } // } // } return result; } /**@}*/