Index: firmware/.launches/DG.launch =================================================================== diff -u -rfeb93744f73bc0a3d58841bb02bd05c38357f35d -r5d8530d242d8065178eab9e3e5d8e4561b790e01 --- firmware/.launches/DG.launch (.../DG.launch) (revision feb93744f73bc0a3d58841bb02bd05c38357f35d) +++ firmware/.launches/DG.launch (.../DG.launch) (revision 5d8530d242d8065178eab9e3e5d8e4561b790e01) @@ -1,13 +1,17 @@ + + + + Index: firmware/App/Controllers/DrainPump.c =================================================================== diff -u -rccf1219089b835ab2f9d401c0be0d2000be9010a -r5d8530d242d8065178eab9e3e5d8e4561b790e01 --- firmware/App/Controllers/DrainPump.c (.../DrainPump.c) (revision ccf1219089b835ab2f9d401c0be0d2000be9010a) +++ firmware/App/Controllers/DrainPump.c (.../DrainPump.c) (revision 5d8530d242d8065178eab9e3e5d8e4561b790e01) @@ -252,10 +252,11 @@ // Convert speed ADC to RPM currentDrainPumpRPM = CONVERSION_COEFF / getFPGADrainPumpSpeed(); + // TODO commented out to correct the RPM conversion prior to monitoring the RPM // The RPM is only checked in open loop state that the pump is run at a fixed RPM. // The persistent alarm waits for a couple of seconds before raising an alarm, this is supposed to cover // when the pump is turned on and it takes a while to ramp up to target RPM. - if( drainPumpControlModeSet == PUMP_CONTROL_MODE_OPEN_LOOP ) + /*if( drainPumpControlModeSet == PUMP_CONTROL_MODE_OPEN_LOOP ) { U32 targetRPM = getTargetDrainPumpRPM(); F32 threshold = OPEN_LOOP_RPM_OUT_OF_RANGE * targetRPM; @@ -278,7 +279,7 @@ { activateSafetyShutdown(); } - } + }*/ // Publish drain pump data on interval publishDrainPumpData(); Index: firmware/App/Controllers/TemperatureSensors.c =================================================================== diff -u -rccf1219089b835ab2f9d401c0be0d2000be9010a -r5d8530d242d8065178eab9e3e5d8e4561b790e01 --- firmware/App/Controllers/TemperatureSensors.c (.../TemperatureSensors.c) (revision ccf1219089b835ab2f9d401c0be0d2000be9010a) +++ firmware/App/Controllers/TemperatureSensors.c (.../TemperatureSensors.c) (revision 5d8530d242d8065178eab9e3e5d8e4561b790e01) @@ -32,11 +32,11 @@ // ********** private definitions ********** -#define PRIMARY_HEATER_EXT_TEMP_SENSORS_GAIN 16U ///< Primary heater external temperature sensors gain. +#define PRIMARY_HEATER_EXT_TEMP_SENSORS_GAIN 8U ///< Primary heater external temperature sensors gain. #define PRIMARY_HEATER_EXT_TEMP_SENSORS_REF_RESISTANCE 19600U ///< Primary heater external temperature sensors reference resistance. #define PRIMARY_HEATER_EXT_TEMP_SENSORS_0_DEGREE_RESISTANCE 1000U ///< Primary heater external temperature sensors zero degree resistance. -#define COND_SENSORS_TEMP_SENSOR_GAIN 16U ///< Temperature sensor for conductivity gain. +#define COND_SENSORS_TEMP_SENSOR_GAIN 8U ///< Temperature sensor for conductivity gain. #define COND_SENSORS_TEMP_SENSOR_REF_RESISTANCE 19600U ///< Temperature sensor for conductivity reference resistance. #define COND_SENSORS_TEMP_SENSOR_0_DEGREE_RESISTANCE 1000U ///< Temperature sensor for conductivity zero degree resistance. Index: firmware/App/Modes/ModeFlush.c =================================================================== diff -u -r4d7d40a27130dc813d653f044cbb856b1b7d8481 -r5d8530d242d8065178eab9e3e5d8e4561b790e01 --- firmware/App/Modes/ModeFlush.c (.../ModeFlush.c) (revision 4d7d40a27130dc813d653f044cbb856b1b7d8481) +++ firmware/App/Modes/ModeFlush.c (.../ModeFlush.c) (revision 5d8530d242d8065178eab9e3e5d8e4561b790e01) @@ -15,9 +15,21 @@ * ***************************************************************************/ +#include "ConductivitySensors.h" +#include "DrainPump.h" +#include "Heaters.h" +#include "LoadCell.h" #include "ModeFlush.h" #include "OperationModes.h" #include "Pressures.h" +#include "Reservoirs.h" +#include "ROPump.h" +#include "SystemCommMessages.h" +#include "TaskGeneral.h" +#include "TemperatureSensors.h" +#include "Timers.h" +#include "UVReactors.h" +#include "Valves.h" /** * @addtogroup DGFlushMode @@ -26,12 +38,74 @@ // ********** private definitions ********** +// General defines +#define FLUSH_DATA_PUB_INTERVAL ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ) ///< Mode flush data publish interval in counts. +#define RO_PUMP_TARGET_FLOW_RATE_LPM 0.8 ///< RO pump target flow rate during flush/fill in L/min. TODO original flow was 0.8 +#define RO_PUMP_MAX_PRESSURE_PSI 130 ///< Maximum RO pump pressure during flush/fill states in psi. +#define DRAIN_PUMP_TARGET_RPM 1800 ///< Drain pump target RPM during drain. + +// Start state defines + + +// Drain R1 & R2 states defines +#define RSRVRS_DRAIN_TIME_OUT_MS ( 2 * 60 * MS_PER_SECOND ) ///< Reservoirs 1 & 2 drain time out in milliseconds. +#define DRAIN_WEIGHT_UNCHANGE_TIMEOUT ( 6 * MS_PER_SECOND ) ///< Time period of unchanged weight during draining before timeout. + +// Flush drain path state defines +#define FLUSH_DRAIN_WAIT_TIME_MS ( 1 * 60 * MS_PER_SECOND ) ///< Flush Drain path wait time in milliseconds. TODo original time is 2 minutes +#define MIN_INLET_TEMPERATURE_C 15.0 ///< Minimum water inlet temperature in C. TODO original temperature was 25 C +#define MIN_INLET_CONDUCTIVITY_US_PER_CM 0.0 ///< Minimum water inlet conductivity in uS/cm +#define MAX_INLET_CONDUCTIVITY_US_PER_CM 2000.0 ///< Maximum water inlet conductivity in us/cm + +// Flush dialysate state defines +#define FLUSH_DIALYSATE_WAIT_TIME_MS ( 0.5 * 60 * MS_PER_SECOND ) ///< Flush dialysate wait time in milliseconds. + +// Flush concentrate straws state defines +#define FLUSH_CONCENTRATE_STRAWS_TIME_MS ( 0.5 * 60 * MS_PER_SECOND ) ///< Flush concentrate straws wait time in milliseconds. TODO original time is 3 minutes + +// Flush and drain R1 and R2 +#define RSRVRS_FULL_VOL_ML 1750.0 ///< Reservoirs 1 & 2 full volume in mL. TODo original value was 1900 +#define RSRVRS_PARTIAL_FILL_VOL_ML 500.0 ///< Reservoirs 1 & 2 partial volume in mL. +#define RSRVRS_FULL_STABLE_TIME_COUNT ( ( 4 * MS_PER_SECOND ) / TASK_GENERAL_INTERVAL ) ///< Reservoirs 1 & 2 full stable time in counts. +#define RSRVRS_FILL_UP_TIMEOUT_MS ( 5 * 60 * MS_PER_SECOND ) ///< Reservoirs 1 & 2 full fill up timeout in ms. TODO original value was 5 mins +#define RSRVRS_PARTIAL_FILL_TIMEOUT_MS ( 2 * 60 * MS_PER_SECOND ) ///< Reservoirs 1 & 2 partial fill up timeout in ms. +#define RSRVRS_DRAIN_TIMEOUT_MS ( 2 * 60 * MS_PER_SECOND ) ///< Reservoirs 1 & 2 drain timeout in ms. + + // ********** private data ********** static DG_FLUSH_STATE_T flushState = DG_FLUSH_STATE_START; ///< Currently active flush state. +static DG_FLUSH_STATE_T prevFlushState = DG_FLUSH_STATE_START; +static U32 rsrvrFillStableTimeCounter = 0; ///< Reservoirs fill stable time counter. +static U32 overallFlushElapsedTime = 0; +static U32 stateTimer = 0; +static ALARM_ID_T alarm; +static DG_RESERVOIR_STATUS_T rsrvr1Status = NUM_OF_DG_RESERVOIR_STATUS; ///< Reservoir 1 status. +static DG_RESERVOIR_STATUS_T rsrvr2Status = NUM_OF_DG_RESERVOIR_STATUS; ///< Reservoir 2 status. +static BOOL isThisInitialDrain = TRUE; +static U32 dataPublishCounter = 0; ///< Flush data publish counter. // ********** private function prototypes ********** +static DG_FLUSH_STATE_T handleFlushModeStartState( void ); +static DG_FLUSH_STATE_T handleFlushModeDrainR1State( void ); +static DG_FLUSH_STATE_T handleFlushModeDrainR2State( void ); +static DG_FLUSH_STATE_T handleFlushModeFlushDrainState( void ); +static DG_FLUSH_STATE_T handleFlushModeFlushDialysateState( void ); +static DG_FLUSH_STATE_T handleFlushModeFlushConcentrateStrawsState( void ); +static DG_FLUSH_STATE_T handleFlushModeFlushR1ToR2State( void ); +static DG_FLUSH_STATE_T handleFlushModeFlushR2AndDrainR1State( void ); +static DG_FLUSH_STATE_T handleFlushModeFlushCirculationState( void ); +static DG_FLUSH_STATE_T handleFlushModeCancelBasicPathState( void ); +static DG_FLUSH_STATE_T handleFlushModeCancelWaterPathState( void ); +static DG_FLUSH_STATE_T handleFlushModeComplete( void ); + +static void resetActuators( void ); +static void setModeToFailed( void ); +static DG_RESERVOIR_STATUS_T getRsrvrFillStatus( DG_RESERVOIR_ID_T r, F32 targetVol, U32 timeout ); +static DG_RESERVOIR_STATUS_T getRsrvrDrainStatus( DG_RESERVOIR_ID_T r, U32 drainSteadyStateTimeout, U32 timeout ); +static void publishFlushData( void ); + /*********************************************************************//** * @brief * The initFlushMode function initializes flush mode module. @@ -42,6 +116,7 @@ void initFlushMode( void ) { flushState = DG_FLUSH_STATE_START; + isThisInitialDrain = TRUE; } /*********************************************************************//** @@ -65,26 +140,74 @@ *************************************************************************/ U32 execFlushMode( void ) { - checkInletPressureFault(); + //checkInletPressureFault(); TODO why do we need this? - // execute current flush state + // Execute current flush state switch ( flushState ) { case DG_FLUSH_STATE_START: + flushState = handleFlushModeStartState(); break; + case DG_FLUSH_STATE_DRAIN_R1: + flushState = handleFlushModeDrainR1State(); + break; + + case DG_FLUSH_STATE_DRAIN_R2: + flushState = handleFlushModeDrainR2State(); + break; + + case DG_FLUSH_STATE_FLUSH_DRAIN: + flushState = handleFlushModeFlushDrainState(); + break; + + case DG_FLUSH_STATE_FLUSH_DIALYSATE: + flushState = handleFlushModeFlushDialysateState(); + break; + + case DG_FLUSH_STATE_FLUSH_CONCENTRATE_STRAWS: + flushState = handleFlushModeFlushConcentrateStrawsState(); + break; + + case DG_FLUSH_STATE_FLUSH_R1_TO_R2: + flushState = handleFlushModeFlushR1ToR2State(); + break; + + case DG_FLUSH_STATE_FLUSH_R2_AND_DRAIN_R1: + flushState = handleFlushModeFlushR2AndDrainR1State(); + break; + + case DG_FLUSH_STATE_FLUSH_CIRCULATION: + flushState = handleFlushModeFlushCirculationState(); + break; + + case DG_FLUSH_STATE_CANCEL_BASIC_PATH: + flushState = handleFlushModeCancelBasicPathState(); + break; + + case DG_FLUSH_STATE_CANCEL_WATER_PATH: + flushState = handleFlushModeCancelWaterPathState(); + break; + + case DG_FLUSH_STATE_COMPLETE: + flushState = handleFlushModeComplete(); + break; + default: - // TODO - s/w fault + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DG_SOFTWARE_FAULT, SW_FAULT_ID_DG_FLUSH_INVALID_EXEC_STATE, flushState ) flushState = DG_FLUSH_STATE_START; break; } + publishFlushData(); + return flushState; } /*********************************************************************//** * @brief - * The getCurrentFlushState function returns the current state of the flush mode. + * The getCurrentFlushState function returns the current state of the flush + * mode. * @details Inputs: flushState * @details Outputs: none * @return current state of flush mode. @@ -94,4 +217,403 @@ return flushState; } +/*********************************************************************//** + * @brief + * The stopDGFlush function stops flush mode. + * @details Inputs: none + * @details Outputs: none + * @return none + *************************************************************************/ +void stopDGFlush( void ) +{ + // Reset all the actuators + resetActuators(); + + // Transition to mode standby + requestNewOperationMode( DG_MODE_STAN ); +} + +// ********** private functions ********** + +static DG_FLUSH_STATE_T handleFlushModeStartState( void ) +{ + DG_FLUSH_STATE_T state = DG_FLUSH_STATE_START; + + //TODO make sure the conductivities are in range + + // Start overall flush timer + overallFlushElapsedTime = getMSTimerCount(); + + // Set all the actuators to reset and de-energized state + resetActuators(); + + if ( FALSE ) //TODO figure out the conductivity and pressure check + { + state = DG_FLUSH_STATE_CANCEL_BASIC_PATH; + } + else + { + // Reset the load cells lowest weight prior to starting the run + resetReservoirsLowestWeight(); + + // Close VPi to prevent wasting water + setValveState( VPI, VALVE_STATE_CLOSED ); + + // Request a tare for reservoir 1 + tareReservoir(); + + // Set the actuators to drain R1 + setValveState( VRD, VALVE_STATE_R1_C_TO_NC ); + setDrainPumpTargetRPM( DRAIN_PUMP_TARGET_RPM ); + + stateTimer = getMSTimerCount(); + rsrvr1Status = DG_RESERVOIR_ABOVE_TARGET; + state = DG_FLUSH_STATE_DRAIN_R1; + } + + return state; +} + +static DG_FLUSH_STATE_T handleFlushModeDrainR1State( void ) +{ + DG_FLUSH_STATE_T state = DG_FLUSH_STATE_DRAIN_R1; + + if ( rsrvr1Status == DG_RESERVOIR_ABOVE_TARGET ) + { + rsrvr1Status = getRsrvrDrainStatus( DG_RESERVOIR_1, DRAIN_WEIGHT_UNCHANGE_TIMEOUT, RSRVRS_DRAIN_TIME_OUT_MS ); + } + else if ( rsrvr1Status == DG_RESERVOIR_REACHED_TARGET ) + { + // Request a tare for reservoir 2 + tareReservoir(); + + // Set the actuators to drain R2 + // NOTE: Drain pump is already on and VDr is already on drain state + setValveState( VRD, VALVE_STATE_R2_C_TO_NO ); + + stateTimer = getMSTimerCount(); + rsrvr2Status = DG_RESERVOIR_ABOVE_TARGET; + state = DG_FLUSH_STATE_DRAIN_R2; + } + else if ( rsrvr1Status == DG_RESERVOIR_NOT_REACHED_TARGET ) + { + state = DG_FLUSH_STATE_CANCEL_BASIC_PATH; + } + + return state; +} + +static DG_FLUSH_STATE_T handleFlushModeDrainR2State( void ) +{ + DG_FLUSH_STATE_T state = DG_FLUSH_STATE_DRAIN_R2; + + if ( rsrvr2Status == DG_RESERVOIR_ABOVE_TARGET ) + { + rsrvr2Status = getRsrvrDrainStatus( DG_RESERVOIR_2, DRAIN_WEIGHT_UNCHANGE_TIMEOUT, RSRVRS_DRAIN_TIME_OUT_MS ); + } + else if ( rsrvr2Status == DG_RESERVOIR_REACHED_TARGET ) + { + signalDrainPumpHardStop(); + + // Set the actuators to flush drain + setValveState( VPI, VALVE_STATE_OPEN ); + setValveState( VPD, VALVE_STATE_DRAIN_C_TO_NC ); + + stateTimer = getMSTimerCount(); + + state = DG_FLUSH_STATE_FLUSH_DRAIN; + } + else if ( rsrvr2Status == DG_RESERVOIR_NOT_REACHED_TARGET ) + { + state = DG_FLUSH_STATE_CANCEL_BASIC_PATH; + } + + return state; +} + +static DG_FLUSH_STATE_T handleFlushModeFlushDrainState( void ) +{ + DG_FLUSH_STATE_T state = DG_FLUSH_STATE_FLUSH_DRAIN; + + if ( didTimeout( stateTimer, FLUSH_DRAIN_WAIT_TIME_MS ) ) + { + setValveState( VPD, VALVE_STATE_OPEN_C_TO_NO ); + setROPumpTargetFlowRate( RO_PUMP_TARGET_FLOW_RATE_LPM, RO_PUMP_MAX_PRESSURE_PSI ); + + // Turn on the UV reactors + turnOnUVReactor( INLET_UV_REACTOR ); + turnOnUVReactor( OUTLET_UV_REACTOR ); + + stateTimer = getMSTimerCount(); + + state = DG_FLUSH_STATE_FLUSH_DIALYSATE; + } + + return state; +} + +static DG_FLUSH_STATE_T handleFlushModeFlushDialysateState( void ) +{ + DG_FLUSH_STATE_T state = DG_FLUSH_STATE_FLUSH_DIALYSATE; + + if ( didTimeout( stateTimer, FLUSH_DIALYSATE_WAIT_TIME_MS ) ) + { + // TODO turn on the concentrate pumps + stateTimer = getMSTimerCount(); + + state = DG_FLUSH_STATE_FLUSH_CONCENTRATE_STRAWS; + } + + return state; +} +static DG_FLUSH_STATE_T handleFlushModeFlushConcentrateStrawsState( void ) +{ + DG_FLUSH_STATE_T state = DG_FLUSH_STATE_FLUSH_CONCENTRATE_STRAWS; + + if ( didTimeout( stateTimer, FLUSH_CONCENTRATE_STRAWS_TIME_MS ) ) + { + // TODO turn off the concentrate pumps + setValveState( VPO, VALVE_STATE_FILL_C_TO_NC ); + setValveState( VRF, VALVE_STATE_R1_C_TO_NC ); + setValveState( VRI, VALVE_STATE_R2_C_TO_NC ); + stateTimer = getMSTimerCount(); + + rsrvr1Status = DG_RESERVOIR_BELOW_TARGET; + rsrvr2Status = DG_RESERVOIR_BELOW_TARGET; + state = DG_FLUSH_STATE_FLUSH_R1_TO_R2; + } + + return state; +} + +static DG_FLUSH_STATE_T handleFlushModeFlushR1ToR2State( void ) +{ + DG_FLUSH_STATE_T state = DG_FLUSH_STATE_FLUSH_R1_TO_R2; + + if ( rsrvr1Status == DG_RESERVOIR_BELOW_TARGET ) + { + rsrvr1Status = getRsrvrFillStatus( DG_RESERVOIR_1, RSRVRS_FULL_VOL_ML, RSRVRS_FILL_UP_TIMEOUT_MS ); + } + else if ( rsrvr1Status == DG_RESERVOIR_REACHED_TARGET ) + { + if ( rsrvr2Status == DG_RESERVOIR_BELOW_TARGET ) + { + rsrvr2Status = getRsrvrFillStatus( DG_RESERVOIR_2, RSRVRS_PARTIAL_FILL_VOL_ML, RSRVRS_PARTIAL_FILL_TIMEOUT_MS ); + } + else if ( rsrvr2Status == DG_RESERVOIR_REACHED_TARGET ) + { + // Set the actuators to flush R2 and drain R1 state + setValveState( VRF, VALVE_STATE_R2_C_TO_NO ); + setValveState( VRI, VALVE_STATE_R1_C_TO_NO ); + setValveState( VRO, VALVE_STATE_R2_C_TO_NC ); + setValveState( VRD, VALVE_STATE_R1_C_TO_NC ); + setDrainPumpTargetRPM( DRAIN_PUMP_TARGET_RPM ); + stateTimer = getMSTimerCount(); + + // Set both reservoirs status + rsrvr1Status = DG_RESERVOIR_ABOVE_TARGET; + rsrvr2Status = DG_RESERVOIR_BELOW_TARGET; + state = DG_FLUSH_STATE_FLUSH_R2_AND_DRAIN_R1; + } + else if ( rsrvr2Status == DG_RESERVOIR_NOT_REACHED_TARGET ) + { + state = DG_FLUSH_STATE_CANCEL_WATER_PATH; + } + } + else if ( rsrvr1Status == DG_RESERVOIR_NOT_REACHED_TARGET ) + { + state = DG_FLUSH_STATE_CANCEL_WATER_PATH; + } + + return state; +} + +static DG_FLUSH_STATE_T handleFlushModeFlushR2AndDrainR1State( void ) +{ + DG_FLUSH_STATE_T state = DG_FLUSH_STATE_FLUSH_R2_AND_DRAIN_R1; + + // If reservoir 1 is empty, turn off the drain pump + if ( rsrvr1Status == DG_RESERVOIR_ABOVE_TARGET ) + { + rsrvr1Status = getRsrvrDrainStatus( DG_RESERVOIR_1, DRAIN_WEIGHT_UNCHANGE_TIMEOUT, RSRVRS_DRAIN_TIME_OUT_MS ); + } + else if ( rsrvr1Status == DG_RESERVOIR_REACHED_TARGET ) + { + // Done with draining R1 + signalDrainPumpHardStop(); + } + else if ( rsrvr1Status == DG_RESERVOIR_NOT_REACHED_TARGET ) + { + state = DG_FLUSH_STATE_CANCEL_BASIC_PATH; + } + + // First reservoir 2 must be completely full + if ( rsrvr2Status == DG_RESERVOIR_BELOW_TARGET ) + { + rsrvr2Status = getRsrvrFillStatus( DG_RESERVOIR_2, RSRVRS_FULL_VOL_ML, RSRVRS_FILL_UP_TIMEOUT_MS ); + } + // Once R2 is full, R1 must be partially full + else if( rsrvr2Status == DG_RESERVOIR_REACHED_TARGET ) + { + rsrvr1Status = getRsrvrFillStatus( DG_RESERVOIR_1, RSRVRS_PARTIAL_FILL_VOL_ML, RSRVRS_PARTIAL_FILL_TIMEOUT_MS ); + + // Once R1 is partially full, transition to the next state + if ( rsrvr1Status == DG_RESERVOIR_REACHED_TARGET ) + { + signalROPumpHardStop(); + setValveState( VRD, VALVE_STATE_R2_C_TO_NO ); + setDrainPumpTargetRPM( DRAIN_PUMP_TARGET_RPM ); + + stateTimer = getMSTimerCount(); + isThisInitialDrain = FALSE; + state = DG_FLUSH_STATE_DRAIN_R2; + } + // TODO add timeout + } + // TODO add timeout + + return state; +} + +static DG_FLUSH_STATE_T handleFlushModeFlushCirculationState( void ) +{ + DG_FLUSH_STATE_T state = DG_FLUSH_STATE_FLUSH_CIRCULATION; + + return state; +} + +static DG_FLUSH_STATE_T handleFlushModeCancelBasicPathState( void ) +{ + DG_FLUSH_STATE_T state = DG_FLUSH_STATE_CANCEL_BASIC_PATH; + + return state; +} + +static DG_FLUSH_STATE_T handleFlushModeCancelWaterPathState( void ) +{ + DG_FLUSH_STATE_T state = DG_FLUSH_STATE_CANCEL_WATER_PATH; + + return state; +} + +static DG_FLUSH_STATE_T handleFlushModeComplete( void ) +{ + DG_FLUSH_STATE_T state = DG_FLUSH_STATE_COMPLETE; + + return state; +} + +/*********************************************************************//** + * @brief + * The resetActuators function sets all the actuators to reset and + * de-energized state. + * @details Inputs: none + * @details Outputs: none + * @return none + *************************************************************************/ +static void resetActuators( void ) +{ + // Turn off the UV reactors + turnOffUVReactor( INLET_UV_REACTOR ); + turnOffUVReactor( OUTLET_UV_REACTOR ); + + // De-energize all the valves + setValveState( VPI, VALVE_STATE_OPEN ); + setValveState( VBF, VALVE_STATE_CLOSED ); + setValveState( VSP, VALVE_STATE_CLOSED ); + setValveState( VPD, VALVE_STATE_OPEN_C_TO_NO ); + setValveState( VPO, VALVE_STATE_NOFILL_C_TO_NO ); + setValveState( VDR, VALVE_STATE_DRAIN_C_TO_NO ); + setValveState( VRC, VALVE_STATE_DRAIN_C_TO_NO ); + setValveState( VRO, VALVE_STATE_R1_C_TO_NO ); + setValveState( VRD, VALVE_STATE_R2_C_TO_NO ); + setValveState( VRI, VALVE_STATE_R1_C_TO_NO ); + setValveState( VRF, VALVE_STATE_R2_C_TO_NO ); + + //TODO add the composition pumps + signalROPumpHardStop(); + signalDrainPumpHardStop(); + stopPrimaryHeater(); + stopTrimmerHeater(); +} + +static void setModeToFailed( void ) +{ + SET_ALARM_WITH_1_U32_DATA( alarm, prevFlushState ) +} + +static DG_RESERVOIR_STATUS_T getRsrvrFillStatus( DG_RESERVOIR_ID_T r, F32 targetVol, U32 timeout ) +{ + DG_RESERVOIR_STATUS_T status = DG_RESERVOIR_BELOW_TARGET; + F32 volume = 0.0; + + if ( r == DG_RESERVOIR_1 ) + { + volume = getLoadCellSmallFilteredWeight( LOAD_CELL_RESERVOIR_1_PRIMARY ); + } + else if ( r == DG_RESERVOIR_2 ) + { + volume = getLoadCellSmallFilteredWeight( LOAD_CELL_RESERVOIR_2_PRIMARY ); + } + + // Check the volume of the reservoir against the target volume + if ( volume >= targetVol ) + { + if ( ++rsrvrFillStableTimeCounter >= RSRVRS_FULL_STABLE_TIME_COUNT ) + { + status = DG_RESERVOIR_REACHED_TARGET; + rsrvrFillStableTimeCounter = 0; + // Set the state timer in case it needs to be used for another timeout check + stateTimer = getMSTimerCount(); + } + } + else if ( didTimeout( stateTimer, timeout ) ) + { + // Failed to fill on time + alarm = ALARM_ID_DG_RESERVOIR_FILL_TIMEOUT; + status = DG_RESERVOIR_NOT_REACHED_TARGET; + } + + return status; +} + +static DG_RESERVOIR_STATUS_T getRsrvrDrainStatus( DG_RESERVOIR_ID_T r, U32 drainSteadyStateTimeout, U32 timeout ) +{ + DG_RESERVOIR_STATUS_T status = DG_RESERVOIR_ABOVE_TARGET; + + BOOL isDrainComplete = hasTargetDrainVolumeBeenReached( r, drainSteadyStateTimeout ); + + if ( TRUE == isDrainComplete ) + { + // Set the state timer in case it needs to be used for another timeout check + stateTimer = getMSTimerCount(); + status = DG_RESERVOIR_REACHED_TARGET; + } + else if ( didTimeout( stateTimer, timeout ) ) + { + // Failed to drain on time + prevFlushState = flushState; + alarm = ALARM_ID_DG_RESERVOIR_DRAIN_TIMEOUT; + status = DG_RESERVOIR_NOT_REACHED_TARGET; + } + + return status; +} + +static void publishFlushData( void ) +{ + if ( ++dataPublishCounter > FLUSH_DATA_PUB_INTERVAL ) + { + MODE_FLUSH_DATA_T data; + + data.flushState = (U32)flushState; + data.overallElapsedTime = calcTimeSince( overallFlushElapsedTime ); + data.stateElapsedTime = calcTimeSince( stateTimer ); + + broadcastFlushData( &data ); + + dataPublishCounter = 0; + } +} + /**@}*/ Index: firmware/App/Modes/ModeFlush.h =================================================================== diff -u -r54f45c387430e440ab4607451fc84dea61f273f1 -r5d8530d242d8065178eab9e3e5d8e4561b790e01 --- firmware/App/Modes/ModeFlush.h (.../ModeFlush.h) (revision 54f45c387430e440ab4607451fc84dea61f273f1) +++ firmware/App/Modes/ModeFlush.h (.../ModeFlush.h) (revision 5d8530d242d8065178eab9e3e5d8e4561b790e01) @@ -31,6 +31,14 @@ // ********** public definitions ********** +/// Flush mode data publish struct +typedef struct +{ + U32 flushState; ///< Flush state. + U32 overallElapsedTime; ///< Overall elapsed time in flush mode. + U32 stateElapsedTime; ///< Current flush elapsed time. +} MODE_FLUSH_DATA_T; + // ********** public function prototypes ********** void initFlushMode( void ); // initialize this module @@ -39,6 +47,8 @@ DG_FLUSH_STATE_T getCurrentFlushState( void ); // get the current state of the flush mode. +void stopDGFlush( void ); + /**@}*/ #endif Index: firmware/App/Modes/ModeStandby.c =================================================================== diff -u -r484b185f0cf4b2ea0ba9de331573952b1b5124b4 -r5d8530d242d8065178eab9e3e5d8e4561b790e01 --- firmware/App/Modes/ModeStandby.c (.../ModeStandby.c) (revision 484b185f0cf4b2ea0ba9de331573952b1b5124b4) +++ firmware/App/Modes/ModeStandby.c (.../ModeStandby.c) (revision 5d8530d242d8065178eab9e3e5d8e4561b790e01) @@ -226,6 +226,28 @@ /*********************************************************************//** * @brief + * The startDGFlush function starts DG flush mode. + * @details Inputs: standbyState + * @details Outputs: none + * @return: TRUE if the switch was successful, otherwise FALSE + *************************************************************************/ +BOOL startDGFlush( void ) +{ + BOOL result = FALSE; + + // If DG is in standby mode and the standby mode is in Idle state, request DG flush + if ( DG_MODE_STAN == getCurrentOperationMode() && DG_STANDBY_MODE_STATE_IDLE == standbyState ) + { + requestNewOperationMode( DG_MODE_FLUS ); + + result = TRUE; + } + + return result; +} + +/*********************************************************************//** + * @brief * The getCurrentStandbyState function returns the current state of standby mode. * @details Inputs: standbyState * @details Outputs: none Index: firmware/App/Modes/ModeStandby.h =================================================================== diff -u -r54f45c387430e440ab4607451fc84dea61f273f1 -r5d8530d242d8065178eab9e3e5d8e4561b790e01 --- firmware/App/Modes/ModeStandby.h (.../ModeStandby.h) (revision 54f45c387430e440ab4607451fc84dea61f273f1) +++ firmware/App/Modes/ModeStandby.h (.../ModeStandby.h) (revision 5d8530d242d8065178eab9e3e5d8e4561b790e01) @@ -42,6 +42,8 @@ BOOL requestWaterSample( void ); // HD requests water sample BOOL requestDGStart( void ); // HD requests DG start (go to re-circulate mode) +BOOL startDGFlush( void ); + /**@}*/ #endif Index: firmware/App/Services/AlarmMgmt.h =================================================================== diff -u -rac55f23681cd3a29ec235265f73c67895e36ada9 -r5d8530d242d8065178eab9e3e5d8e4561b790e01 --- firmware/App/Services/AlarmMgmt.h (.../AlarmMgmt.h) (revision ac55f23681cd3a29ec235265f73c67895e36ada9) +++ firmware/App/Services/AlarmMgmt.h (.../AlarmMgmt.h) (revision 5d8530d242d8065178eab9e3e5d8e4561b790e01) @@ -164,6 +164,7 @@ SW_FAULT_ID_INVALID_TEMPERATURE_SENSOR_SELECTED, SW_FAULT_ID_DRAIN_PUMP_INVALID_RPM_SELECTED, SW_FAULT_ID_ALARM_MGMT_INVALID_ALARM_ID, + SW_FAULT_ID_DG_FLUSH_INVALID_EXEC_STATE, // 75 NUM_OF_SW_FAULT_IDS } SW_FAULT_ID_T; Index: firmware/App/Services/Reservoirs.c =================================================================== diff -u -r484b185f0cf4b2ea0ba9de331573952b1b5124b4 -r5d8530d242d8065178eab9e3e5d8e4561b790e01 --- firmware/App/Services/Reservoirs.c (.../Reservoirs.c) (revision 484b185f0cf4b2ea0ba9de331573952b1b5124b4) +++ firmware/App/Services/Reservoirs.c (.../Reservoirs.c) (revision 5d8530d242d8065178eab9e3e5d8e4561b790e01) @@ -14,43 +14,43 @@ * @date (original) 18-Mar-2020 * ***************************************************************************/ - -#include // for memcpy() -#include "LoadCell.h" -#include "ModeRecirculate.h" -#include "OperationModes.h" -#include "Reservoirs.h" -#include "SystemCommMessages.h" +#include // for memcpy() + +#include "LoadCell.h" +#include "ModeRecirculate.h" +#include "OperationModes.h" +#include "Reservoirs.h" +#include "SystemCommMessages.h" #include "TaskGeneral.h" -#include "Timers.h" -#include "Valves.h" - -/** - * @addtogroup Reservoirs - * @{ - */ - -// ********** private definitions ********** - -#define MIN_RESERVOIR_VOLUME_ML 0 ///< Minimum reservoir volume in mL. -#define MAX_RESERVOIR_VOLUME_ML 2000 ///< Maximum reservoir volume in mL. -#define DEFAULT_FILL_VOLUME_ML 1700 ///< Default fill volume for treatment in mL. -#define DISINFECT_FILL_VOLUME_ML 2400 ///< Fill volume for disinfection in mL. -#define MAX_FILL_VOLUME_ML MAX_RESERVOIR_VOLUME_ML ///< Maximum fill volume in mL. -#define DEFAULT_DRAIN_VOLUME_ML 100 ///< Default drain volume in mL. -#define MAX_DRAIN_VOLUME_ML MAX_RESERVOIR_VOLUME_ML ///< Maximum drain volume in mL. +#include "Timers.h" +#include "Valves.h" -#define MAX_RESERVOIR_WEIGHT 10000 ///< Maximum reservoir weight in grams. - -#define RESERVOIR_DATA_PUB_INTERVAL ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ) ///< interval (ms/task time) at which the reservoir data is published on the CAN bus. +/** + * @addtogroup Reservoirs + * @{ + */ -// ********** private data ********** - -static U32 reservoirDataPublicationTimerCounter = 0; ///< used to schedule reservoir data publication to CAN bus. - -static OVERRIDE_U32_T activeReservoir = { 0, 0, 0, 0 }; ///< The active reservoir that the DG is filling/draining/etc. -static OVERRIDE_U32_T fillVolumeTargetMl = { 0, 0, 0, 0 }; ///< The target reservoir fill volume (in mL). +// ********** private definitions ********** + +#define MIN_RESERVOIR_VOLUME_ML 0 ///< Minimum reservoir volume in mL. +#define MAX_RESERVOIR_VOLUME_ML 2000 ///< Maximum reservoir volume in mL. +#define DEFAULT_FILL_VOLUME_ML 1700 ///< Default fill volume for treatment in mL. +#define DISINFECT_FILL_VOLUME_ML 2400 ///< Fill volume for disinfection in mL. +#define MAX_FILL_VOLUME_ML MAX_RESERVOIR_VOLUME_ML ///< Maximum fill volume in mL. +#define DEFAULT_DRAIN_VOLUME_ML 0 ///< Default drain volume in mL. +#define MAX_DRAIN_VOLUME_ML MAX_RESERVOIR_VOLUME_ML ///< Maximum drain volume in mL. + +#define MAX_RESERVOIR_WEIGHT 10000 ///< Maximum reservoir weight in grams. + +#define RESERVOIR_DATA_PUB_INTERVAL ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ) ///< interval (ms/task time) at which the reservoir data is published on the CAN bus. + +// ********** private data ********** + +static U32 reservoirDataPublicationTimerCounter = 0; ///< used to schedule reservoir data publication to CAN bus. + +static OVERRIDE_U32_T activeReservoir = { 0, 0, 0, 0 }; ///< The active reservoir that the DG is filling/draining/etc. +static OVERRIDE_U32_T fillVolumeTargetMl = { 0, 0, 0, 0 }; ///< The target reservoir fill volume (in mL). static OVERRIDE_U32_T drainVolumeTargetMl = { 0, 0, 0, 0 }; ///< The target reservoir drain volume (in mL). /// The reservoirs' associate load cell. @@ -62,104 +62,100 @@ static F32 reservoirLowestWeight[ NUM_OF_DG_RESERVOIRS ] = { MAX_RESERVOIR_WEIGHT, MAX_RESERVOIR_WEIGHT }; static U32 reservoirWeightUnchangeStartTime[ NUM_OF_DG_RESERVOIRS ] = { 0, 0 }; ///< The reservoirs' weight start time when weight stop decreasing. static BOOL tareLoadCellRequest; ///< Flag indicates if load cell tare has been requested by HD. - + // ********** private function prototypes ********** static DG_RESERVOIR_ID_T getActiveReservoir( void ); static U32 getReservoirFillVolumeTargetMl( void ); -static U32 getReservoirDrainVolumeTargetMl( void ); - -/*********************************************************************//** - * @brief - * The initReservoirs function initializes the Reservoirs module. - * @details Inputs: none - * @details Outputs: Reservoirs module initialized - * @return none - *************************************************************************/ -void initReservoirs( void ) -{ - activeReservoir.data = DG_RESERVOIR_2; - setValveState( VRF, VALVE_STATE_R1_C_TO_NC ); - setValveState( VRD, VALVE_STATE_R1_C_TO_NC ); - setValveState( VRO, VALVE_STATE_R2_C_TO_NC ); - setValveState( VRI, VALVE_STATE_R2_C_TO_NC ); - fillVolumeTargetMl.data = DEFAULT_FILL_VOLUME_ML; - drainVolumeTargetMl.data = DEFAULT_DRAIN_VOLUME_ML; -} - -/*********************************************************************//** - * @brief - * The execReservoirs function manages periodic tasks for the Reservoirs module. - * @details Inputs: none - * @details Outputs: Reservoir data broadcast on interval - * @return none - *************************************************************************/ -void execReservoirs( void ) -{ - // publish active reservoir, fill/drain volume targets at 1 Hz. - if ( ++reservoirDataPublicationTimerCounter >= RESERVOIR_DATA_PUB_INTERVAL ) - { - U32 actRes = getActiveReservoir(); - U32 filVol = getReservoirFillVolumeTargetMl(); - U32 drnVol = getReservoirDrainVolumeTargetMl(); - broadcastReservoirData( actRes, filVol, drnVol ); - reservoirDataPublicationTimerCounter = 0; - } -} - -/*********************************************************************//** - * @brief - * The setActiveReservoirCmd function sets the given reservoir as active - * (meaning HD will be drawing from this reservoir). - * @details Inputs: none - * @details Outputs: Specified reservoir is set as active. - * @param resID ID of reservoir to set as active - * @return none - *************************************************************************/ -void setActiveReservoirCmd( DG_RESERVOIR_ID_T resID ) +static U32 getReservoirDrainVolumeTargetMl( void ); + +/*********************************************************************//** + * @brief + * The initReservoirs function initializes the Reservoirs module. + * @details Inputs: none + * @details Outputs: Reservoirs module initialized + * @return none + *************************************************************************/ +void initReservoirs( void ) { + setActiveReservoirCmd( DG_RESERVOIR_1 ); + fillVolumeTargetMl.data = DEFAULT_FILL_VOLUME_ML; + drainVolumeTargetMl.data = DEFAULT_DRAIN_VOLUME_ML; +} + +/*********************************************************************//** + * @brief + * The execReservoirs function manages periodic tasks for the Reservoirs module. + * @details Inputs: none + * @details Outputs: Reservoir data broadcast on interval + * @return none + *************************************************************************/ +void execReservoirs( void ) +{ + // publish active reservoir, fill/drain volume targets at 1 Hz. + if ( ++reservoirDataPublicationTimerCounter >= RESERVOIR_DATA_PUB_INTERVAL ) + { + U32 actRes = getActiveReservoir(); + U32 filVol = getReservoirFillVolumeTargetMl(); + U32 drnVol = getReservoirDrainVolumeTargetMl(); + broadcastReservoirData( actRes, filVol, drnVol ); + reservoirDataPublicationTimerCounter = 0; + } +} + +/*********************************************************************//** + * @brief + * The setActiveReservoirCmd function sets the given reservoir as active + * (meaning HD will be drawing from this reservoir). + * @details Inputs: none + * @details Outputs: Specified reservoir is set as active. + * @param resID ID of reservoir to set as active + * @return none + *************************************************************************/ +void setActiveReservoirCmd( DG_RESERVOIR_ID_T resID ) +{ DG_CMD_RESPONSE_T cmdResponse; cmdResponse.commandID = DG_CMD_SWITCH_RESERVOIR; cmdResponse.rejected = TRUE; cmdResponse.rejectCode = DG_CMD_REQUEST_REJECT_REASON_NONE; - - // switch reservoir command only valid in re-circulate mode - if ( DG_MODE_CIRC == getCurrentOperationMode() ) - { - switch ( resID ) - { - case DG_RESERVOIR_1: + + // switch reservoir command only valid in re-circulate mode + if ( DG_MODE_CIRC == getCurrentOperationMode() ) + { + switch ( resID ) + { + case DG_RESERVOIR_1: activeReservoir.data = (U32)resID; - cmdResponse.rejected = FALSE; - setValveState( VRF, VALVE_STATE_R2_C_TO_NO ); - setValveState( VRD, VALVE_STATE_R2_C_TO_NO ); - setValveState( VRO, VALVE_STATE_R1_C_TO_NO ); - setValveState( VRI, VALVE_STATE_R1_C_TO_NO ); - break; - - case DG_RESERVOIR_2: + cmdResponse.rejected = FALSE; + setValveState( VRF, VALVE_STATE_R2_C_TO_NO ); + setValveState( VRD, VALVE_STATE_R2_C_TO_NO ); + setValveState( VRO, VALVE_STATE_R1_C_TO_NO ); + setValveState( VRI, VALVE_STATE_R1_C_TO_NO ); + break; + + case DG_RESERVOIR_2: activeReservoir.data = (U32)resID; - cmdResponse.rejected = FALSE; - setValveState( VRF, VALVE_STATE_R1_C_TO_NC ); - setValveState( VRD, VALVE_STATE_R1_C_TO_NC ); - setValveState( VRO, VALVE_STATE_R2_C_TO_NC ); - setValveState( VRI, VALVE_STATE_R2_C_TO_NC ); - break; - - default: + cmdResponse.rejected = FALSE; + setValveState( VRF, VALVE_STATE_R1_C_TO_NC ); + setValveState( VRD, VALVE_STATE_R1_C_TO_NC ); + setValveState( VRO, VALVE_STATE_R2_C_TO_NC ); + setValveState( VRI, VALVE_STATE_R2_C_TO_NC ); + break; + + default: // invalid reservoir given - cmd will be NAK'd w/ false result. - cmdResponse.rejectCode = DG_CMD_REQUEST_REJECT_REASON_INVALID_PARAMETER; - break; - } + cmdResponse.rejectCode = DG_CMD_REQUEST_REJECT_REASON_INVALID_PARAMETER; + break; + } } else { cmdResponse.rejectCode = DG_CMD_REQUEST_REJECT_REASON_INVALID_MODE; - } + } sendCommandResponseMsg( &cmdResponse ); -} +} /*********************************************************************//** * @brief @@ -208,149 +204,175 @@ sendCommandResponseMsg( &cmdResponse ); } - -/*********************************************************************//** - * @brief - * The startFillCmd function handles a fill command from the HD. - * @details Inputs: none - * @details Outputs: move to fill mode - * @param fillToVolMl Target volume (in mL) to fill reservoir to - * @return none - *************************************************************************/ -void startFillCmd( U32 fillToVolMl ) -{ + +/*********************************************************************//** + * @brief + * The startFillCmd function handles a fill command from the HD. + * @details Inputs: none + * @details Outputs: move to fill mode + * @param fillToVolMl Target volume (in mL) to fill reservoir to + * @return none + *************************************************************************/ +void startFillCmd( U32 fillToVolMl ) +{ DG_CMD_RESPONSE_T cmdResponse; cmdResponse.commandID = DG_CMD_START_FILL; cmdResponse.rejected = TRUE; - cmdResponse.rejectCode = DG_CMD_REQUEST_REJECT_REASON_NONE; - - // fill command only valid in re-circulate mode - if ( ( DG_MODE_CIRC == getCurrentOperationMode() ) && - ( DG_RECIRCULATE_MODE_STATE_RECIRC_WATER == getCurrentRecirculateState() ) ) - { - // validate parameters - if ( fillToVolMl < MAX_FILL_VOLUME_ML ) - { - fillVolumeTargetMl.data = fillToVolMl; - requestNewOperationMode( DG_MODE_FILL ); - cmdResponse.rejected = FALSE; + cmdResponse.rejectCode = DG_CMD_REQUEST_REJECT_REASON_NONE; + + // fill command only valid in re-circulate mode + if ( ( DG_MODE_CIRC == getCurrentOperationMode() ) && + ( DG_RECIRCULATE_MODE_STATE_RECIRC_WATER == getCurrentRecirculateState() ) ) + { + // validate parameters + if ( fillToVolMl < MAX_FILL_VOLUME_ML ) + { + fillVolumeTargetMl.data = fillToVolMl; + requestNewOperationMode( DG_MODE_FILL ); + cmdResponse.rejected = FALSE; } else { cmdResponse.rejectCode = DG_CMD_REQUEST_REJECT_REASON_INVALID_PARAMETER; - } + } } else { cmdResponse.rejectCode = DG_CMD_REQUEST_REJECT_REASON_INVALID_MODE; - } + } - sendCommandResponseMsg( &cmdResponse ); -} - -/*********************************************************************//** - * @brief - * The stopFillCmd function handles a stop fill command from the HD. - * @details Inputs: none - * @details Outputs: move to re-circulate mode - * @return none - *************************************************************************/ -void stopFillCmd( void ) -{ + sendCommandResponseMsg( &cmdResponse ); +} + +/*********************************************************************//** + * @brief + * The stopFillCmd function handles a stop fill command from the HD. + * @details Inputs: none + * @details Outputs: move to re-circulate mode + * @return none + *************************************************************************/ +void stopFillCmd( void ) +{ DG_CMD_RESPONSE_T cmdResponse; cmdResponse.commandID = DG_CMD_STOP_FILL; cmdResponse.rejected = TRUE; cmdResponse.rejectCode = DG_CMD_REQUEST_REJECT_REASON_NONE; - - // stop fill command only valid in fill mode - if ( DG_MODE_FILL == getCurrentOperationMode() ) - { - fillVolumeTargetMl.data = 0; - requestNewOperationMode( DG_MODE_CIRC ); - cmdResponse.rejected = FALSE; + + // stop fill command only valid in fill mode + if ( DG_MODE_FILL == getCurrentOperationMode() ) + { + fillVolumeTargetMl.data = 0; + requestNewOperationMode( DG_MODE_CIRC ); + cmdResponse.rejected = FALSE; } else { cmdResponse.rejectCode = DG_CMD_REQUEST_REJECT_REASON_INVALID_MODE; - } - - sendCommandResponseMsg( &cmdResponse ); -} - -/*********************************************************************//** - * @brief - * The startDrainCmd function handles a drain command from the HD. - * @details Inputs: none - * @details Outputs: Start draining in re-circulate mode - * @param drainCmd drain command data record - * @return none - *************************************************************************/ -void startDrainCmd( DRAIN_CMD_T drainCmd ) -{ + } + + sendCommandResponseMsg( &cmdResponse ); +} + +/*********************************************************************//** + * @brief + * The startDrainCmd function handles a drain command from the HD. + * @details Inputs: none + * @details Outputs: Start draining in re-circulate mode + * @param drainCmd drain command data record + * @return none + *************************************************************************/ +void startDrainCmd( DRAIN_CMD_T drainCmd ) +{ DG_CMD_RESPONSE_T cmdResponse; cmdResponse.commandID = DG_CMD_START_DRAIN; cmdResponse.rejected = TRUE; - cmdResponse.rejectCode = DG_CMD_REQUEST_REJECT_REASON_NONE; - - // drain command only valid in re-circulate mode - if ( DG_MODE_CIRC == getCurrentOperationMode() ) - { - // validate parameters - if ( drainCmd.targetVolume <= MAX_DRAIN_VOLUME_ML ) - { + cmdResponse.rejectCode = DG_CMD_REQUEST_REJECT_REASON_NONE; + + // drain command only valid in re-circulate mode + if ( DG_MODE_CIRC == getCurrentOperationMode() ) + { + // validate parameters + if ( drainCmd.targetVolume <= MAX_DRAIN_VOLUME_ML ) + { drainVolumeTargetMl.data = drainCmd.targetVolume; - tareLoadCellRequest = drainCmd.tareLoadCell; - requestNewOperationMode( DG_MODE_DRAI ); - cmdResponse.rejected = FALSE; + tareLoadCellRequest = drainCmd.tareLoadCell; + requestNewOperationMode( DG_MODE_DRAI ); + cmdResponse.rejected = FALSE; } else { cmdResponse.rejectCode = DG_CMD_REQUEST_REJECT_REASON_INVALID_PARAMETER; - } + } } else { cmdResponse.rejectCode = DG_CMD_REQUEST_REJECT_REASON_INVALID_MODE; - } - - sendCommandResponseMsg( &cmdResponse ); -} - -/*********************************************************************//** - * @brief - * The stopDrainCmd function handles a stop drain command from the HD. - * @details Inputs: none - * @details Outputs: move to re-circulate mode - * @return none - *************************************************************************/ -void stopDrainCmd( void ) -{ + } + + sendCommandResponseMsg( &cmdResponse ); +} + +/*********************************************************************//** + * @brief + * The stopDrainCmd function handles a stop drain command from the HD. + * @details Inputs: none + * @details Outputs: move to re-circulate mode + * @return none + *************************************************************************/ +void stopDrainCmd( void ) +{ DG_CMD_RESPONSE_T cmdResponse; cmdResponse.commandID = DG_CMD_STOP_DRAIN; cmdResponse.rejected = TRUE; - cmdResponse.rejectCode = DG_CMD_REQUEST_REJECT_REASON_NONE; - - // stop drain command only valid in drain mode - if ( DG_MODE_DRAI == getCurrentOperationMode() ) - { - drainVolumeTargetMl.data = 0; - requestNewOperationMode( DG_MODE_CIRC ); - cmdResponse.rejected = FALSE; - } + cmdResponse.rejectCode = DG_CMD_REQUEST_REJECT_REASON_NONE; + + // stop drain command only valid in drain mode + if ( DG_MODE_DRAI == getCurrentOperationMode() ) + { + drainVolumeTargetMl.data = 0; + requestNewOperationMode( DG_MODE_CIRC ); + cmdResponse.rejected = FALSE; + } else { cmdResponse.rejectCode = DG_CMD_REQUEST_REJECT_REASON_INVALID_MODE; } - - sendCommandResponseMsg( &cmdResponse ); -} + sendCommandResponseMsg( &cmdResponse ); +} + /*********************************************************************//** * @brief + * The tareReservoir function sets the tare load cell variable to TRUE. + * @details Inputs: none + * @details Outputs: none + * @return none + *************************************************************************/ +void tareReservoir( void ) +{ + tareLoadCellRequest = TRUE; +} + +/*********************************************************************//** + * @brief + * The resetReservoirsLowestWeight function resets the lowest load cell + * weight of the reservoirs. + * @details Inputs: reservoirLowestWeight + * @details Outputs: reservoirLowestWeight + * @return none + *************************************************************************/ +void resetReservoirsLowestWeight( void ) +{ + reservoirLowestWeight[ DG_RESERVOIR_1 ] = MAX_RESERVOIR_WEIGHT; + reservoirLowestWeight[ DG_RESERVOIR_2 ] = MAX_RESERVOIR_WEIGHT; +} + +/*********************************************************************//** + * @brief * The getInactiveReservoir function gets the inactive reservoir. * @details Inputs: activeReservoir * @details Outputs: none @@ -514,142 +536,142 @@ } -/************************************************************************* - * TEST SUPPORT FUNCTIONS - *************************************************************************/ +/************************************************************************* + * TEST SUPPORT FUNCTIONS + *************************************************************************/ - -/*********************************************************************//** - * @brief - * The testSetDGActiveReservoirOverride function overrides the active reservoir. - * @details Inputs: activeReservoir - * @details Outputs: activeReservoir - * @param value override active reservoir ID - * @return TRUE if override successful, FALSE if not - *************************************************************************/ -BOOL testSetDGActiveReservoirOverride( DG_RESERVOIR_ID_T value ) -{ - BOOL result = FALSE; - - if ( TRUE == isTestingActivated() ) - { - result = TRUE; - activeReservoir.ovData = value; - activeReservoir.override = OVERRIDE_KEY; - } - - return result; -} - -/*********************************************************************//** - * @brief - * The activeReservoir function resets the override of the active reservoir. - * @details Inputs: activeReservoir - * @details Outputs: activeReservoir - * @return TRUE if override reset successful, FALSE if not - *************************************************************************/ -BOOL testResetDGActiveReservoirOverride( void ) -{ - BOOL result = FALSE; - - if ( TRUE == isTestingActivated() ) - { - result = TRUE; - activeReservoir.override = OVERRIDE_RESET; - activeReservoir.ovData = activeReservoir.ovInitData; - } - - return result; -} - -/*********************************************************************//** - * @brief - * The testSetReservoirFillVolumeMlOverride function overrides the target - * reservoir fill volume (in mL). - * @details Inputs: fillVolumeTargetMl - * @details Outputs: fillVolumeTargetMl - * @param value override target reservoir fill volume (in mL) - * @return TRUE if override successful, FALSE if not - *************************************************************************/ -BOOL testSetReservoirFillVolumeMlOverride( U32 value ) -{ - BOOL result = FALSE; - - if ( TRUE == isTestingActivated() ) - { - result = TRUE; - fillVolumeTargetMl.ovData = value; - fillVolumeTargetMl.override = OVERRIDE_KEY; - } - - return result; -} - -/*********************************************************************//** - * @brief + +/*********************************************************************//** + * @brief + * The testSetDGActiveReservoirOverride function overrides the active reservoir. + * @details Inputs: activeReservoir + * @details Outputs: activeReservoir + * @param value override active reservoir ID + * @return TRUE if override successful, FALSE if not + *************************************************************************/ +BOOL testSetDGActiveReservoirOverride( DG_RESERVOIR_ID_T value ) +{ + BOOL result = FALSE; + + if ( TRUE == isTestingActivated() ) + { + result = TRUE; + activeReservoir.ovData = value; + activeReservoir.override = OVERRIDE_KEY; + } + + return result; +} + +/*********************************************************************//** + * @brief + * The activeReservoir function resets the override of the active reservoir. + * @details Inputs: activeReservoir + * @details Outputs: activeReservoir + * @return TRUE if override reset successful, FALSE if not + *************************************************************************/ +BOOL testResetDGActiveReservoirOverride( void ) +{ + BOOL result = FALSE; + + if ( TRUE == isTestingActivated() ) + { + result = TRUE; + activeReservoir.override = OVERRIDE_RESET; + activeReservoir.ovData = activeReservoir.ovInitData; + } + + return result; +} + +/*********************************************************************//** + * @brief + * The testSetReservoirFillVolumeMlOverride function overrides the target + * reservoir fill volume (in mL). + * @details Inputs: fillVolumeTargetMl + * @details Outputs: fillVolumeTargetMl + * @param value override target reservoir fill volume (in mL) + * @return TRUE if override successful, FALSE if not + *************************************************************************/ +BOOL testSetReservoirFillVolumeMlOverride( U32 value ) +{ + BOOL result = FALSE; + + if ( TRUE == isTestingActivated() ) + { + result = TRUE; + fillVolumeTargetMl.ovData = value; + fillVolumeTargetMl.override = OVERRIDE_KEY; + } + + return result; +} + +/*********************************************************************//** + * @brief * The testResetReservoirFillVolumeMlOverride function resets the override of - * the target reservoir fill volume. - * @details Inputs: fillVolumeTargetMl - * @details Outputs: fillVolumeTargetMl - * @return TRUE if override reset successful, FALSE if not - *************************************************************************/ -BOOL testResetReservoirFillVolumeMlOverride( void ) -{ - BOOL result = FALSE; - - if ( TRUE == isTestingActivated() ) - { - result = TRUE; - fillVolumeTargetMl.override = OVERRIDE_RESET; - fillVolumeTargetMl.ovData = fillVolumeTargetMl.ovInitData; - } - - return result; -} - -/*********************************************************************//** - * @brief - * The testSetReservoirDrainVolumeMlOverride function overrides the target - * reservoir drain volume (in mL). - * @details Inputs: drainVolumeTargetMl - * @details Outputs: drainVolumeTargetMl - * @param value override target reservoir drain volume (in mL) - * @return TRUE if override successful, FALSE if not - *************************************************************************/ -BOOL testSetReservoirDrainVolumeMlOverride( U32 value ) -{ - BOOL result = FALSE; - - if ( TRUE == isTestingActivated() ) - { - result = TRUE; - drainVolumeTargetMl.ovData = value; - drainVolumeTargetMl.override = OVERRIDE_KEY; - } - - return result; -} - -/*********************************************************************//** - * @brief + * the target reservoir fill volume. + * @details Inputs: fillVolumeTargetMl + * @details Outputs: fillVolumeTargetMl + * @return TRUE if override reset successful, FALSE if not + *************************************************************************/ +BOOL testResetReservoirFillVolumeMlOverride( void ) +{ + BOOL result = FALSE; + + if ( TRUE == isTestingActivated() ) + { + result = TRUE; + fillVolumeTargetMl.override = OVERRIDE_RESET; + fillVolumeTargetMl.ovData = fillVolumeTargetMl.ovInitData; + } + + return result; +} + +/*********************************************************************//** + * @brief + * The testSetReservoirDrainVolumeMlOverride function overrides the target + * reservoir drain volume (in mL). + * @details Inputs: drainVolumeTargetMl + * @details Outputs: drainVolumeTargetMl + * @param value override target reservoir drain volume (in mL) + * @return TRUE if override successful, FALSE if not + *************************************************************************/ +BOOL testSetReservoirDrainVolumeMlOverride( U32 value ) +{ + BOOL result = FALSE; + + if ( TRUE == isTestingActivated() ) + { + result = TRUE; + drainVolumeTargetMl.ovData = value; + drainVolumeTargetMl.override = OVERRIDE_KEY; + } + + return result; +} + +/*********************************************************************//** + * @brief * The testResetReservoirDrainVolumeMlOverride function resets the override of - * the target reservoir drain volume. - * @details Inputs: drainVolumeTargetMl - * @details Outputs: drainVolumeTargetMl - * @return TRUE if override reset successful, FALSE if not - *************************************************************************/ -BOOL testResetReservoirDrainVolumeMlOverride( void ) -{ - BOOL result = FALSE; - - if ( TRUE == isTestingActivated() ) - { - result = TRUE; - drainVolumeTargetMl.override = OVERRIDE_RESET; - drainVolumeTargetMl.ovData = drainVolumeTargetMl.ovInitData; - } - - return result; -} - -/**@}*/ + * the target reservoir drain volume. + * @details Inputs: drainVolumeTargetMl + * @details Outputs: drainVolumeTargetMl + * @return TRUE if override reset successful, FALSE if not + *************************************************************************/ +BOOL testResetReservoirDrainVolumeMlOverride( void ) +{ + BOOL result = FALSE; + + if ( TRUE == isTestingActivated() ) + { + result = TRUE; + drainVolumeTargetMl.override = OVERRIDE_RESET; + drainVolumeTargetMl.ovData = drainVolumeTargetMl.ovInitData; + } + + return result; +} + +/**@}*/ Index: firmware/App/Services/Reservoirs.h =================================================================== diff -u -r484b185f0cf4b2ea0ba9de331573952b1b5124b4 -r5d8530d242d8065178eab9e3e5d8e4561b790e01 --- firmware/App/Services/Reservoirs.h (.../Reservoirs.h) (revision 484b185f0cf4b2ea0ba9de331573952b1b5124b4) +++ firmware/App/Services/Reservoirs.h (.../Reservoirs.h) (revision 5d8530d242d8065178eab9e3e5d8e4561b790e01) @@ -14,23 +14,23 @@ * @date (original) 18-Mar-2020 * ***************************************************************************/ - -#ifndef __RESERVOIRS_H__ -#define __RESERVOIRS_H__ +#ifndef __RESERVOIRS_H__ +#define __RESERVOIRS_H__ + #include "DGCommon.h" -#include "DGDefs.h" - -/** - * @defgroup Reservoirs Reservoirs - * @brief Reservoirs service module. Maintains reservoir set points and handles reservoir related commands from the HD. - * - * @addtogroup Reservoirs - * @{ - */ - -// ********** public definitions ********** +#include "DGDefs.h" +/** + * @defgroup Reservoirs Reservoirs + * @brief Reservoirs service module. Maintains reservoir set points and handles reservoir related commands from the HD. + * + * @addtogroup Reservoirs + * @{ + */ + +// ********** public definitions ********** + #pragma pack(push,1) /// Drain command data structure. @@ -48,35 +48,39 @@ U32 rejectCode; ///< Reason code for rejecting the command } DG_CMD_RESPONSE_T; -#pragma pack(pop) - -// ********** public function prototypes ********** - -void initReservoirs( void ); -void execReservoirs( void ); +#pragma pack(pop) +// ********** public function prototypes ********** + +void initReservoirs( void ); +void execReservoirs( void ); + void setActiveReservoirCmd( DG_RESERVOIR_ID_T resID ); // handle switch reservoirs command from HD -void changeValveSettingCmd( DG_VALVE_SETTING_ID_T valveSettingID ); // handle valve setting change command from HD -void startFillCmd( U32 fillToVolMl ); // handle fill command from HD -void stopFillCmd( void ); // handle stop fill command from HD -void startDrainCmd( DRAIN_CMD_T drainCmd ); // handle drain command from HD -void stopDrainCmd( void ); // handle stop drain command from HD - +void changeValveSettingCmd( DG_VALVE_SETTING_ID_T valveSettingID ); // handle valve setting change command from HD +void startFillCmd( U32 fillToVolMl ); // handle fill command from HD +void stopFillCmd( void ); // handle stop fill command from HD +void startDrainCmd( DRAIN_CMD_T drainCmd ); // handle drain command from HD +void stopDrainCmd( void ); // handle stop drain command from HD + +void tareReservoir( void ); + +void resetReservoirsLowestWeight( void ); + DG_RESERVOIR_ID_T getInactiveReservoir( void ); F32 getReservoirWeight( DG_RESERVOIR_ID_T reservoirId ); - -BOOL hasTargetFillVolumeBeenReached( DG_RESERVOIR_ID_T reservoirId ); + +BOOL hasTargetFillVolumeBeenReached( DG_RESERVOIR_ID_T reservoirId ); BOOL hasTargetDrainVolumeBeenReached( DG_RESERVOIR_ID_T reservoirId , U32 timeout ); void resetReservoirLoadCellsOffset( DG_RESERVOIR_ID_T reservoirId ); - -BOOL testSetDGActiveReservoirOverride( DG_RESERVOIR_ID_T value ); -BOOL testResetDGActiveReservoirOverride( void ); -BOOL testSetReservoirFillVolumeMlOverride( U32 value ); -BOOL testResetReservoirFillVolumeMlOverride( void ); -BOOL testSetReservoirDrainVolumeMlOverride( U32 value ); -BOOL testResetReservoirDrainVolumeMlOverride( void ); - -/**@}*/ - -#endif + +BOOL testSetDGActiveReservoirOverride( DG_RESERVOIR_ID_T value ); +BOOL testResetDGActiveReservoirOverride( void ); +BOOL testSetReservoirFillVolumeMlOverride( U32 value ); +BOOL testResetReservoirFillVolumeMlOverride( void ); +BOOL testSetReservoirDrainVolumeMlOverride( U32 value ); +BOOL testResetReservoirDrainVolumeMlOverride( void ); + +/**@}*/ + +#endif Index: firmware/App/Services/SystemComm.c =================================================================== diff -u -r1b8f3d5802dcd34fbd8ab27163aec26b1ec08088 -r5d8530d242d8065178eab9e3e5d8e4561b790e01 --- firmware/App/Services/SystemComm.c (.../SystemComm.c) (revision 1b8f3d5802dcd34fbd8ab27163aec26b1ec08088) +++ firmware/App/Services/SystemComm.c (.../SystemComm.c) (revision 5d8530d242d8065178eab9e3e5d8e4561b790e01) @@ -1039,6 +1039,10 @@ handleTesterLogInRequest( message ); break; + case MSG_ID_DG_START_STOP_FLUSH: + handleStartStopDGFlush( message ); + break; + default: // unrecognized message ID received - ok, ignore - may be a test message handled below break; Index: firmware/App/Services/SystemCommMessages.c =================================================================== diff -u -r98eaa905f2487013d5e9af76bf064f872332c2fe -r5d8530d242d8065178eab9e3e5d8e4561b790e01 --- firmware/App/Services/SystemCommMessages.c (.../SystemCommMessages.c) (revision 98eaa905f2487013d5e9af76bf064f872332c2fe) +++ firmware/App/Services/SystemCommMessages.c (.../SystemCommMessages.c) (revision 5d8530d242d8065178eab9e3e5d8e4561b790e01) @@ -27,6 +27,7 @@ #include "Heaters.h" #include "LoadCell.h" #include "MessagePayloads.h" +#include "ModeFlush.h" #include "ModeStandby.h" #include "ModeRecirculate.h" #include "MsgQueues.h" @@ -911,7 +912,33 @@ return result; } +/*********************************************************************//** + * @brief + * The broadcastFlushData function sends out the flush mode data. + * @details Inputs: none + * @details Outputs: flush data msg constructed and queued + * @param flushData which is flush msg constructed and queued + * @return TRUE if msg successfully queued for transmit, FALSE if not + *************************************************************************/ +BOOL broadcastFlushData( MODE_FLUSH_DATA_T *flushData ) +{ + BOOL result; + MESSAGE_T msg; + U08 *payloadPtr = msg.payload; + // create a message record + blankMessage( &msg ); + msg.hdr.msgID = MSG_ID_DG_FLUSH_DATA; + msg.hdr.payloadLen = sizeof( MODE_FLUSH_DATA_T ); + + memcpy( payloadPtr, flushData, sizeof( MODE_FLUSH_DATA_T ) ); + + // serialize the message (w/ sync, CRC, and appropriate CAN padding) and add serialized message data to appropriate comm buffer + result = serializeMessage( msg, COMM_BUFFER_OUT_CAN_DG_BROADCAST, ACK_NOT_REQUIRED ); + + return result; +} + /*********************************************************************//** * @brief * The sendCommandResponseMsg function constructs a command response to HD @@ -2511,7 +2538,15 @@ sendTestAckResponseMsg( (MSG_ID_T)message->hdr.msgID, result ); } -//*******************************************************************/ +/*********************************************************************//** +* @brief +* The handleROPumpTargetPressureOverride function handles a request +* to override the RO pump target pressure. +* @details Inputs: none +* @details Outputs: message handled +* @param message a pointer to the message to handle +* @return none +*************************************************************************/ void handleROPumpTargetPressureOverride( MESSAGE_T *message ) { BOOL result = FALSE; @@ -2531,4 +2566,39 @@ sendTestAckResponseMsg( (MSG_ID_T)message->hdr.msgID, result ); } +/*********************************************************************//** +* @brief +* The handleStartStopDGFlush function handles a request to override start +* or stop DG flush mode. +* @details Inputs: none +* @details Outputs: message handled +* @param message a pointer to the message to handle +* @return none +*************************************************************************/ +BOOL handleStartStopDGFlush( MESSAGE_T *message ) +{ + BOOL result = FALSE; + + if ( message->hdr.payloadLen == sizeof(U32) ) + { + BOOL startingDGFlush; + + memcpy( &startingDGFlush, message->payload, sizeof(U32) ); + + if ( TRUE == startingDGFlush ) + { + startDGFlush(); + result = TRUE; + } + else + { + stopDGFlush(); + result = TRUE; + } + } + sendAckResponseMsg( (MSG_ID_T)message->hdr.msgID, COMM_BUFFER_OUT_CAN_DG_2_HD, result ); + + return result; +} + /**@}*/ Index: firmware/App/Services/SystemCommMessages.h =================================================================== diff -u -r98eaa905f2487013d5e9af76bf064f872332c2fe -r5d8530d242d8065178eab9e3e5d8e4561b790e01 --- firmware/App/Services/SystemCommMessages.h (.../SystemCommMessages.h) (revision 98eaa905f2487013d5e9af76bf064f872332c2fe) +++ firmware/App/Services/SystemCommMessages.h (.../SystemCommMessages.h) (revision 5d8530d242d8065178eab9e3e5d8e4561b790e01) @@ -22,6 +22,7 @@ #include "DrainPump.h" #include "Fans.h" #include "FluidLeak.h" +#include "ModeFlush.h" #include "MsgQueues.h" #include "Reservoirs.h" #include "ROPump.h" @@ -103,6 +104,9 @@ // MSG_ID_DG_FLUID_LEAK_STATE BOOL broadcastFluidLeakState( FLUID_LEAK_STATES_T state); +// MSG_ID_DG_FLUSH_DATA +BOOL broadcastFlushData( MODE_FLUSH_DATA_T *flushData ); + // MSG_ID_DG_COMMAND_RESPONSE void sendCommandResponseMsg( DG_CMD_RESPONSE_T *cmdResponsePtr ); @@ -276,6 +280,9 @@ // MSG_ID_DG_RO_PUMP_TARGET_PRESSURE_OVERRIDE void handleROPumpTargetPressureOverride( MESSAGE_T *message ); +// MSG_ID_DG_START_STOP_FLUSH +BOOL handleStartStopDGFlush( MESSAGE_T *message ); + /**@}*/ #endif