Index: firmware/App/Controllers/UVReactors.c =================================================================== diff -u -r9e5ee62245eb2a73b167eabd6c274a71a76a7b0e -r72bca5d2e489fa253f3bdfdb254261a32c7a0c19 --- firmware/App/Controllers/UVReactors.c (.../UVReactors.c) (revision 9e5ee62245eb2a73b167eabd6c274a71a76a7b0e) +++ firmware/App/Controllers/UVReactors.c (.../UVReactors.c) (revision 72bca5d2e489fa253f3bdfdb254261a32c7a0c19) @@ -137,7 +137,8 @@ setReactorEnableStatus( reactor, PIN_SIGNAL_LOW ); } - initPersistentAlarm( ALARM_ID_UV_REACTOR_NOT_HEALTHY, MAX_ALLOWED_UNHEALTHY_REACTOR_PERIOD, MAX_ALLOWED_UNHEALTHY_REACTOR_PERIOD ); + initPersistentAlarm( ALARM_ID_DG_INLET_UV_REACTOR_NOT_HEALTHY, MAX_ALLOWED_UNHEALTHY_REACTOR_PERIOD, MAX_ALLOWED_UNHEALTHY_REACTOR_PERIOD ); + initPersistentAlarm( ALARM_ID_DG_OUTLET_UV_REACTOR_NOT_HEALTHY, MAX_ALLOWED_UNHEALTHY_REACTOR_PERIOD, MAX_ALLOWED_UNHEALTHY_REACTOR_PERIOD ); initPersistentAlarm( ALARM_ID_DG_INLET_UV_REACTOR_ON_WITH_NO_FLOW, UV_REACTORS_ON_NO_FLOW_TIMEOUT_MS, UV_REACTORS_ON_NO_FLOW_TIMEOUT_MS ); initPersistentAlarm( ALARM_ID_DG_OUTLET_UV_REACTOR_ON_WITH_NO_FLOW, UV_REACTORS_ON_NO_FLOW_TIMEOUT_MS, UV_REACTORS_ON_NO_FLOW_TIMEOUT_MS ); } @@ -354,11 +355,11 @@ // Check which reactor has not been healthy and raise an alarm if ( FALSE == isInletHealthy ) { - SET_ALARM_WITH_1_U32_DATA( ALARM_ID_UV_REACTOR_NOT_HEALTHY, INLET_UV_REACTOR ); + activateAlarmNoData( ALARM_ID_DG_INLET_UV_REACTOR_NOT_HEALTHY ); } - else + else if ( FALSE == isOutletHealthy ) { - SET_ALARM_WITH_1_U32_DATA( ALARM_ID_UV_REACTOR_NOT_HEALTHY, OUTLET_UV_REACTOR ); + activateAlarmNoData( ALARM_ID_DG_OUTLET_UV_REACTOR_NOT_HEALTHY ); } } @@ -409,6 +410,7 @@ { UV_REACTOR_STATE_T state = UV_REACTOR_STATE_ON; BOOL isReactorUnhealthy = ( UV_REACTOR_HEALTHY == getUVReactorHealth( reactor ) ? FALSE : TRUE ); + ALARM_ID_T reactorAlarm = ( INLET_UV_REACTOR == reactor ? ALARM_ID_DG_INLET_UV_REACTOR_NOT_HEALTHY : ALARM_ID_DG_OUTLET_UV_REACTOR_NOT_HEALTHY ); // Update the UV reactor's health. It should be either healthy (1) or not healthy (0) reactorsStatus[ reactor ].healthStatus.data = getReactorHealth( reactor ); @@ -417,9 +419,9 @@ if ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_UV_REACTORS ) != SW_CONFIG_ENABLE_VALUE ) #endif { - checkPersistentAlarm( ALARM_ID_UV_REACTOR_NOT_HEALTHY, isReactorUnhealthy, (U32)reactor, MAX_ALLOWED_UNHEALTHY_REACTOR_PERIOD ); + checkPersistentAlarm( reactorAlarm, isReactorUnhealthy, (U32)reactor, MAX_ALLOWED_UNHEALTHY_REACTOR_PERIOD ); - if ( TRUE == isAlarmActive( ALARM_ID_UV_REACTOR_NOT_HEALTHY ) ) + if ( TRUE == isAlarmActive( reactorAlarm ) ) { // The UV reactor is not healthy turn it off and trigger the alarm reactorsStatus[ reactor ].switchState = TURN_OFF; Index: firmware/App/Modes/ModeChemicalDisinfect.c =================================================================== diff -u -r9e5ee62245eb2a73b167eabd6c274a71a76a7b0e -r72bca5d2e489fa253f3bdfdb254261a32c7a0c19 --- firmware/App/Modes/ModeChemicalDisinfect.c (.../ModeChemicalDisinfect.c) (revision 9e5ee62245eb2a73b167eabd6c274a71a76a7b0e) +++ firmware/App/Modes/ModeChemicalDisinfect.c (.../ModeChemicalDisinfect.c) (revision 72bca5d2e489fa253f3bdfdb254261a32c7a0c19) @@ -25,6 +25,7 @@ #include "MessageSupport.h" #include "ModeChemicalDisinfect.h" #include "ModeFault.h" +#include "ModeHeatDisinfect.h" #include "ModeStandby.h" #include "NVDataMgmt.h" #include "OperationModes.h" @@ -178,6 +179,10 @@ static DISINFECT_NV_OPS_T disinfectNVOps; ///< Disinfect non-volatile memory operations. static BOOL haveDrainParamsBeenInit[ NUM_OF_DG_RESERVOIRS ]; ///< Boolean flag to indicate whether the drain parameters have been reset or not. +#ifndef _RELEASE_ +static NELSON_SUPPORT_T nelsonSupport; ///< Nelson support. +#endif + // ********** private function prototypes ********** static DG_CHEM_DISINFECT_STATE_T handleChemicalDisinfectStartState( void ); @@ -207,6 +212,10 @@ static void monitorModeChemicalDisinfect( void ); static void writeDisinfectDataToNV( DG_USAGE_INFO_ITEMS_T info ); +#ifndef _RELEASE_ +static void setNelsonSupportConditions( void ); +#endif + /*********************************************************************//** * @brief * The initChemicalDisinfectMode function initializes the chemical @@ -268,6 +277,12 @@ R2FullVolume = 0.0F; disinfectantMixRatio = 0.0F; +#ifndef _RELEASE_ + nelsonSupport = NELSON_NONE; + + setNelsonSupportConditions(); +#endif + initPersistentAlarm( ALARM_ID_DG_CHEM_DISINFECT_TARGET_TEMP_OUT_OF_RANGE, DISINFECT_TEMP_OUT_OF_RANGE_TIMEOUT_MS, DISINFECT_TEMP_OUT_OF_RANGE_TIMEOUT_MS ); initPersistentAlarm( ALARM_ID_DG_CHEM_DISINFECT_TARGET_COND_OUT_OF_RANGE, DISINFECT_COND_OUT_OF_RANGE_TIMEOUT_MS, DISINFECT_COND_OUT_OF_RANGE_TIMEOUT_MS ); } @@ -289,7 +304,12 @@ setCPLDCleanLEDColor( CPLD_CLEAN_LED_YELLOW ); - activateAlarmNoData( ALARM_ID_DG_CHEM_DISINFECT_INSERT_ACID ); +#ifndef _RELEASE_ + if ( nelsonSupport != NELSON_POS_CONTROL_CHEM_DISINFECT ) +#endif + { + activateAlarmNoData( ALARM_ID_DG_CHEM_DISINFECT_INSERT_ACID ); + } return chemDisinfectState; } @@ -726,7 +746,8 @@ handleDisinfectantMixing( getMeasuredFlowRateLPM( RO_FLOW_SENSOR ) * ML_PER_LITER, disinfectantMixRatio ); #ifndef _RELEASE_ - if ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_DISINFECT_CONDUCTIVITY_CHECK ) != SW_CONFIG_ENABLE_VALUE ) + if ( ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_DISINFECT_CONDUCTIVITY_CHECK ) != SW_CONFIG_ENABLE_VALUE ) || + ( nelsonSupport != NELSON_POS_CONTROL_CHEM_DISINFECT ) ) #endif { if ( cd2Conductivity < MIN_PRIME_ACID_CONDUCTIVITY_US_PER_CM ) @@ -1061,6 +1082,14 @@ chemDisinfectUIState = CHEM_DISINFECT_UI_STATE_FLUSH_AFTER_DISINFECT; stateTimer = getMSTimerCount(); state = DG_CHEM_DISINFECT_STATE_DRAIN_R1; + +#ifndef _RELEASE_ + if ( ( NELSON_POS_CONTROL_CHEM_DISINFECT == nelsonSupport ) || ( NELSON_CHEM_DISINFECT == nelsonSupport ) ) + { + deenergizeActuators( NO_PARK_CONC_PUMPS ); + state = DG_CHEM_DISINFECT_STATE_COMPLETE; + } +#endif } else { @@ -1238,7 +1267,17 @@ chemDisinfectUIState = CHEM_DISINFECT_UI_STATE_COMPLETE; - requestNewOperationMode( DG_MODE_CHFL ); +#ifndef _RELEASE_ + if ( nelsonSupport != NELSON_NONE ) + { + nelsonSupport = NELSON_NONE; + requestNewOperationMode( DG_MODE_STAN ); + } + else +#endif + { + requestNewOperationMode( DG_MODE_CHFL ); + } return state; } @@ -1259,6 +1298,11 @@ { SET_ALARM_WITH_1_U32_DATA( alarmDetectedPendingTrigger, prevChemDisinfectState ) } + +#ifndef _RELEASE_ + nelsonSupport = NELSON_NONE; +#endif + requestNewOperationMode( DG_MODE_FAUL ); } @@ -1558,6 +1602,7 @@ data.overallElapsedTime = calcTimeSince( overallChemDisinfectTimer ); data.stateElapsedTime = calcTimeSince( stateTimer ); data.cancellationMode = (U32)cancellationMode; + data.nelsonSupportMode = (U32)nelsonSupport; //If the mode is in the actual chemical disinfect states, publish the elapsed time, otherwise publish 0 to avoid confusion if ( chemDisinfectState > DG_CHEM_DISINFECT_STATE_FLUSH_DRAIN ) @@ -1569,9 +1614,9 @@ } else { - uiData.chemDisinfectCountdownTime = 0.0; - data.R1FillLevel = 0.0; - data.R2FillLevel = 0.0; + uiData.chemDisinfectCountdownTime = 0.0F; + data.R1FillLevel = 0.0F; + data.R2FillLevel = 0.0F; } data.chemDisinfectUIState = chemDisinfectUIState; @@ -1696,4 +1741,58 @@ } } +// ********** Nelson Support Functions ********** + +#ifndef _RELEASE_ +/*********************************************************************//** + * @brief + * The setNelsonSupportConditions function sets the disinfect variables for + * Nelson support. + * @details Inputs: nelsonSupport + * @details Outputs: chemDisinfectState, flushCircWaitTime, stateTimer + * @return: none + *************************************************************************/ +static void setNelsonSupportConditions( void ) +{ + F32 temperature = 0.0F; + + switch ( nelsonSupport ) + { + case NELSON_POS_CONTROL_CHEM_DISINFECT: + case NELSON_CHEM_DISINFECT: + // The target temperature is set to low so the heater will turn on but it will not heat because + // we are very close to the target. Set the stop temperature to a temperature lower by a couple degrees + // make sure the timer will continuously count against the disinfection time to inoculate. + // NOTE: this is not part of the commercial code so no #defines + temperature = 20.0F; + + // Set the valves to start flush circulation + setValveState( VPI, VALVE_STATE_CLOSED ); + setValveState( VBF, VALVE_STATE_CLOSED ); + setValveState( VPD, VALVE_STATE_OPEN_C_TO_NC ); + setValveState( VDR, VALVE_STATE_DRAIN_C_TO_NO ); + setValveState( VRC, VALVE_STATE_DRAIN_C_TO_NO ); + setValveState( VPO, VALVE_STATE_NOFILL_C_TO_NO ); + setValveState( VRF, VALVE_STATE_R2_C_TO_NO ); + setValveState( VRO, VALVE_STATE_R1_C_TO_NO ); + setValveState( VRI, VALVE_STATE_R1_C_TO_NO ); + setValveState( VRD1, VALVE_STATE_CLOSED ); + setValveState( VRD2, VALVE_STATE_CLOSED ); + setROPumpTargetFlowRateLPM( RO_PUMP_TARGET_FLUSH_FLOW_RATE_LPM, MAX_RO_PUMP_FLUSH_FILL_PRESSURE_PSI ); + setHeaterTargetTemperature( DG_PRIMARY_HEATER, temperature ); + startHeater( DG_PRIMARY_HEATER ); + turnOnUVReactor( INLET_UV_REACTOR ); + turnOnUVReactor( OUTLET_UV_REACTOR ); + flushCircWaitTime = FLUSH_CICRCULATION_INITIAL_WAIT_TIME_MS; + stateTimer = getMSTimerCount(); + chemDisinfectState = DG_CHEM_DISINFECT_STATE_FLUSH_CIRCULATION; + break; + + case NELSON_NONE: + default: + break; + } +} +#endif + /**@}*/ Index: firmware/App/Modes/ModeHeatDisinfect.c =================================================================== diff -u -r1440a4a2be8d12edebd405a20807882e5d32d619 -r72bca5d2e489fa253f3bdfdb254261a32c7a0c19 --- firmware/App/Modes/ModeHeatDisinfect.c (.../ModeHeatDisinfect.c) (revision 1440a4a2be8d12edebd405a20807882e5d32d619) +++ firmware/App/Modes/ModeHeatDisinfect.c (.../ModeHeatDisinfect.c) (revision 72bca5d2e489fa253f3bdfdb254261a32c7a0c19) @@ -92,8 +92,8 @@ #define HEAT_DISINFECT_TARGET_RO_FLOW_TRANSFER_LPM 0.8F ///< Heat disinfect target RO flow rate in L/min when transferring between reservoirs. #define HEAT_DISINFECT_MAX_RO_PRESSURE_PSI 30 ///< Heat disinfect maximum RO pressure in psi. #define HEAT_DISINFECT_START_TEMP_TIMOUT_MS ( 4 * MIN_PER_HOUR * SEC_PER_MIN * MS_PER_SECOND ) ///< Heat disinfect reaching to minimum temperature timeout in milliseconds. -#define RSRVRS_TARGET_VOL_OUT_TIMEOUT_MS ( 0.5F * SEC_PER_MIN * MS_PER_SECOND ) ///< Reservoirs 1 & 2 maximum volume out of range timeout during heat disinfect. TODO change this to 5 seconds -#define RSRVRS_MAX_TARGET_VOL_CHANGE_ML 250.0F // TODO temporary change. Change back to 100 ///< Reservoirs 1 & 2 maximum allowed volume change when full during heat disinfect. +#define RSRVRS_TARGET_VOL_OUT_TIMEOUT_MS ( 5 * MS_PER_SECOND ) ///< Reservoirs 1 & 2 maximum volume out of range timeout during heat disinfect. +#define RSRVRS_MAX_TARGET_VOL_CHANGE_ML 100.0F ///< Reservoirs 1 & 2 maximum allowed volume change when full during heat disinfect. #define POST_HEAT_DISINFECT_WAIT_TIME_MS ( 3 * SEC_PER_MIN * MS_PER_SECOND ) ///< Heat disinfect final wait time before flushing the system in milliseconds. #define HEAT_DISINFECT_MAX_TEMP_GRADIENT_C 15.0F ///< Heat disinfect maximum allowed temperature gradient in between hottest and coldest sensors. #define HEAT_DISINFECT_TEMP_GRAD_OUT_RANGE_TIME_MS ( 0.16 * SEC_PER_MIN * MS_PER_SECOND ) ///< Heat disinfect temperature gradient out of range timeout in milliseconds. @@ -193,6 +193,10 @@ static DISINFECT_NV_OPS_T disinfectNVOps; ///< Disinfect non-volatile memory operations. static HEAT_DISINFECT_TIME_STATUS_T timeStatus[ NUM_OF_HEAT_DISINFECT_TIMES ]; ///< Heat disinfect time status. +#ifndef _RELEASE_ +static NELSON_SUPPORT_T nelsonSupport; ///< Nelson support. +#endif + // ********** private function prototypes ********** static DG_HEAT_DISINFECT_STATE_T handleHeatDisinfectStartState( void ); @@ -224,6 +228,11 @@ static void monitorModeHeatDisinfect( void ); static void writeDisinfectDataToNV( DG_USAGE_INFO_ITEMS_T info ); +#ifndef _RELEASE_ +static void setNelsonSupportConditions( void ); +static DG_HEAT_DISINFECT_STATE_T handleNelsonHeatDisinfectFillR1WithWaterState( void ); +#endif + /*********************************************************************//** * @brief * The initHeatDisinfectMode function initializes the heat disinfect mode @@ -267,6 +276,10 @@ areRsrvrsLeaking = FALSE; dataPublishCounter = 0; +#ifndef _RELEASE_ + nelsonSupport = NELSON_NONE; +#endif + // Initialize the disinfect times timeStatus[ RO_AT_77_C ].startTempC = HEAT_DISINFECT_START_TEMP_AT_77_C; timeStatus[ RO_AT_77_C ].startTimeMS = 0; @@ -291,6 +304,10 @@ timeStatus[ RSRVR_AT_82_C ].stopTempC = HEAT_DISINFECT_STOP_TEMP_AT_81_C; timeStatus[ RSRVR_AT_82_C ].targetTimeMS = HEAT_DISINFECT_AT_82_C_TIME_MS; timeStatus[ RSRVR_AT_82_C ].tempSensor = TEMPSENSORS_INLET_DIALYSATE; + +#ifndef _RELEASE_ + setNelsonSupportConditions(); +#endif } /*********************************************************************//** @@ -414,6 +431,12 @@ heatDisinfectState = handleHeatDisinfectCompleteState(); break; +#ifndef _RELEASE_ + case DG_NELSON_HEAT_DISINFECT_STATE_FILL_R1_WITH_WATER: + heatDisinfectState = handleNelsonHeatDisinfectFillR1WithWaterState(); + break; +#endif + default: SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DG_SOFTWARE_FAULT, SW_FAULT_ID_HEAT_DISINFECT_INVALID_EXEC_STATE, heatDisinfectState ) heatDisinfectState = DG_HEAT_DISINFECT_STATE_START; @@ -452,6 +475,9 @@ // Check if the current operation mode is heat disinfect if ( DG_MODE_HEAT == getCurrentOperationMode() ) { +#ifndef _RELEASE_ + nelsonSupport = NELSON_NONE; +#endif // Reset all the actuators deenergizeActuators( NO_PARK_CONC_PUMPS ); @@ -464,6 +490,22 @@ return status; } +#ifndef _RELEASE_ +/*********************************************************************//** + * @brief + * The setNelsonSupportMode function sets the requested Nelson support + * mode (i.e. inoculate, ...) + * @details Inputs: none + * @details Outputs: nelsonSupport + * @param support the type Nelson support (i.e. inoculate, heat disinfect) + * @return none + *************************************************************************/ +void setNelsonSupportMode( NELSON_SUPPORT_T support ) +{ + nelsonSupport = support; +} +#endif + // ********** private functions ********** /*********************************************************************//** @@ -520,20 +562,17 @@ tareLoadCell( LOAD_CELL_RESERVOIR_1_PRIMARY ); tareLoadCell( LOAD_CELL_RESERVOIR_1_BACKUP ); - // Assume reservoir 2 is full and drain it - rsrvr2Status = DG_RESERVOIR_ABOVE_TARGET; - // Done with draining R1, close it setValveState( VRD1, VALVE_STATE_CLOSED ); // Set the actuators to drain R2. // NOTE: Drain pump is already on and VDr is already on drain state setValveState( VRD2, VALVE_STATE_OPEN ); - state = DG_HEAT_DISINFECT_STATE_DRAIN_R2; - setValveState( VPO, VALVE_STATE_FILL_C_TO_NC); - // Start the timer - stateTimer = getMSTimerCount(); + // Assume reservoir 2 is full and drain it + rsrvr2Status = DG_RESERVOIR_ABOVE_TARGET; + state = DG_HEAT_DISINFECT_STATE_DRAIN_R2; + stateTimer = getMSTimerCount(); } else if ( DG_RESERVOIR_NOT_REACHED_TARGET == rsrvr1Status ) { @@ -570,14 +609,23 @@ signalDrainPumpHardStop(); - // Done with draining R2, close it - turnOnUVReactor( INLET_UV_REACTOR ); - setValveState( VPO, VALVE_STATE_NOFILL_C_TO_NO ); - setValveState( VRD2, VALVE_STATE_CLOSED ); - setValveState( VPI, VALVE_STATE_OPEN ); - stateTrialCounter = 0; - stateTimer = getMSTimerCount(); - state = DG_HEAT_DISINFECT_STATE_FLUSH_DRAIN; +#ifndef _RELEASE_ + if ( NELSON_DRAIN_SAMPLES == nelsonSupport ) + { + state = DG_HEAT_DISINFECT_STATE_COMPLETE; + } + else +#endif + { + // Done with draining R2, close it + turnOnUVReactor( INLET_UV_REACTOR ); + setValveState( VPO, VALVE_STATE_NOFILL_C_TO_NO ); + setValveState( VRD2, VALVE_STATE_CLOSED ); + setValveState( VPI, VALVE_STATE_OPEN ); + stateTrialCounter = 0; + stateTimer = getMSTimerCount(); + state = DG_HEAT_DISINFECT_STATE_FLUSH_DRAIN; + } } else if ( DG_RESERVOIR_NOT_REACHED_TARGET == rsrvr2Status ) { @@ -1226,6 +1274,27 @@ stateTimer = getMSTimerCount(); state = DG_HEAT_DISINFECT_STATE_COOL_DOWN_HEATERS; } +#ifndef _RELEASE_ + if ( NELSON_INOCULATE == nelsonSupport ) + { + // Set the valves to transfer hot water from R1 to R2 and fill up R2. + setValveState( VRO, VALVE_STATE_R1_C_TO_NO ); + setValveState( VRD1, VALVE_STATE_CLOSED ); + setValveState( VRD2, VALVE_STATE_OPEN ); + setValveState( VRI, VALVE_STATE_R2_C_TO_NC ); + setValveState( VRF, VALVE_STATE_R1_C_TO_NC ); + setDrainPumpTargetOutletFlowLPM( HEAT_DISINFECT_TARGET_RO_FLOW_TRANSFER_LPM ); + + // Although there is fluid in both reservoirs, but they are set to empty + // to begin the transition of hot water from R1 to R2. + rsrvr2Status = DG_RESERVOIR_BELOW_TARGET; + rsrvr1Status = DG_RESERVOIR_BELOW_TARGET; + stateTimer = getMSTimerCount(); + rsrvr1RefVolML = 0.0F; + rsrvr2RefVolML = 0.0F; + state = DG_NELSON_HEAT_DISINFECT_STATE_FILL_R1_WITH_WATER; + } +#endif break; case HEAT_DISINFECT_HEAT_UP_IN_PROGRESS: @@ -1512,7 +1581,18 @@ heatDisinfectUIState = HEAT_DISINFECT_UI_STATE_COMPLETE; - requestNewOperationMode( DG_MODE_HCOL ); +#ifndef _RELEASE_ + if ( nelsonSupport != NELSON_NONE ) + { + // Clear the variable to be out of Nelson support + nelsonSupport = NELSON_NONE; + requestNewOperationMode( DG_MODE_STAN ); + } + else +#endif + { + requestNewOperationMode( DG_MODE_HCOL ); + } return state; } @@ -1533,7 +1613,19 @@ { SET_ALARM_WITH_1_U32_DATA( alarmDetectedPendingTrigger, prevHeatDisinfectState ) } - requestNewOperationMode( DG_MODE_FAUL ); + +#ifndef _RELEASE_ + if ( nelsonSupport != NELSON_NONE ) + { + // Clear the variable to be out of Nelson support + nelsonSupport = NELSON_NONE; + requestNewOperationMode( DG_MODE_STAN ); + } + else +#endif + { + requestNewOperationMode( DG_MODE_FAUL ); + } } /*********************************************************************//** @@ -1853,6 +1945,7 @@ uiData.r82CountdownTimeS = ( 0 == timeStatus[ RSRVR_AT_82_C ].startTimeMS ? 0 : ( timeStatus[ RSRVR_AT_82_C ].targetTimeMS - calcTimeSince( timeStatus[ RSRVR_AT_82_C ].startTimeMS ) ) / 1000 ); data.R1FillLevel = rsrvr1RefVolML; data.R2FillLevel = rsrvr2RefVolML; + data.nelsonSupportMode = (U32)nelsonSupport; broadcastData( MSG_ID_DG_HEAT_DISINFECT_DATA, COMM_BUFFER_OUT_CAN_DG_BROADCAST, (U08*)&data, sizeof( MODE_HEAT_DISINFECT_DATA_T ) ); broadcastData( MSG_ID_DG_HEAT_DISINFECT_TIME_DATA, COMM_BUFFER_OUT_CAN_DG_2_UI, (U08*)&uiData, sizeof( MODE_HEAT_DISINFECT_UI_DATA_T ) ); @@ -1913,4 +2006,127 @@ } } +// ********** Nelson Support Functions ********** + +#ifndef _RELEASE_ +/*********************************************************************//** + * @brief + * The setNelsonSupportConditions function sets the disinfect variables for + * Nelson support. + * @details Inputs: nelsonSupport + * @details Outputs: timeStatus, heatDisinfectState + * @return: none + *************************************************************************/ +static void setNelsonSupportConditions( void ) +{ + F32 temperature = 0.0F; + F32 stopTemperature = 0.0F; + U32 disinfectTime = 0; + + switch ( nelsonSupport ) + { + case NELSON_INOCULATE: + // The target temperature is set to low so the heater will turn on but it will not heat because + // we are very close to the target. Set the stop temperature to a temperature lower by a couple degrees + // make sure the timer will continuously count against the disinfection time to inoculate. + // NOTE: this is not part of the commercial code so no #defines + temperature = 20.0F; + stopTemperature = temperature - 3.0F; + disinfectTime = 2 * MIN_PER_HOUR * SEC_PER_MIN * MS_PER_SECOND; + heatDisinfectState = DG_HEAT_DISINFECT_STATE_START; + + timeStatus[ RO_AT_77_C ].startTempC = temperature; + timeStatus[ RO_AT_77_C ].startTimeMS = 0; + timeStatus[ RO_AT_77_C ].stopTempC = stopTemperature; + timeStatus[ RO_AT_77_C ].targetTimeMS = HEAT_DISINFECT_AT_77_C_TIME_MS; + + timeStatus[ RO_AT_82_C ].startTempC = temperature; + timeStatus[ RO_AT_82_C ].startTimeMS = 0; + timeStatus[ RO_AT_82_C ].stopTempC = stopTemperature; + timeStatus[ RO_AT_82_C ].targetTimeMS = HEAT_DISINFECT_AT_82_C_TIME_MS; + + timeStatus[ RSRVR_AT_77_C ].startTempC = temperature; + timeStatus[ RSRVR_AT_77_C ].startTimeMS = 0; + timeStatus[ RSRVR_AT_77_C ].stopTempC = stopTemperature; + timeStatus[ RSRVR_AT_77_C ].targetTimeMS = disinfectTime; + + timeStatus[ RSRVR_AT_82_C ].startTempC = temperature; + timeStatus[ RSRVR_AT_82_C ].startTimeMS = 0; + timeStatus[ RSRVR_AT_82_C ].stopTempC = stopTemperature; + timeStatus[ RSRVR_AT_82_C ].targetTimeMS = disinfectTime; + break; + + case NELSON_HEAT_DISINFECT: + // Set the valves to drain R2 and no fill + setValveState( VPI, VALVE_STATE_CLOSED ); + setValveState( VBF, VALVE_STATE_OPEN ); + setValveState( VPD, VALVE_STATE_DRAIN_C_TO_NO ); + setValveState( VDR, VALVE_STATE_RECIRC_C_TO_NC ); + setValveState( VRC, VALVE_STATE_RECIRC_C_TO_NC ); + setValveState( VPO, VALVE_STATE_FILL_C_TO_NC ); + setValveState( VRF, VALVE_STATE_R1_C_TO_NC ); + setValveState( VRO, VALVE_STATE_R1_C_TO_NO ); + setValveState( VRI, VALVE_STATE_R2_C_TO_NC ); + setValveState( VRD1, VALVE_STATE_CLOSED ); + setValveState( VRD2, VALVE_STATE_OPEN ); + signalROPumpHardStop(); + setDrainPumpTargetOutletFlowLPM( HEAT_DISINFECT_TARGET_RO_FLOW_LPM ); + setHeaterTargetTemperature( DG_PRIMARY_HEATER, HEAT_DISINFECT_PRIM_HEATER_TARGET_TEMP_C ); + startHeater( DG_PRIMARY_HEATER ); + heatDisinfectState = DG_HEAT_DISINFECT_STATE_DISINFECT_R1_TO_R2; + break; + + case NELSON_DRAIN_SAMPLES: + heatDisinfectState = DG_HEAT_DISINFECT_STATE_START; + break; + + case NELSON_NONE: + default: + break; + } +} + +/*********************************************************************//** + * @brief + * The handleNelsonHeatDisinfectFillR1WithWaterState function handles the Nelson + * fill reservoir 1 with water. + * @details Inputs: rsrvr1Status, rsrvr2Status + * @details Outputs: rsrvr1Status, rsrvr2Status, prevHeatDisinfectState + * @return next state of the heat disinfect state machine + *************************************************************************/ +static DG_HEAT_DISINFECT_STATE_T handleNelsonHeatDisinfectFillR1WithWaterState( void ) +{ + DG_HEAT_DISINFECT_STATE_T state = DG_NELSON_HEAT_DISINFECT_STATE_FILL_R1_WITH_WATER; + + // First reservoir 2 must be partially full + if ( DG_RESERVOIR_BELOW_TARGET == rsrvr2Status ) + { + rsrvr2Status = getRsrvrFillStatus( DG_RESERVOIR_2, RSRVRS_PARTIAL_FILL_VOL_ML, RSRVRS_500ML_FILL_UP_TIMEOUT_MS ); + } + else if ( DG_RESERVOIR_REACHED_TARGET == rsrvr2Status ) + { + rsrvr1Status = getRsrvrFillStatus( DG_RESERVOIR_1, RSRVRS_FULL_VOL_ML, RSRVRS_FILL_UP_TIMEOUT_MS ); + + if ( DG_RESERVOIR_REACHED_TARGET == rsrvr1Status ) + { + deenergizeActuators( PARK_CONC_PUMPS ); + state = DG_HEAT_DISINFECT_STATE_COMPLETE; + } + else if ( DG_RESERVOIR_NOT_REACHED_TARGET == rsrvr1Status ) + { + prevHeatDisinfectState = state; + state = DG_HEAT_DISINFECT_STATE_CANCEL_WATER_PATH; + } + } + else if ( DG_RESERVOIR_NOT_REACHED_TARGET == rsrvr2Status ) + { + prevHeatDisinfectState = state; + state = DG_HEAT_DISINFECT_STATE_CANCEL_WATER_PATH; + } + + return state; +} + +#endif + /**@}*/ Index: firmware/App/Modes/ModeHeatDisinfect.h =================================================================== diff -u -r1440a4a2be8d12edebd405a20807882e5d32d619 -r72bca5d2e489fa253f3bdfdb254261a32c7a0c19 --- firmware/App/Modes/ModeHeatDisinfect.h (.../ModeHeatDisinfect.h) (revision 1440a4a2be8d12edebd405a20807882e5d32d619) +++ firmware/App/Modes/ModeHeatDisinfect.h (.../ModeHeatDisinfect.h) (revision 72bca5d2e489fa253f3bdfdb254261a32c7a0c19) @@ -36,21 +36,38 @@ { U32 heatDisinfectTargetTime; ///< Target time to heat disinfect. U32 ro77CountdownTimeS; ///< Heat disinfect RO 77 count down time in seconds. - U32 ro82CountdownTimeS; ///< - U32 r77CountdownTimeS; - U32 r82CountdownTimeS; + U32 ro82CountdownTimeS; ///< Heat disinfect RO 82 count down time in seconds. + U32 r77CountdownTimeS; ///< Heat disinfect reservoir 77 count down time in seconds. + U32 r82CountdownTimeS; ///< Heat disinfect reservoir 82 count down time in seconds. } MODE_HEAT_DISINFECT_UI_DATA_T; +#ifndef _RELEASE_ +typedef enum Nelson_States +{ + NELSON_NONE = 0, ///< Nelson none. + NELSON_INOCULATE, ///< Nelson inoculate. + NELSON_HEAT_DISINFECT, ///< Nelson heat disinfect. + NELSON_POS_CONTROL_CHEM_DISINFECT, ///< Nelson positive control chemical disinfect. + NELSON_CHEM_DISINFECT, ///< Nelson chemical disinfect. + NELSON_DRAIN_SAMPLES, ///< Nelson drain sample. + NUM_OF_NELSON_SUPPORT ///< Number of Nelson supports. +} NELSON_SUPPORT_T; +#endif + // ********** public function prototypes ********** void initHeatDisinfectMode( void ); // Initialize this module -U32 transitionToHeatDisinfectMode( void ); // Prepares for transition to heat disinfect mode +U32 transitionToHeatDisinfectMode( void ); // Prepares for transition to heat disinfect mode U32 execHeatDisinfectMode( void ); // Execute the heat disinfect mode state machine (call from OperationModes) DG_HEAT_DISINFECT_STATE_T getCurrentHeatDisinfectState( void ); // get the current state of the heat disinfect mode BOOL stopDGHeatDisinfect( void ); // Stop DG heat disinfect +#ifndef _RELEASE_ +void setNelsonSupportMode( NELSON_SUPPORT_T support ); +#endif + /**@}*/ #endif Index: firmware/App/Services/SystemComm.c =================================================================== diff -u -rb8f298547eb578000b3ff3cf55732fda7a689ce0 -r72bca5d2e489fa253f3bdfdb254261a32c7a0c19 --- firmware/App/Services/SystemComm.c (.../SystemComm.c) (revision b8f298547eb578000b3ff3cf55732fda7a689ce0) +++ firmware/App/Services/SystemComm.c (.../SystemComm.c) (revision 72bca5d2e489fa253f3bdfdb254261a32c7a0c19) @@ -1268,6 +1268,12 @@ handleTestDGHeatersDutyCycleOverrideRequest( message ); break; +#ifndef _RELEASE_ + case MSG_ID_DG_NELSON_DISINFECT_SUPPORT: + handleTestDGNelsonDisinfectSupport( message ); + break; +#endif + default: // TODO - unrecognized message ID received - ignore break; Index: firmware/App/Services/SystemCommMessages.c =================================================================== diff -u -rb8f298547eb578000b3ff3cf55732fda7a689ce0 -r72bca5d2e489fa253f3bdfdb254261a32c7a0c19 --- firmware/App/Services/SystemCommMessages.c (.../SystemCommMessages.c) (revision b8f298547eb578000b3ff3cf55732fda7a689ce0) +++ firmware/App/Services/SystemCommMessages.c (.../SystemCommMessages.c) (revision 72bca5d2e489fa253f3bdfdb254261a32c7a0c19) @@ -4312,4 +4312,60 @@ sendTestAckResponseMsg( (MSG_ID_T)message->hdr.msgID, result ); } +#ifndef _RELEASE_ +/*********************************************************************//** + * @brief + * The handleTestDGNelsonDisinfectSupport function handles a request + * to set the Nelson disinfect support mode. + * @details Inputs: none + * @details Outputs: message handled + * @param message a pointer to the message to handle + * @return none + *************************************************************************/ +void handleTestDGNelsonDisinfectSupport( MESSAGE_T *message ) +{ + TEST_OVERRIDE_PAYLOAD_T payload; + BOOL result = FALSE; + + // verify payload length + if ( sizeof( TEST_OVERRIDE_PAYLOAD_T ) == message->hdr.payloadLen ) + { + memcpy( &payload, message->payload, sizeof( TEST_OVERRIDE_PAYLOAD_T ) ); + + NELSON_SUPPORT_T nelson = (NELSON_SUPPORT_T)payload.state.u32; + + switch( nelson ) + { + case NELSON_INOCULATE: + setNelsonSupportMode( nelson ); + requestNewOperationMode( DG_MODE_HEAT ); + break; + + case NELSON_HEAT_DISINFECT: + setNelsonSupportMode( nelson ); + requestNewOperationMode( DG_MODE_HEAT ); + break; + + case NELSON_POS_CONTROL_CHEM_DISINFECT: + setNelsonSupportMode( nelson ); + requestNewOperationMode( DG_MODE_CHEM ); + break; + + case NELSON_CHEM_DISINFECT: + setNelsonSupportMode( nelson ); + requestNewOperationMode( DG_MODE_CHEM ); + break; + + case NELSON_DRAIN_SAMPLES: + setNelsonSupportMode( nelson ); + requestNewOperationMode( DG_MODE_HEAT ); + break; + } + } + + // respond to request + sendTestAckResponseMsg( (MSG_ID_T)message->hdr.msgID, result ); +} +#endif + /**@}*/ Index: firmware/App/Services/SystemCommMessages.h =================================================================== diff -u -rb8f298547eb578000b3ff3cf55732fda7a689ce0 -r72bca5d2e489fa253f3bdfdb254261a32c7a0c19 --- firmware/App/Services/SystemCommMessages.h (.../SystemCommMessages.h) (revision b8f298547eb578000b3ff3cf55732fda7a689ce0) +++ firmware/App/Services/SystemCommMessages.h (.../SystemCommMessages.h) (revision 72bca5d2e489fa253f3bdfdb254261a32c7a0c19) @@ -451,6 +451,11 @@ // MSG_ID_DG_HEATERS_DUTY_CYCLE_OVERRIDE void handleTestDGHeatersDutyCycleOverrideRequest( MESSAGE_T *message ); +#ifndef _RELEASE_ +// MSG_ID_DG_NELSON_DISINFECT_SUPPORT +void handleTestDGNelsonDisinfectSupport( MESSAGE_T *message ); +#endif + /**@}*/ #endif