Index: firmware/App/Controllers/Heaters.c =================================================================== diff -u -r1923195b6564be4405a39a3ebf09c3d6026860b3 -rf215311725c002c9b9f2915e3502b89ae6a93c91 --- firmware/App/Controllers/Heaters.c (.../Heaters.c) (revision 1923195b6564be4405a39a3ebf09c3d6026860b3) +++ firmware/App/Controllers/Heaters.c (.../Heaters.c) (revision f215311725c002c9b9f2915e3502b89ae6a93c91) @@ -79,16 +79,17 @@ HEATER_EXEC_STATE_OFF = 0, ///< Heater exec state off. HEATER_EXEC_STATE_RAMP_TO_TARGET, ///< Heater exec state ramp to target. HEATER_EXEC_STATE_CONTROL_TO_TARGET, ///< Heater exec state control to target. + HEATER_EXEC_STATE_CONTROL_TO_DISINFECT_TARGET, ///< Heater exec state control to disinfect (heat or chemical) target. NUM_OF_HEATERS_STATE, ///< Number of heaters state. } HEATERS_STATE_T; /// Heaters data structure typedef struct { F32 targetTemp; // TODO do we need this anymore? ///< Heater target temperature. - F32 originalTargetTemp; ///< Heater original target temperature set by user. + F32 originalTargetTemp; ///< Heater original target temperature set by user. HEATERS_STATE_T state; ///< Heater state. - TEMPERATURE_SENSORS_T feedbackSensor; ///< Heater feedback sensor for controlling. + TEMPERATURE_SENSORS_T feedbackSensor; // TODO do we need this? ///< Heater feedback sensor for controlling. U32 controlTimerCounter; // TODO remove? Maybe use in heat disinfect ///< Heater control timer counter. BOOL startHeaterSignal; ///< Heater start indication flag. BOOL isHeaterOn; ///< Heater on/off status flag. @@ -97,7 +98,8 @@ U32 heaterOnWithNoFlowTimer; // TODO remove ///< Heater on with no flow timer. BOOL isFlowBelowMin; ///< Heater flow below minimum flag indicator. BOOL hasTargetTempChanged; ///< Heater target temperature change flag indicator. - F32 heaterEfficiency; + F32 heaterEfficiency; ///< Heater efficiency during the run. + BOOL hasTargetBeenReached; ///< Heater flag to indicate whether the target temperature has been reached. PI_CONTROLLER_ID_T controllerID; ///< Heater PI controller ID TODO remove this? U32 tempOutOfRangeTimer; ///< Heater temperature out of range timer TODO remove once the mechanical thermal cutoff was implemented @@ -115,6 +117,7 @@ static HEATERS_STATE_T handleHeaterStateOff( DG_HEATERS_T heater ); static HEATERS_STATE_T handleHeaterStateRampToTarget( DG_HEATERS_T heater ); static HEATERS_STATE_T handleHeaterStateControlToTarget( DG_HEATERS_T heater ); +static HEATERS_STATE_T handleHeaterStateControlToDisinfectTarget( DG_HEATERS_T heater ); static void setHeaterDutyCycle( DG_HEATERS_T heater, F32 pwm ); static F32 calculatePrimaryHeaterDutyCycle( F32 targetTemperature, F32 currentTemperature, F32 flow ); @@ -128,7 +131,7 @@ static void checkTrimmerHeaterTempSensors( void ); static void monitorHeatersVoltage( void ); static void checkHeaterOnStatus( DG_HEATERS_T heater ); -static void getHeatersEfficiencyFromRTCRAM(); +static void getHeatersEfficiencyFromRTCRAM( void ); /*********************************************************************//** * @brief @@ -161,7 +164,8 @@ heatersStatus[ heater ].targetROFlow = 0.0; heatersStatus[ heater ].controllerID = ( DG_PRIMARY_HEATER == heater ? 4 : PI_CONTROLLER_ID_TRIMMER_HEATER ); // TODO remove or refactor? heatersStatus[ heater ].hasTargetTempChanged = FALSE; - heatersStatus[ heater ].heaterEfficiency = 1.0; // Assuming 100% efficiency until it is updated + heatersStatus[ heater ].heaterEfficiency = 1.0; // Assuming 100% efficiency during initialization until it is updated + heatersStatus[ heater ].hasTargetBeenReached = FALSE; } // Initialize the PI controller for the trimmer heater @@ -187,18 +191,12 @@ // Assume the target temperature has not changed heatersStatus[ heater ].hasTargetTempChanged = FALSE; - F32 currentTargetTemperature = heatersStatus[ heater ].originalTargetTemp; - - // Check if the current target temperature in structure is different from the new requested target temperature - if ( fabs( targetTemperature - currentTargetTemperature ) > NEARLY_ZERO ) + // Check if the requested temperature is within the allowed range + if ( ( targetTemperature >= MINIMUM_TARGET_TEMPERATURE ) && ( targetTemperature <= MAXIMUM_TARGET_TEMPERATURE ) ) { - // Check if the requested temperature is within the allowed range - if ( ( targetTemperature >= MINIMUM_TARGET_TEMPERATURE ) && ( targetTemperature <= MAXIMUM_TARGET_TEMPERATURE ) ) - { - heatersStatus[ heater ].originalTargetTemp = targetTemperature; - heatersStatus[ heater ].hasTargetTempChanged = TRUE; - // TODO alarm if temperature if out of range or just reject? - } + heatersStatus[ heater ].originalTargetTemp = targetTemperature; + heatersStatus[ heater ].hasTargetTempChanged = TRUE; + // TODO alarm if temperature if out of range or just reject? } #endif } @@ -294,13 +292,24 @@ heatersStatus[ heater ].state = handleHeaterStateControlToTarget( heater ); break; + case HEATER_EXEC_STATE_CONTROL_TO_DISINFECT_TARGET: + heatersStatus[ heater ].state = handleHeaterStateControlToDisinfectTarget( heater ); + break; + default: // The heater is in an unknown state. Turn it off and switch to not running state stopHeater( heater ); heatersStatus[ heater ].state = HEATER_EXEC_STATE_OFF; SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DG_SOFTWARE_FAULT, SW_FAULT_ID_HEATERS_INVALID_EXEC_STATE, heater ); break; } + + // Check if the heater is requested to be off + if ( FALSE == heatersStatus[ heater ].isHeaterOn ) + { + setHeaterDutyCycle( heater, HEATERS_MIN_DUTY_CYCLE ); + heatersStatus[ heater ].state = HEATER_EXEC_STATE_OFF; + } } } @@ -461,39 +470,42 @@ dutyCycle = calculatePrimaryHeaterDutyCycle( targetTemperature, inletTemperature, targetFlow ); // Multiply the duty cycle to the heater efficiency dutyCycle *= heaterEfficiency; + state = HEATER_EXEC_STATE_CONTROL_TO_TARGET; } else if ( ( DG_MODE_GENE == getCurrentOperationMode() ) || ( DG_MODE_DRAI == getCurrentOperationMode() ) ) { targetTemperature += DELTA_TEMPERATURE_TIME_COSNTANT_C; // Use target flow rate during Idle and drain targetFlow = getTargetROPumpFlowRate(); dutyCycle = calculatePrimaryHeaterDutyCycle( targetTemperature, inletTemperature, targetFlow ); + state = HEATER_EXEC_STATE_CONTROL_TO_TARGET; } - - setHeaterDutyCycle( heater, dutyCycle ); - state = HEATER_EXEC_STATE_CONTROL_TO_TARGET; - - if ( FALSE == heatersStatus[ heater ].isHeaterOn ) + else if ( ( DG_MODE_HEAT == getCurrentOperationMode() ) || ( DG_MODE_CHEM == getCurrentOperationMode() ) ) { - setHeaterDutyCycle( heater, HEATERS_MIN_DUTY_CYCLE ); - state = HEATER_EXEC_STATE_OFF; + // If the mode is any of the disinfects, especially heat, use the target flow rate instead of the avg. flow + // Most of the times the heater should be running at 100% duty cycle since the target temperature is 81 C + targetFlow = getTargetROPumpFlowRate(); + dutyCycle = calculatePrimaryHeaterDutyCycle( targetTemperature, inletTemperature, targetFlow ); + state = HEATER_EXEC_STATE_CONTROL_TO_DISINFECT_TARGET; } + setHeaterDutyCycle( heater, dutyCycle ); + return state; } /*********************************************************************//** * @brief * The handleHeaterStateControlToTarget function handles the heaters' control - * to target while they have reached to target. + * to target while the heater is targeting to reach to temperature. * @details Inputs: heaterStatus * @details Outputs: heaterStatus * @param heater: The heater Id that its on state is handled * @return next state of the state machine *************************************************************************/ static HEATERS_STATE_T handleHeaterStateControlToTarget( DG_HEATERS_T heater ) { - HEATERS_STATE_T state = HEATER_EXEC_STATE_CONTROL_TO_TARGET; + HEATERS_STATE_T state = HEATER_EXEC_STATE_CONTROL_TO_TARGET; // TODO do we need any control to maintain the temperature? @@ -502,11 +514,45 @@ state = HEATER_EXEC_STATE_RAMP_TO_TARGET; } - // Check if the heater is requested to be off - if ( FALSE == heatersStatus[ heater ].isHeaterOn ) + return state; +} + +/*********************************************************************//** + * @brief + * The handleHeaterStateControlToDisinfectTarget function handles the + * heaters' control to target while the operation mode is heat or chemical + * disinfects. + * @details Inputs: heaterStatus + * @details Outputs: heaterStatus + * @param heater: The heater Id that its on state is handled + * @return next state of the state machine + *************************************************************************/ +static HEATERS_STATE_T handleHeaterStateControlToDisinfectTarget( DG_HEATERS_T heater ) +{ + HEATERS_STATE_T state = HEATER_EXEC_STATE_CONTROL_TO_DISINFECT_TARGET; + + F32 heatDisinfectSensorTemp = getTemperatureValue( TEMPSENSORS_HEAT_DISINFECT ); + + // Check if the heaters control conditions have changed, if yes, switch back to ramp to target + if ( TRUE == haveHeaterControlConditionsChanged( heater ) ) { + state = HEATER_EXEC_STATE_RAMP_TO_TARGET; + } + + // If the heat disifect sensor indicates that the temperature is below target temperature but the target temperature had been reached + // before turn on the heaters with 100% power + if ( ( heatDisinfectSensorTemp <= heatersStatus[ heater ].originalTargetTemp ) && ( TRUE == heatersStatus[ heater ].hasTargetBeenReached ) ) + { + heatersStatus[ heater ].hasTargetBeenReached = FALSE; + setHeaterDutyCycle( heater, HEATERS_MAX_DUTY_CYCLE ); + } + + // If we have reached to target temperature, turn off the heaters + if ( heatDisinfectSensorTemp > heatersStatus[ heater ].originalTargetTemp ) + { + // Set the flag to true for the next run + heatersStatus[ heater ].hasTargetBeenReached = TRUE; setHeaterDutyCycle( heater, HEATERS_MIN_DUTY_CYCLE ); - state = HEATER_EXEC_STATE_OFF; } return state;