Index: firmware/App/Controllers/ConductivitySensors.c =================================================================== diff -u -r86617288c49b57eca42cf2d0b67ade76e69f96bd -re44aad7a9d5fa48aeaa55c65bd28ad9acde6ce05 --- firmware/App/Controllers/ConductivitySensors.c (.../ConductivitySensors.c) (revision 86617288c49b57eca42cf2d0b67ade76e69f96bd) +++ firmware/App/Controllers/ConductivitySensors.c (.../ConductivitySensors.c) (revision e44aad7a9d5fa48aeaa55c65bd28ad9acde6ce05) @@ -284,7 +284,7 @@ } else { - activateAlarmNoData( ALARM_ID_DG_SOFTWARE_FAULT ); + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DG_SOFTWARE_FAULT, SW_FAULT_ID_INVALID_CONDUCTIVITY_SENSOR_ID, sensorId ); } return result; Index: firmware/App/Controllers/DrainPump.c =================================================================== diff -u -r5a36a768d11cc597a36b894c1fb3a5e5590130f1 -re44aad7a9d5fa48aeaa55c65bd28ad9acde6ce05 --- firmware/App/Controllers/DrainPump.c (.../DrainPump.c) (revision 5a36a768d11cc597a36b894c1fb3a5e5590130f1) +++ firmware/App/Controllers/DrainPump.c (.../DrainPump.c) (revision e44aad7a9d5fa48aeaa55c65bd28ad9acde6ce05) @@ -359,7 +359,6 @@ if ( isAlarmActive( ALARM_ID_DRAIN_PUMP_OFF_FAULT ) ) { activateSafetyShutdown(); - BOOL test = FALSE; } } #endif Index: firmware/App/Controllers/Heaters.c =================================================================== diff -u -r8467f8ff09e382e0991f14d02683080dc811e24e -re44aad7a9d5fa48aeaa55c65bd28ad9acde6ce05 --- firmware/App/Controllers/Heaters.c (.../Heaters.c) (revision 8467f8ff09e382e0991f14d02683080dc811e24e) +++ firmware/App/Controllers/Heaters.c (.../Heaters.c) (revision e44aad7a9d5fa48aeaa55c65bd28ad9acde6ce05) @@ -219,6 +219,19 @@ /*********************************************************************//** * @brief + * The getPrimaryHeaterTargetTemperature function return the primary heater + * target temperature. + * @details Inputs: primaryHeaterTargetTemperature + * @details Outputs: none + * @return the current primary heater target temperature + *************************************************************************/ +F32 getPrimaryHeaterTargetTemperature( void ) +{ + return primaryHeaterTargetTemperature; +} + +/*********************************************************************//** + * @brief * The startPrimaryHeater function starts the primary heaters. It resets * the primary heaters state and sets the main primary heater duty cycle. * @details Inputs: primaryHeaterTargetTemperature @@ -272,8 +285,6 @@ *************************************************************************/ void stopPrimaryHeater( void ) { - setMainPrimaryHeaterPWM( HEATERS_MIN_DUTY_CYCLE ); - setSmallPrimaryHeaterPWM( HEATERS_MIN_DUTY_CYCLE ); isPrimaryHeaterOn = FALSE; } @@ -286,7 +297,6 @@ *************************************************************************/ void stopTrimmerHeater( void ) { - setTrimmerHeaterPWM( HEATERS_MIN_DUTY_CYCLE ); isTrimmerHeaterOn = FALSE; } @@ -684,6 +694,8 @@ // Switch to off state. Set the duty cycles to 0 mainPrimaryHeaterDutyCycle = HEATERS_MIN_DUTY_CYCLE; smallPrimaryHeaterDutyCycle = HEATERS_MIN_DUTY_CYCLE; + setMainPrimaryHeaterPWM( HEATERS_MIN_DUTY_CYCLE ); + setSmallPrimaryHeaterPWM( HEATERS_MIN_DUTY_CYCLE ); state = PRIMARY_HEATERS_EXEC_STATE_OFF; } @@ -759,6 +771,7 @@ { // Set the duty cycle to 0 and switch to off state trimmerHeaterDutyCycle = HEATERS_MIN_DUTY_CYCLE; + setTrimmerHeaterPWM( HEATERS_MIN_DUTY_CYCLE ); state = TRIMMER_HEATER_EXEC_STATE_OFF; } Index: firmware/App/Controllers/LoadCell.c =================================================================== diff -u -r7e632c636be41c139d2d97cc845298ff98ff66ed -re44aad7a9d5fa48aeaa55c65bd28ad9acde6ce05 --- firmware/App/Controllers/LoadCell.c (.../LoadCell.c) (revision 7e632c636be41c139d2d97cc845298ff98ff66ed) +++ firmware/App/Controllers/LoadCell.c (.../LoadCell.c) (revision e44aad7a9d5fa48aeaa55c65bd28ad9acde6ce05) @@ -34,33 +34,33 @@ // TODO check the maximum weight on the load cells in tare. There was 1500 grams limit // but it has been removed. Check the load cells data sheet. -#define LOAD_CELL_REPORT_PERIOD (100 / TASK_PRIORITY_INTERVAL) ///< Broadcast load cell values message every 100 ms. +#define LOAD_CELL_REPORT_PERIOD (100 / TASK_PRIORITY_INTERVAL) ///< Broadcast load cell values message every 100 ms. /// Conversion factor from ADC counts to grams. -static const F32 ADC2GRAM = (0.0894 * 1.1338); -#define LOAD_CELL_FILTER_ALPHA 0.05 ///< Alpha factor for the alpha filter used on load cell readings. +static const F32 ADC2GRAM = (0.0894 * 1.1338); +#define LOAD_CELL_FILTER_ALPHA 0.05 ///< Alpha factor for the alpha filter used on load cell readings. #define SIZE_OF_SMALL_LOAD_CELL_AVG 100 ///< Small load cell moving average has 100 raw samples @ 10ms intervals (1-second). -#define SIZE_OF_LARGE_LOAD_CELL_AVG 40 ///< Large load cell moving average has 40 samples from small filter @ 100ms intervals (4-second). +#define SIZE_OF_LARGE_LOAD_CELL_AVG 40 ///< Large load cell moving average has 40 samples from small filter @ 100ms intervals (4-second). #define LOAD_CELL_ADC_ERROR_PERSISTENCE 500 ///< Alarm persistence period (in ms) for load cell ADC errors. -#define EMPTY_RESERVOIR_WEIGHT_GRAMS 1600 ///< Reservoirs empty weight in grams. +#define EMPTY_RESERVOIR_WEIGHT_GRAMS 1600 ///< Reservoirs empty weight in grams. #define MAX_ALLOWED_EXTRA_WEIGHT_BEFORE_TARE_GRAMS 300 ///< Max allowed extra weight before tare in grams. /// Load cell data structure. typedef struct { - U32 rawReading; ///< Latest raw load cell reading - OVERRIDE_F32_T weight; ///< Latest load cell weight + U32 rawReading; ///< Latest raw load cell reading. + OVERRIDE_F32_T weight; ///< Latest load cell weight. F32 autoCalOffset; ///< Load cell auto-calibration offset F32 loadCellVelocity_g_min; ///< Velocity (in g/min) of load cell. - F32 smallFilterReadings[ SIZE_OF_SMALL_LOAD_CELL_AVG ]; ///< Load cell samples for small load cell moving average. - F32 smallFilterTotal; ///< Small filter rolling total - used to calc small load cell moving average. - F32 smallFilteredWeight; ///< Load cell small filtered (100 100Hz raw sample) weight. + F32 smallFilterReadings[ SIZE_OF_SMALL_LOAD_CELL_AVG ]; ///< Load cell samples for small load cell moving average. + F32 smallFilterTotal; ///< Small filter rolling total - used to calc small load cell moving average. + F32 smallFilteredWeight; ///< Load cell small filtered (100 100Hz raw sample) weight. - F32 largeFilterReadings[ SIZE_OF_LARGE_LOAD_CELL_AVG ]; ///< Load cell samples for large load cell moving average. - F32 largeFilterTotal; ///< Large filter rolling total - used to calc small load cell moving average. - F32 largeFilteredWeight; ///< Load cell large filtered (40 10Hz filtered sample) weight. + F32 largeFilterReadings[ SIZE_OF_LARGE_LOAD_CELL_AVG ]; ///< Load cell samples for large load cell moving average. + F32 largeFilterTotal; ///< Large filter rolling total - used to calc small load cell moving average. + F32 largeFilteredWeight; ///< Load cell large filtered (40 10Hz filtered sample) weight. } LOADCELL_T; // ********** private data ********** Index: firmware/App/Controllers/UVReactors.c =================================================================== diff -u -ra8bb1da29825b5d666333629fda871652d16229a -re44aad7a9d5fa48aeaa55c65bd28ad9acde6ce05 --- firmware/App/Controllers/UVReactors.c (.../UVReactors.c) (revision a8bb1da29825b5d666333629fda871652d16229a) +++ firmware/App/Controllers/UVReactors.c (.../UVReactors.c) (revision e44aad7a9d5fa48aeaa55c65bd28ad9acde6ce05) @@ -19,7 +19,7 @@ #define INLET_UV_REACTOR_ENABLE_PIN 0 ///< Inlet UV reactor GPIO pin number (enable pin). #define OUTLET_UV_REACTOR_ENABLE_PIN 1 ///< Outlet UV reactor GPIO pin number (enable Pin). -#define INLET_UV_REACTOR_INDICATION_PIN 0x1A ///< Inlet UV reactor N2HET1 pin number (health check). +#define INLET_UV_REACTOR_INDICATION_PIN 0x18 ///< Inlet UV reactor N2HET1 pin number (health check). #define OUTLET_UV_REACTOR_INDICATION_PIN 0x0B ///< Outlet UV reactor N2HET1 pin number (health check). #define UV_REACTORS_DATA_PUB_INTERVAL ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ) ///< UV reactors data publication time interval. /// Self test wait time after enabling the reactors and before checking for their health in ms. @@ -75,7 +75,7 @@ static UV_REACTOR_STATE_T handleUVReactorStateOn( UV_REACTORS_T reactor ); // Support functions -static BOOL isReactorHealthy( UV_REACTORS_T reactor ); +static U32 getReactorHealth( UV_REACTORS_T reactor ); static void setReactorEnableStatus( UV_REACTORS_T reactor, PIN_SIGNAL_STATE_T state ); static void publishUVReactorsData( void ); static U32 getPublishUVReactorsDataInterval( void ); @@ -93,7 +93,7 @@ { UV_REACTORS_T reactor; - uvReactorsSelfTestResult = SELF_TEST_STATUS_IN_PROGRESS; + uvReactorsSelfTestResult = SELF_TEST_STATUS_IN_PROGRESS; uvReactorsSelfTestStates = UV_REACTORS_SELF_TEST_OFF; dataPublishCounter = 0; @@ -108,9 +108,9 @@ // Initialize the common values in the UV reactors for( reactor = INLET_UV_REACTOR; reactor < NUM_OF_UV_REACTORS; reactor++ ) { - reactorsStatus[ reactor ].pinSignalState = PIN_SIGNAL_LOW; - reactorsStatus[ reactor ].execState = UV_REACTOR_STATE_OFF; - reactorsStatus[ reactor ].switchState = TURN_OFF; + reactorsStatus[ reactor ].pinSignalState = PIN_SIGNAL_LOW; + reactorsStatus[ reactor ].execState = UV_REACTOR_STATE_OFF; + reactorsStatus[ reactor ].switchState = TURN_OFF; } initPersistentAlarm( ALARM_ID_UV_REACTOR_NOT_HEALTHY, MAX_ALLOWED_UNHEALTHY_REACTOR_PERIOD, MAX_ALLOWED_UNHEALTHY_REACTOR_PERIOD ); @@ -186,27 +186,28 @@ /*********************************************************************//** * @brief - * The getUVReactorHealth function returns the health status of a UV reactor. + * The getUVReactorHealth function returns the health status of a UV + * reactor. * @details Inputs: reactorsStatus * @details Outputs: none * @param reactor to return its health - * @return returns the health of the requested UV reactor + * @return returns the health of the requested UV reactor as an enum *************************************************************************/ -BOOL getUVReactorHealth( UV_REACTORS_T reactor ) +UV_REACTORS_HEALTH_STATUS_T getUVReactorHealth( UV_REACTORS_T reactor ) { - BOOL health = FALSE; + UV_REACTORS_HEALTH_STATUS_T health = UV_REACTOR_OFF; // Check if the reactor selected is in range if ( reactor < NUM_OF_UV_REACTORS ) { // Check if the health is in override or not if ( reactorsStatus[ reactor ].healthStatus.override == OVERRIDE_KEY ) { - health = reactorsStatus[ reactor ].healthStatus.ovData; + health = (UV_REACTORS_HEALTH_STATUS_T)reactorsStatus[ reactor ].healthStatus.ovData; } else { - health = reactorsStatus[ reactor ].healthStatus.data; + health = (UV_REACTORS_HEALTH_STATUS_T)reactorsStatus[ reactor ].healthStatus.data; } } else @@ -306,18 +307,19 @@ if ( TRUE == didTimeout( selfTestElapsedTime, SELF_TEST_DELAY_TIME ) ) { // Get the health status of the reactors - BOOL isInletHealthy = isReactorHealthy( INLET_UV_REACTOR ); - BOOL isOutletHealthy = isReactorHealthy( OUTLET_UV_REACTOR ); + BOOL isInletHealthy = (BOOL)getReactorHealth( INLET_UV_REACTOR ); + BOOL isOutletHealthy = (BOOL)getReactorHealth( OUTLET_UV_REACTOR ); // Check if both of them are healthy and if not, raise an alarm - if ( TRUE == isInletHealthy && TRUE == isOutletHealthy ) + if ( ( TRUE == isInletHealthy ) &&( TRUE == isOutletHealthy ) ) { uvReactorsSelfTestResult = SELF_TEST_STATUS_PASSED; } else { uvReactorsSelfTestResult = SELF_TEST_STATUS_FAILED; +#ifndef DISABLE_UV_REACTOR_MONITOR // Check which reactor has not been healthy and raise an alarm if ( FALSE == isInletHealthy ) { @@ -327,6 +329,7 @@ { SET_ALARM_WITH_1_U32_DATA( ALARM_ID_UV_REACTOR_NOT_HEALTHY, OUTLET_UV_REACTOR ); } +#endif } // Turn off the UV reactors once the test is finished @@ -351,6 +354,10 @@ { UV_REACTOR_STATE_T state = UV_REACTOR_STATE_OFF; + // Set the health status to be off. When the reactor is off, it does not report + // its health status + reactorsStatus[reactor].healthStatus.data = (U32)UV_REACTOR_OFF; + // If the a reactor is requested to be on and it is off, turn it on // and change the state if ( TURN_ON == reactorsStatus[ reactor ].switchState ) @@ -375,17 +382,21 @@ { UV_REACTOR_STATE_T state = UV_REACTOR_STATE_ON; - reactorsStatus[ reactor ].healthStatus.data = (U32)isReactorHealthy( reactor ); + // Update the UV reactor's health. It should be either healthy (1) or not healthy (0) + reactorsStatus[ reactor ].healthStatus.data = getReactorHealth( reactor ); - BOOL isReactorHealthy = getUVReactorHealth( reactor ); + // Get the health of the reactor (override or non-override) and decide the status + BOOL isReactorUnhealthy = ( UV_REACTOR_HEALTHY == getUVReactorHealth( reactor ) ? FALSE : TRUE ); - checkPersistentAlarm( ALARM_ID_UV_REACTOR_NOT_HEALTHY, !isReactorHealthy, (U32)reactor, MAX_ALLOWED_UNHEALTHY_REACTOR_PERIOD ); +#ifndef DISABLE_UV_REACTOR_MONITOR + checkPersistentAlarm( ALARM_ID_UV_REACTOR_NOT_HEALTHY, isReactorUnhealthy, (U32)reactor, MAX_ALLOWED_UNHEALTHY_REACTOR_PERIOD ); // Check if the alarm has been active if ( TRUE == isAlarmActive( ALARM_ID_UV_REACTOR_NOT_HEALTHY ) ) { reactorsStatus[ reactor ].switchState = TURN_OFF; } +#endif // Check if it has been requested to turn off a reactor if ( TURN_OFF == reactorsStatus[ reactor ].switchState ) @@ -411,23 +422,23 @@ static void setReactorEnableStatus( UV_REACTORS_T reactor, PIN_SIGNAL_STATE_T state ) { // Set the GIO pin to enable or disable - gioSetBit( gioPORTA, reactorsStatus[ reactor ].reactorEnablePin, state ); + gioSetBit( gioPORTA, reactorsStatus[ reactor ].reactorEnablePin, (U32)state ); // Update the pin signal state reactorsStatus[ reactor ].pinSignalState = state; } /*********************************************************************//** * @brief - * The isReactorHealthy function checks the health status of a reactor. + * The getReactorHealth function checks the health status of a reactor. * @details Inputs: reactorsStatus * @details Outputs: none * @param reactor to check its health - * @return returns TRUE if the reactor is healthy otherwise a FALSE + * @return returns 1 if the reactor is healthy otherwise a 0 *************************************************************************/ -static BOOL isReactorHealthy( UV_REACTORS_T reactor ) +static U32 getReactorHealth( UV_REACTORS_T reactor ) { - return (BOOL)gioGetBit( hetPORT1, reactorsStatus[ reactor ].reactorHealthStatusPin ); + return gioGetBit( hetPORT1, reactorsStatus[ reactor ].reactorHealthStatusPin ); } /*********************************************************************//** @@ -462,17 +473,18 @@ { UV_REACTORS_DATA_T uvReactorsData; // Publish the reactors health status - uvReactorsData.inletUVReactorHealthStatus = reactorsStatus[ INLET_UV_REACTOR ].reactorHealthStatusPin; - uvReactorsData.outletUVReactorHealthStatus = reactorsStatus[ OUTLET_UV_REACTOR ].reactorHealthStatusPin; - uvReactorsData.inletUVReactorState = reactorsStatus[ INLET_UV_REACTOR ].execState; - uvReactorsData.outletUVReactorHealthStatus = reactorsStatus[ OUTLET_UV_REACTOR ].execState; + uvReactorsData.inletUVReactorHealthStatus = (U32)getUVReactorHealth( INLET_UV_REACTOR ); + uvReactorsData.outletUVReactorHealthStatus = (U32)getUVReactorHealth( OUTLET_UV_REACTOR ); + uvReactorsData.inletUVReactorState = (U32)reactorsStatus[ INLET_UV_REACTOR ].execState; + uvReactorsData.outletUVReactorState = (U32)reactorsStatus[ OUTLET_UV_REACTOR ].execState; broadcastUVReactorsData( &uvReactorsData ); dataPublishCounter = 0; } } + /************************************************************************* * TEST SUPPORT FUNCTIONS *************************************************************************/ @@ -535,15 +547,15 @@ * @param health which is high for healthy on and low for not healthy * @return TRUE if override successful, FALSE if not *************************************************************************/ -BOOL testSetUVReactorHealthOverride( U32 reactor, BOOL health ) +BOOL testSetUVReactorHealthOverride( U32 reactor, U32 health ) { BOOL result = FALSE; - if ( TRUE == isTestingActivated() && (UV_REACTORS_T)reactor < NUM_OF_UV_REACTORS ) + if ( ( TRUE == isTestingActivated() ) && ( (UV_REACTORS_T)reactor < NUM_OF_UV_REACTORS ) ) { reactorsStatus[ (UV_REACTORS_T)reactor ].healthStatus.ovInitData = reactorsStatus[ (UV_REACTORS_T)reactor ].healthStatus.data; reactorsStatus[ (UV_REACTORS_T)reactor ].healthStatus.override = OVERRIDE_KEY; - reactorsStatus[ (UV_REACTORS_T)reactor ].healthStatus.ovData = (U32)health; + reactorsStatus[ (UV_REACTORS_T)reactor ].healthStatus.ovData = health; result = TRUE; } Index: firmware/App/DGCommon.h =================================================================== diff -u -r5a36a768d11cc597a36b894c1fb3a5e5590130f1 -re44aad7a9d5fa48aeaa55c65bd28ad9acde6ce05 --- firmware/App/DGCommon.h (.../DGCommon.h) (revision 5a36a768d11cc597a36b894c1fb3a5e5590130f1) +++ firmware/App/DGCommon.h (.../DGCommon.h) (revision e44aad7a9d5fa48aeaa55c65bd28ad9acde6ce05) @@ -23,9 +23,9 @@ // ********** version ********** #define DG_VERSION_MAJOR 0 -#define DG_VERSION_MINOR 5 +#define DG_VERSION_MINOR 6 #define DG_VERSION_MICRO 0 -#define DG_VERSION_BUILD 15 +#define DG_VERSION_BUILD 12 // ********** build switches ********** @@ -37,8 +37,8 @@ // #define SIMULATE_UI 1 // #define TASK_TIMING_OUTPUT_ENABLED 1 // re-purposes drain pump enable pin for task timing // #define DISABLE_HEATERS_AND_TEMPS 1 -// #define DISABLE_ACCELS 1 -// #define SKIP_POST 1 + #define DISABLE_ACCELS 1 + #define SKIP_POST 1 #define DISABLE_CAL_CHECK 1 // #define ENABLE_DIP_SWITCHES 1 // #define EMC_TEST_BUILD 1 @@ -49,11 +49,17 @@ #define IGNORE_DRAIN_PUMP_MONITOR 1 #define IGNORE_HEATERS_MONITOR 1 #define IGNORE_RO_PUMP_MONITOR 1 - #define IGNORE_HEAT_DISINFECT_RSRVR_TIMEOUT 1 -// #define DISABLE_RO_RATIO_CHECK 1 + #define IGNORE_DISINFECT_RSRVR_TIMEOUT 1 + #define DISABLE_RO_RATIO_CHECK 1 #define DISABLE_COND_SENSOR_CHECK 1 #define DISABLE_MIXING 1 -// #define DISABLE_WATER_QUALITY_CHECK 1 + #define DISABLE_WATER_QUALITY_CHECK 1 + #define DISABLE_RTC_CONFIG 1 +// #define V_2_SYSTEM 1 +// #define SKIP_RECIRC 1 + #define DISABLE_UV_REACTOR_MONITOR 1 + #define IGNORE_HEAT_DISINFECT_RSRVR_TIMEOUT 1 + #include #include #endif Index: firmware/App/Modes/ModeFault.c =================================================================== diff -u -r5a36a768d11cc597a36b894c1fb3a5e5590130f1 -re44aad7a9d5fa48aeaa55c65bd28ad9acde6ce05 --- firmware/App/Modes/ModeFault.c (.../ModeFault.c) (revision 5a36a768d11cc597a36b894c1fb3a5e5590130f1) +++ firmware/App/Modes/ModeFault.c (.../ModeFault.c) (revision e44aad7a9d5fa48aeaa55c65bd28ad9acde6ce05) @@ -123,12 +123,22 @@ setValveState( VPI, VALVE_STATE_CLOSED ); setValveState( VBF, VALVE_STATE_CLOSED ); setValveState( VSP, VALVE_STATE_CLOSED ); +#ifndef V_2_SYSTEM setValveState( VPD, VALVE_STATE_DRAIN_C_TO_NO ); +#else + setValveState( VPD, VALVE_STATE_OPEN_C_TO_NO ); +#endif 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 ); + +#ifndef V_2_SYSTEM + setValveState( VRD1, VALVE_STATE_CLOSED ); + setValveState( VRD2, VALVE_STATE_CLOSED ); +#else setValveState( VRD, VALVE_STATE_R2_C_TO_NO ); +#endif setValveState( VRI, VALVE_STATE_R1_C_TO_NO ); setValveState( VRF, VALVE_STATE_R2_C_TO_NO ); Index: firmware/App/Modes/ModeFlush.c =================================================================== diff -u -r654c5598765bb862c00a0175bdac95604c6c9b24 -re44aad7a9d5fa48aeaa55c65bd28ad9acde6ce05 --- firmware/App/Modes/ModeFlush.c (.../ModeFlush.c) (revision 654c5598765bb862c00a0175bdac95604c6c9b24) +++ firmware/App/Modes/ModeFlush.c (.../ModeFlush.c) (revision e44aad7a9d5fa48aeaa55c65bd28ad9acde6ce05) @@ -642,7 +642,7 @@ } } // Once reservoir 2 is full, reservoir 1 must be partially full - else if( DG_RESERVOIR_REACHED_TARGET == rsrvr2Status ) + else if ( DG_RESERVOIR_REACHED_TARGET == rsrvr2Status ) { rsrvr1Status = getRsrvrFillStatus( DG_RESERVOIR_1, RSRVRS_PARTIAL_FILL_VOL_ML, RSRVRS_PARTIAL_FILL_TIMEOUT_MS ); @@ -669,7 +669,7 @@ } } // Check if reservoir 2 fill time out - else if( DG_RESERVOIR_NOT_REACHED_TARGET == rsrvr2Status ) + else if ( DG_RESERVOIR_NOT_REACHED_TARGET == rsrvr2Status ) { state = DG_FLUSH_STATE_CANCEL_WATER_PATH; } Index: firmware/App/Modes/ModeHeatDisinfect.c =================================================================== diff -u -r5a36a768d11cc597a36b894c1fb3a5e5590130f1 -re44aad7a9d5fa48aeaa55c65bd28ad9acde6ce05 --- firmware/App/Modes/ModeHeatDisinfect.c (.../ModeHeatDisinfect.c) (revision 5a36a768d11cc597a36b894c1fb3a5e5590130f1) +++ firmware/App/Modes/ModeHeatDisinfect.c (.../ModeHeatDisinfect.c) (revision e44aad7a9d5fa48aeaa55c65bd28ad9acde6ce05) @@ -41,11 +41,11 @@ // General defines #define MAX_ALLOWED_STATE_TRIALS 1 ///< Max allowed trials on a state. This is general among all the states. -#define HEAT_DISINFECT_DATA_PUB_INTERVAL ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ) ///< Mode Heat Disinfect data publish interval in counts. +#define HEAT_DISINFECT_DATA_PUB_INTERVAL ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ) ///< Mode chem disinfect data publish interval in counts. // Start state defines #define MIN_INLET_PRESSURE_PSI 30.0 ///< Minimum water inlet pressure in psi. -#define MAX_START_STATE_TEMP_SENSORS_DIFF_C 1.0 ///< Max start state TDi and TRo difference tolerance in C. +#define MAX_START_STATE_TEMP_SENSORS_DIFF_C 3.0 ///< Max start state TDi and TRo difference tolerance in C. // Drain R1 & R2 states defines #define DRAIN_PUMP_TARGET_RPM 1800 ///< Drain pump target RPM during drain. @@ -106,7 +106,7 @@ CANCELLATION_MODE_HOT, ///< Cancellation mode hot. CANCELLATION_MODE_COLD, ///< Cancellation mode cold. NUM_OF_CANCELLATION_MODES ///< Number of cancellation modes. -} CANCELLATION_MODES_T; +} CANCELLATION_MODE_T; /// Heat disinfect status typedef enum Heat_disinfect_status @@ -137,7 +137,7 @@ static U32 rsrvrsVolMonitorTimer = 0; ///< Reservoir 1 & 2 volume monitor timers during heat disinfect. static BOOL areRsrvrsLeaking = FALSE; ///< Reservoir 1 & 2 leak check flag during heat disinfect. static U32 dataPublishCounter = 0; ///< Heat Disinfect data publish counter. -static CANCELLATION_MODES_T cancellationMode = CANCELLATION_MODE_NONE; ///< Cancellation mode. +static CANCELLATION_MODE_T cancellationMode = CANCELLATION_MODE_NONE; ///< Cancellation mode. static U32 rsrvrFillStableTimeCounter = 0; ///< Reservoirs fill stable time counter. static ALARM_ID_T alarmDetectedPendingTrigger; ///< Heat disinfect alarm to raise. static BOOL isDrainPumpInMixDrainOn = FALSE; ///< Flag to show the drain pump is on during mix drain. @@ -182,8 +182,8 @@ * @details Outputs: heatDisinfectState, stateTimer, isThisLastDrain, * stateTrialCounter, areTempSensorsInRange, rsrvr1Status, rsrvr2Status, * R1HeatDisinfectVol, R2HeatDisinfectVol, overallHeatDisinfectTimer, - * cancellationMode, rsrvrFillStableTimeCounter, isPartialDisinfectInProgress, - * isDrainPumpOnInMixDrain + * cancellationMode, rsrvrFillStableTimeCounter, prevHeatDisinfectState + * isPartialDisinfectInProgress, isDrainPumpOnInMixDrain * @return none *************************************************************************/ void initHeatDisinfectMode( void ) @@ -406,7 +406,7 @@ F32 TDiTemp = getTemperatureValue( TEMPSENSORS_OUTLET_REDUNDANT ); //TODo change to TDi F32 TRoTemp = getTemperatureValue( TEMPSENSORS_OUTLET_REDUNDANT ); - // If the inlet pressure is less than the threshold and TDi and TRo difference is greater than 1 C, the cycle + // If the inlet pressure is less than the threshold and TDi and TRo difference is greater than 3 C, the cycle // should be canceled if ( ( ppiPressure < MIN_INLET_PRESSURE_PSI ) && ( fabs( TDiTemp - TRoTemp ) > MAX_START_STATE_TEMP_SENSORS_DIFF_C ) ) { @@ -574,7 +574,7 @@ * @brief * The handleHeatDisinfectFlushDrainState function handles the heat disinfect * flush drain state. The state flushes the drain line for a period of time - * and then measure the temperature and conductivity of water. If they are + * and then measures the temperature and conductivity of water. If they are * not within the range, it transitions to basic cancellation path, otherwise * it transitions to the next state. * @details Inputs: stateTimer, stateTrialCounter, alarm, @@ -640,7 +640,7 @@ DG_HEAT_DISINFECT_STATE_T state = DG_HEAT_DISINFECT_STATE_FLUSH_CIRCULATION; // Check if the flush circulation time has elapsed and the temperature sensors are not in range yet - if ( TRUE == didTimeout( stateTimer, FLUSH_CICRCULATION_WAIT_TIME_MS ) && ( FALSE == areTempSensorsInRange ) ) + if ( ( TRUE == didTimeout( stateTimer, FLUSH_CICRCULATION_WAIT_TIME_MS ) ) && ( FALSE == areTempSensorsInRange ) ) { F32 ThdTemp = getTemperatureValue( TEMPSENSORS_OUTLET_REDUNDANT ); // TODO add THd later. This is the new temp sensor of the coldest spot. F32 TPoTemp = getTemperatureValue( TEMPSENSORS_OUTLET_PRIMARY_HEATER ); @@ -721,7 +721,7 @@ { rsrvr1Status = getRsrvrFillStatus( DG_RESERVOIR_1, RSRVRS_FULL_VOL_ML, RSRVRS_FILL_UP_TIMEOUT_MS ); - // Keep monitoring the status of reservoir 2 as the same time + // Keep monitoring the status of reservoir 2 at the same time rsrvr2Status = getRsrvrFillStatus( DG_RESERVOIR_2, RSRVRS_PARTIAL_FILL_VOL_ML, RSRVRS_500ML_FILL_UP_TIMEOUT_MS ); // Reservoir 2 cannot be filled before reservoir 1 is filled and is overflowing to reservoir 2. If reservoir 2 has already // reached to target volume, it means reservoir 1's load cell might be reading incorrect values. This situation might continue @@ -1039,7 +1039,7 @@ // Get the current volumes of R1 & R2. These values will be used to make sure the reservoirs' // volume does not change more than a certain amount during the actual heat disinfect cycle - R1HeatDisinfectVol = getLoadCellLargeFilteredWeight( LOAD_CELL_RESERVOIR_1_BACKUP ); //TODO change this back to primary + R1HeatDisinfectVol = getLoadCellLargeFilteredWeight( LOAD_CELL_RESERVOIR_1_PRIMARY ); R2HeatDisinfectVol = getLoadCellLargeFilteredWeight( LOAD_CELL_RESERVOIR_2_PRIMARY ); stateTimer = getMSTimerCount(); @@ -1150,15 +1150,15 @@ state = DG_HEAT_DISINFECT_STATE_DISINFECT_R2_TO_R1; } -#ifdef IGNORE_HEAT_DISINFECT_RSRVR_TIMEOUT +#ifdef IGNORE_DISINFECT_RSRVR_TIMEOUT else if ( DG_RESERVOIR_NOT_REACHED_TARGET == rsrvr2Status ) { prevHeatDisinfectState = state; state = DG_HEAT_DISINFECT_STATE_CANCEL_WATER_PATH; } #endif } -#ifdef IGNORE_HEAT_DISINFECT_RSRVR_TIMEOUT +#ifdef IGNORE_DISINFECT_RSRVR_TIMEOUT else if ( DG_RESERVOIR_NOT_REACHED_TARGET == rsrvr1Status ) { prevHeatDisinfectState = state; @@ -1176,8 +1176,8 @@ * temperature within a certain period of time, it transitions to water * cancellation state. If heat disinfect reservoir 1 to reservoir 2 is * completed, it transitions to the next state. - * @details Inputs: hasPostHeatDisinfectWaitStarted, stateTimer, rsrvr1Status - * @details Outputs: hasPostHeatDisinfectWaitStarted, stateTimer, rsrvr1Status + * @details Inputs: stateTimer, rsrvr1Status + * @details Outputs: stateTimer, rsrvr1Status * @return next state of the heat disinfect state machine *************************************************************************/ static DG_HEAT_DISINFECT_STATE_T handleHeatDisinfectDisinfectR2ToR1State( void ) @@ -1193,7 +1193,7 @@ break; case HEAT_DISINFECT_COMPLETE: - // Turn off the pumps and heaters + // Turn off the heaters // TODO turn off CP1 and CP2 stopPrimaryHeater(); stopTrimmerHeater(); @@ -1226,18 +1226,14 @@ // De-energize all the valves that are not in the path anymore // and wait for the RO membrane to be cooled down. - // In this state, VPi and VPd must still be kept energized to make sure fresh - // water does not enter the circulation path the membrane is cooling down setValveState( VPI, VALVE_STATE_CLOSED ); setValveState( VBF, VALVE_STATE_CLOSED ); #ifndef V_2_SYSTEM setValveState( VPD, VALVE_STATE_DRAIN_C_TO_NO ); setValveState( VRD1, VALVE_STATE_CLOSED ); #else setValveState( VPD, VALVE_STATE_DRAIN_C_TO_NC ); - #endif - stateTimer = getMSTimerCount(); state = DG_HEAT_DISINFECT_STATE_COOL_DOWN_RO_FILTER; } @@ -1303,6 +1299,10 @@ setValveState( VRD1, VALVE_STATE_OPEN ); #endif +#ifndef V_2_SYSTEM + setValveState( VRD1, VALVE_STATE_OPEN ); +#endif + // Turn on the drain pump to drain the reservoirs in open loop mode setDrainPumpTargetRPM( DRAIN_PUMP_RPM_IN_MIX_DRAIN ); } @@ -1410,6 +1410,18 @@ if ( DG_RESERVOIR_BELOW_TARGET == rsrvr1Status ) { rsrvr1Status = getRsrvrFillStatus( DG_RESERVOIR_1, RSRVRS_FULL_VOL_ML, RSRVRS_FILL_UP_TIMEOUT_MS ); + + // Keep monitoring the status of reservoir 2 at the same time + rsrvr2Status = getRsrvrFillStatus( DG_RESERVOIR_2, RSRVRS_PARTIAL_FILL_VOL_ML, RSRVRS_500ML_FILL_UP_TIMEOUT_MS ); + // Reservoir 2 cannot be filled before reservoir 1 is filled and is overflowing to reservoir 2. If reservoir 2 has already + // reached to target volume, it means reservoir 1's load cell might be reading incorrect values. This situation might continue + // until reservoir 2 is filled up and the tubing might expand or leak. + if ( DG_RESERVOIR_REACHED_TARGET == rsrvr2Status ) + { + prevHeatDisinfectState = state; + alarmDetectedPendingTrigger = ALARM_ID_DG_INVALID_LOAD_CELL_VALUE; + state = DG_HEAT_DISINFECT_STATE_CANCEL_WATER_PATH; + } } else if ( DG_RESERVOIR_REACHED_TARGET == rsrvr1Status ) { @@ -1487,6 +1499,21 @@ if ( DG_RESERVOIR_BELOW_TARGET == rsrvr2Status ) { rsrvr2Status = getRsrvrFillStatus( DG_RESERVOIR_2, RSRVRS_FULL_VOL_ML, RSRVRS_FILL_UP_TIMEOUT_MS ); + + U32 drainPumpRPM = getTargetDrainPumpRPM(); + // Keep monitoring the status of reservoir 1 as the same time + F32 volume = getLoadCellSmallFilteredWeight( LOAD_CELL_RESERVOIR_1_PRIMARY ); + // Reservoir 1 cannot be filled before reservoir 2 is filled and is overflowing to reservoir 1. If reservoir 1 has already + // reached to target volume, it means reservoir 2's load cell might be reading incorrect values. This situation might continue + // until reservoir 1 is filled up and the tubing might expand or leak. + // Before checking whether reservoir 1 is filled pre-maturely, we have to make sure reservoir 1 is drained completely to make + // sure the extra volume that is read is not because of previous water that is being drained currently and it is above 500 mL + if ( ( volume > RSRVRS_PARTIAL_FILL_VOL_ML ) && ( 0 == drainPumpRPM ) ) + { + prevHeatDisinfectState = state; + alarmDetectedPendingTrigger = ALARM_ID_DG_INVALID_LOAD_CELL_VALUE; + state = DG_HEAT_DISINFECT_STATE_CANCEL_WATER_PATH; + } } // Once reservoir 2 is completely full, monitor reservoir 1 else if ( DG_RESERVOIR_REACHED_TARGET == rsrvr2Status ) @@ -1706,48 +1733,9 @@ /*********************************************************************//** * @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 ) -{ - // UV reactors will not be used in the heat disinfection since their operating temperature - // range is below 85C and they might be damaged by the high temperature. - turnOffUVReactor( INLET_UV_REACTOR ); - turnOffUVReactor( OUTLET_UV_REACTOR ); - - // De-energize all the valves - setValveState( VPI, VALVE_STATE_CLOSED ); - setValveState( VBF, VALVE_STATE_CLOSED ); - setValveState( VSP, VALVE_STATE_CLOSED ); -#ifndef V_2_SYSTEM - setValveState( VPD, VALVE_STATE_OPEN_C_TO_NC ); -#else - setValveState( VPD, VALVE_STATE_OPEN_C_TO_NO ); -#endif - 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(); -} - -/*********************************************************************//** - * @brief * The failHeatDisinfect function sets the alarm that failed the heat * disinfect mode. - * @details Inputs: alarm, prevHeatDisinfectState + * @details Inputs: alarmDetectedPendingTrigger, prevHeatDisinfectState * @details Outputs: none * @return none *************************************************************************/ @@ -1775,7 +1763,7 @@ if ( r == DG_RESERVOIR_1 ) { - volume = getLoadCellSmallFilteredWeight( LOAD_CELL_RESERVOIR_1_BACKUP ); //TODO change back to primary + volume = getLoadCellSmallFilteredWeight( LOAD_CELL_RESERVOIR_1_PRIMARY ); } else if ( r == DG_RESERVOIR_2 ) { @@ -1814,8 +1802,7 @@ * reservoir. * @details Inputs: stateTimer, prevHeatDisinfectState, heatDisinfectState, * alarm - * @details Outputs: stateTimer, heatDisinfectState heatDisinfectState, - * alarm + * @details Outputs: stateTimer, heatDisinfectState, alarm * @param r is DG_RESERVOIR_1 or DG_RESERVOIR_2 * @param drainSteadyStateTimeout which is the time the reservoir's level * does not change and is steady state @@ -1866,11 +1853,11 @@ F32 TPoTemp = getTemperatureValue( TEMPSENSORS_OUTLET_PRIMARY_HEATER ); F32 ThdTemp = getTemperatureValue( TEMPSENSORS_OUTLET_REDUNDANT ); //TODO change this to actual TPm sensor later - BOOL isR1OutOfRange = fabs( getLoadCellSmallFilteredWeight( LOAD_CELL_RESERVOIR_1_BACKUP ) - R1HeatDisinfectVol ) > RSRVRS_MAX_TARGET_VOL_CHANGE_ML; //TODo change this to primary when the stupid load cell was fixed + BOOL isR1OutOfRange = fabs( getLoadCellSmallFilteredWeight( LOAD_CELL_RESERVOIR_1_PRIMARY ) - R1HeatDisinfectVol ) > RSRVRS_MAX_TARGET_VOL_CHANGE_ML; BOOL isR2OutOfRange = fabs( getLoadCellSmallFilteredWeight( LOAD_CELL_RESERVOIR_2_PRIMARY ) - R2HeatDisinfectVol ) > RSRVRS_MAX_TARGET_VOL_CHANGE_ML; // Check if either reservoir 1 or reservoir 2 are losing volume more than allowed volume - if ( isR1OutOfRange || isR2OutOfRange ) + if ( ( TRUE == isR1OutOfRange ) || ( TRUE == isR2OutOfRange ) ) { // If the leak is the first time after a while, set the flag and start the timer if ( FALSE == areRsrvrsLeaking ) Index: firmware/App/Modes/ModeRecirculate.c =================================================================== diff -u -r5a36a768d11cc597a36b894c1fb3a5e5590130f1 -re44aad7a9d5fa48aeaa55c65bd28ad9acde6ce05 --- firmware/App/Modes/ModeRecirculate.c (.../ModeRecirculate.c) (revision 5a36a768d11cc597a36b894c1fb3a5e5590130f1) +++ firmware/App/Modes/ModeRecirculate.c (.../ModeRecirculate.c) (revision e44aad7a9d5fa48aeaa55c65bd28ad9acde6ce05) @@ -166,7 +166,9 @@ // when enough water volume has flowed to flush the lines, transition to re-circ state if ( flushLinesVolumeL >= FLUSH_LINES_VOLUME_L ) { +#ifndef SKIP_RECIRC setValveState( VDR, VALVE_STATE_RECIRC_C_TO_NC ); +#endif setROPumpTargetFlowRate( TARGET_RO_FLOW_RATE_L, TARGET_RO_PRESSURE_PSI ); result = DG_RECIRCULATE_MODE_STATE_RECIRC_WATER; } Index: firmware/App/Modes/ModeStandby.c =================================================================== diff -u -r5a36a768d11cc597a36b894c1fb3a5e5590130f1 -re44aad7a9d5fa48aeaa55c65bd28ad9acde6ce05 --- firmware/App/Modes/ModeStandby.c (.../ModeStandby.c) (revision 5a36a768d11cc597a36b894c1fb3a5e5590130f1) +++ firmware/App/Modes/ModeStandby.c (.../ModeStandby.c) (revision e44aad7a9d5fa48aeaa55c65bd28ad9acde6ce05) @@ -19,6 +19,7 @@ #include "CPLD.h" #include "DrainPump.h" #include "Heaters.h" +#include "ModeFault.h" #include "ModeStandby.h" #include "OperationModes.h" #include "Pressures.h" @@ -98,6 +99,8 @@ // re-initialize standby mode each time we transition to standby mode initStandbyMode(); + //deenergizeActuators(); + // set initial actuator states setValveState( VRF, VALVE_STATE_R2_C_TO_NO ); setValveState( VRI, VALVE_STATE_R1_C_TO_NO ); @@ -191,7 +194,7 @@ filterFlushStartTime = getMSTimerCount(); setValveState( VPI, VALVE_STATE_OPEN ); #ifndef V_2_SYSTEM - setValveState( VPD, VALVE_STATE_OPEN_C_TO_NC ); + setValveState( VPD, VALVE_STATE_DRAIN_C_TO_NO ); #else setValveState( VPD, VALVE_STATE_OPEN ); // TODO: VPD drain state is closed for V3 #endif @@ -223,6 +226,7 @@ if ( TRUE == didTimeout( filterFlushStartTime, filterFlushTimePeriod_ms ) ) { + setValveState( VPI, VALVE_STATE_CLOSED ); state = DG_STANDBY_MODE_STATE_FLUSH_FILTER_IDLE; } @@ -288,6 +292,7 @@ // After HD requests to stop or 10 seconds has elapsed, close and return to idle state if ( ( TRUE == stopSampleWaterRequest ) || ( TRUE == didTimeout( waterSampleStartTime, MAX_WATER_SAMPLE_TIME_MS ) ) ) { + stopSampleWaterRequest = FALSE; setValveState( VSP, VALVE_STATE_CLOSED ); #ifndef V_2_SYSTEM setValveState( VPD, VALVE_STATE_DRAIN_C_TO_NO ); @@ -420,7 +425,28 @@ ( DG_MODE_SOLO == getCurrentOperationMode() ) ) { requestNewOperationMode( DG_MODE_HEAT ); + status = TRUE; + } + return status; +} + +/*********************************************************************//** + * @brief + * The startDGChemicalDisinfect function starts chemical disinfect mode. + * @details Inputs: standbyState + * @details Outputs: none + * @return: TRUE if the switch was successful + *************************************************************************/ +BOOL startDGChemicalDisinfect( void ) +{ + BOOL status = FALSE; + + // If DG is in standby mode and the standby mode is in Idle, request chemical disinfect + // Chemical disinfect cannot be run in solo mode because the user has to confirm that the acid is inserted or removed + //if ( ( DG_MODE_STAN == getCurrentOperationMode() ) && ( DG_STANDBY_MODE_STATE_IDLE == standbyState ) ) TODO un-comment this line. This is commented to be able to run chemical without HD for development + { + requestNewOperationMode( DG_MODE_CHEM ); status = TRUE; } Index: firmware/App/Modes/ModeStandby.h =================================================================== diff -u -r86eec09ab556fbd970ddcae9dc622727928ee757 -re44aad7a9d5fa48aeaa55c65bd28ad9acde6ce05 --- firmware/App/Modes/ModeStandby.h (.../ModeStandby.h) (revision 86eec09ab556fbd970ddcae9dc622727928ee757) +++ firmware/App/Modes/ModeStandby.h (.../ModeStandby.h) (revision e44aad7a9d5fa48aeaa55c65bd28ad9acde6ce05) @@ -37,15 +37,17 @@ void transitionToStandbyMode( void ); // prepares for transition to standby mode U32 execStandbyMode( void ); // execute the standby mode state machine (call from OperationModes) -DG_STANDBY_MODE_STATE_T getCurrentStandbyState( void ); // get the current state of the standby mode. - void waterSampleCommandHandler( SAMPLE_WATER_CMD_T sampleWaterCmd ); BOOL requestDGStart( void ); // HD requests DG start (go to re-circulate mode) BOOL startDGFlush( void ); // HD start flush mode BOOL startDGHeatDisinfect( void ); // HD start heat disinfect mode +DG_STANDBY_MODE_STATE_T getCurrentStandbyState( void ); // get the current state of the standby mode. +BOOL testSetFilterFlushTimePeriodOverride( U32 value ); +BOOL testResetFilterFlushTimePeriodOverride( void ); + BOOL startDGChemicalDisinfect( void ); // HD start chemical disinfect mode /**@}*/ Index: firmware/App/Services/AlarmMgmtSWFaults.h =================================================================== diff -u --- firmware/App/Services/AlarmMgmtSWFaults.h (revision 0) +++ firmware/App/Services/AlarmMgmtSWFaults.h (revision e44aad7a9d5fa48aeaa55c65bd28ad9acde6ce05) @@ -0,0 +1,133 @@ +/************************************************************************** +* +* Copyright (c) 2019-2020 Diality Inc. - All Rights Reserved. +* +* THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, IN PART OR IN +* WHOLE, WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. +* +* @file AlarmMgmt.h +* +* @author (last) Quang Nguyen +* @date (last) 24-Aug-2020 +* +* @author (original) Sean +* @date (original) 04-Feb-2020 +* +***************************************************************************/ + +#ifndef __ALARM_MGMT_SW_FAULTS_H__ +#define __ALARM_MGMT_SW_FAULTS_H__ + +/** + * @addtogroup AlarmManagement + * @{ + */ + +// ********** public definitions ********** + +// Listing of specific software faults for logging purposes. +typedef enum +{ + SW_FAULT_ID_NONE = 0, + SW_FAULT_ID_INT_ADC_DATA_OVERRUN, + SW_FAULT_ID_INT_ADC_INVALID_CHANNEL_REQUESTED, + SW_FAULT_ID_MODE_INIT_POST_INVALID_POST_STATE, + SW_FAULT_ID_OP_MODES_ILLEGAL_MODE_TRANSITION_REQUESTED, + SW_FAULT_ID_OP_MODES_INVALID_MODE_STATE, // 5 + SW_FAULT_ID_OP_MODES_INVALID_MODE_REQUESTED, + SW_FAULT_ID_OP_MODES_INVALID_MODE_TO_TRANSITION_TO, + SW_FAULT_ID_ALARM_MGMT_INVALID_ALARM_TO_ACTIVATE, + SW_FAULT_ID_ALARM_MGMT_INVALID_ALARM_TO_CLEAR, + SW_FAULT_ID_COMM_BUFFERS_ADD_TOO_MUCH_DATA, // 10 + SW_FAULT_ID_COMM_BUFFERS_ADD_INVALID_BUFFER, + SW_FAULT_ID_COMM_BUFFERS_GET_INVALID_BUFFER, + SW_FAULT_ID_COMM_BUFFERS_PEEK_INVALID_BUFFER, + SW_FAULT_ID_COMM_BUFFERS_COUNT_INVALID_BUFFER, + SW_FAULT_ID_FPGA_INVALID_IN_STATE, // 15 + SW_FAULT_ID_FPGA_INVALID_OUT_STATE, + SW_FAULT_ID_FPGA_WRITE_CMD_TOO_MUCH_DATA, + SW_FAULT_ID_FPGA_WRITE_RSP_TOO_MUCH_DATA, + SW_FAULT_ID_FPGA_READ_CMD_TOO_MUCH_DATA, + SW_FAULT_ID_FPGA_READ_RSP_TOO_MUCH_DATA, // 20 + SW_FAULT_ID_MSG_QUEUES_ADD_QUEUE_FULL, + SW_FAULT_ID_MSG_QUEUES_ADD_INVALID_QUEUE, + SW_FAULT_ID_MSG_QUEUES_GET_INVALID_QUEUE, + SW_FAULT_ID_MSG_QUEUES_IS_EMPTY_INVALID_QUEUE, + SW_FAULT_ID_MSG_QUEUES_IS_FULL_INVALID_QUEUE, // 25 + SW_FAULT_ID_WATCHDOG_INVALID_SELF_TEST_STATE, + SW_FAULT_ID_RTC_EXEC_INVALID_STATE, + SW_FAULT_ID_RTC_SELF_TEST_INVALID_STATE, + SW_FAULT_ID_RTC_TRANSACTION_SERVICE_INVALID_STATE, + SW_FAULT_ID_MSG_PENDING_ACK_LIST_FULL, // 30 + SW_FAULT_ID_PI_CTRL_INVALID_CONTROLLER, + SW_FAULT_ID_PI_CTRL_INVALID_SIGNAL, + SW_FAULT_ID_NVDATAMGMT_EXEC_INVALID_STATE, + SW_FAULT_ID_NVDATAMGMT_INVALID_SELF_TEST_STATE, + SW_FAULT_ID_TEMPERATURE_SENSORS_INVALID_SELF_TEST_STATE, // 35 + SW_FAULT_ID_TEMPERATURE_SENSORS_EXEC_INVALID_STATE, + SW_FAULT_ID_HEATERS_SELF_TEST_INVALID_STATE, + SW_FAULT_ID_HEATERS_PRIMARY_HEATER_EXEC_INVALID_STATE, + SW_FAULT_ID_HEATERS_TRIMMER_HEATER_EXEC_INVALID_STATE, + SW_FAULT_ID_VALVES_INVALID_VALVE_STATE_NAME, // 40 + SW_FAULT_ID_VALVES_INVALID_VALVE_ID, + SW_FAULT_ID_CAN_PARITY_ERROR, + SW_FAULT_ID_CAN_PASSIVE_WARNING, + SW_FAULT_ID_CAN_OFF_ERROR, + SW_FAULT_ID_FPGA_UART_FRAME_ERROR, // 45 + SW_FAULT_ID_FPGA_UART_OVERRUN_ERROR, + SW_FAULT_ID_UTIL_TIME_WINDOWED_COUNT_ERROR, + SW_FAULT_ID_ACCEL_INVALID_STATE, + SW_FAULT_ID_ACCEL_GET_INVALID_AXIS, + SW_FAULT_ID_ACCEL_GET_MAX_INVALID_AXIS, // 50 + SW_FAULT_ID_ACCEL_INVALID_SELF_TEST_STATE, + SW_FAULT_ID_UTIL_INVALID_WIN_COUNT, + SW_FAULT_ID_UTIL_INVALID_WIN_MAX_COUNT, + SW_FAULT_ID_PERSISTENT_ALARM_INVALID_INDEX, + SW_FAULT_ID_CONCENTRATE_PUMP_EXEC_INVALID_STATE, // 55 + SW_FAULT_ID_CONCENTRATE_PUMP_INVALID_PUMP_ID, + SW_FAULT_ID_CONCENTRATE_PUMP_SPEED_OUT_OF_RANGE, + SW_FAULT_ID_UV_REACTORS_INVALID_EXEC_STATE, + SW_FAULT_ID_UV_REACTORS_INVALID_SELF_TEST_STATE, + SW_FAULT_ID_THERMISTORS_INVALID_EXEC_STATE, // 60 + SW_FAULT_ID_THERMISTORS_INVALID_SELF_TEST_STATE, + SW_FAULT_ID_INVALID_THERMISTOR_SELECTED, + SW_FAULT_ID_FAN_INVALID_EXEC_STATE, + SW_FAULT_ID_FAN_INVALID_SELF_TEST_STATE, + SW_FAULT_ID_INVALID_FAN_SELECTED, // 65 + SW_FAULT_ID_RO_PUMP_INVALID_EXEC_STATE, + SW_FAULT_ID_RO_PUMP_INVALID_FLOW_RATE_SET, + SW_FAULT_ID_DRAIN_PUMP_INVALID_EXEC_STATE, + SW_FAULT_ID_UV_REACTORS_INVALID_REACTOR_SELECTD, + SW_FAULT_ID_RO_PUMP_INVALID_PRESSURE_SELECTED, // 70 + SW_FAULT_ID_DRAIN_PUMP_INVALID_DELTA_PRESSURE_SELECTED, + 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 + SW_FAULT_ID_HEAT_DISINFECT_INVALID_EXEC_STATE, + SW_FAULT_ID_INVALID_DG_RESERVOIR_SELECTED, + SW_FAULT_ID_STANDBY_MODE_INVALID_EXEC_STATE, + SW_FAULT_ID_RECIRC_MODE_INVALID_EXEC_STATE, + SW_FAULT_ID_DRAIN_MODE_INVALID_EXEC_STATE, // 80 + SW_FAULT_ID_FILL_MODE_INVALID_EXEC_STATE, + SW_FAULT_ID_SOLO_MODE_INVALID_EXEC_STATE, + SW_FAULT_ID_PRESSURE_INVALID_EXEC_STATE, + SW_FAULT_ID_INVALID_NVDATAMGMT_EXEC_CAL_STATE, + SW_FAULT_ID_INVALID_VALVE_ID, // 85 + SW_FAULT_ID_INVALID_INT_ADC_CHANNEL_NUMBER, + SW_FAULT_ID_INVALID_RTI_NOTIFICATION, + SW_FAULT_ID_CAN_TX_FAULT, + SW_FAULT_ID_INVALID_CAN_MESSAGE_SIZE, + SW_FAULT_ID_INVALID_CONDUCTIVITY_SENSOR_ID, // 90 + SW_FAULT_ID_INVALID_PRESSURE_SENSOR_ID, + SW_FAULT_ID_INVALID_TASK, + SW_FAULT_ID_INVALID_VOLTAGE_MONITOR_STATE, + SW_FAULT_ID_INVALID_MONITORED_VOLTAGE_ID, + SW_FAULT_ID_INVALID_LOAD_CELL_ID, // 95 + SW_FAULT_ID_DG_CHEM_DISINFECT_INVALID_EXEC_STATE, + NUM_OF_SW_FAULT_IDS +} SW_FAULT_ID_T; + +/**@}*/ + +#endif Index: firmware/App/Services/FPGA.c =================================================================== diff -u -r5a36a768d11cc597a36b894c1fb3a5e5590130f1 -re44aad7a9d5fa48aeaa55c65bd28ad9acde6ce05 --- firmware/App/Services/FPGA.c (.../FPGA.c) (revision 5a36a768d11cc597a36b894c1fb3a5e5590130f1) +++ firmware/App/Services/FPGA.c (.../FPGA.c) (revision e44aad7a9d5fa48aeaa55c65bd28ad9acde6ce05) @@ -1562,6 +1562,19 @@ /*********************************************************************//** * @brief + * The getFPGAConcentratePumpsFault function gets concentrate pumps fault + * reported by FGPA. + * @details Inputs: fpgaSensorReadings.fpgaCP1CP2Fault + * @details Outputs: none + * @return Latest concentrate pumps fault value + *************************************************************************/ +U08 getFPGAConcentratePumpsFault( void ) +{ + return fpgaSensorReadings.fpgaCP1CP2Fault; +} + +/*********************************************************************//** + * @brief * The getFPGAEmstatOutByte function gets Emstat conductivity sensor output byte. * @details Inputs: fpgaSensorReadings.fpgaEmstatOutByte * @details Outputs: none Index: firmware/App/Services/FPGA.h =================================================================== diff -u -r5a36a768d11cc597a36b894c1fb3a5e5590130f1 -re44aad7a9d5fa48aeaa55c65bd28ad9acde6ce05 --- firmware/App/Services/FPGA.h (.../FPGA.h) (revision 5a36a768d11cc597a36b894c1fb3a5e5590130f1) +++ firmware/App/Services/FPGA.h (.../FPGA.h) (revision e44aad7a9d5fa48aeaa55c65bd28ad9acde6ce05) @@ -101,6 +101,8 @@ U08 getFPGACPoErrorCount( void ); U32 getFPGACPo( void ); +U08 getFPGAConcentratePumpsFault( void ); + U08 getFPGAEmstatOutByte( void ); U08 getFPGAEmstatRxErrCount( void ); U16 getFPGAEmstatRxFifoCount( void ); Index: firmware/App/Services/SystemComm.c =================================================================== diff -u -r5a36a768d11cc597a36b894c1fb3a5e5590130f1 -re44aad7a9d5fa48aeaa55c65bd28ad9acde6ce05 --- firmware/App/Services/SystemComm.c (.../SystemComm.c) (revision 5a36a768d11cc597a36b894c1fb3a5e5590130f1) +++ firmware/App/Services/SystemComm.c (.../SystemComm.c) (revision e44aad7a9d5fa48aeaa55c65bd28ad9acde6ce05) @@ -1045,6 +1045,10 @@ handleStartStopDGHeatDisinfect( message ); break; + case MSG_ID_DG_START_STOP_CHEM_DISINFECT: + handleStartStopDGChemicalDisinfect( message ); + break; + case MSG_ID_UI_DG_SET_RTC_REQUEST: handleUIClockSyncRequest( message ); break; @@ -1197,6 +1201,7 @@ case MSG_ID_DG_FANS_DATA_PUBLISH_INTERVAL_OVERRIDE: handleTestFansDataPublishIntervalOverride( message ); + break; case MSG_ID_DG_RO_PUMP_DUTY_CYCLE_OVERRIDE: handleTestROPumpDutyCycleOverride( message ); Index: firmware/App/Services/SystemCommMessages.c =================================================================== diff -u -r5a36a768d11cc597a36b894c1fb3a5e5590130f1 -re44aad7a9d5fa48aeaa55c65bd28ad9acde6ce05 --- firmware/App/Services/SystemCommMessages.c (.../SystemCommMessages.c) (revision 5a36a768d11cc597a36b894c1fb3a5e5590130f1) +++ firmware/App/Services/SystemCommMessages.c (.../SystemCommMessages.c) (revision e44aad7a9d5fa48aeaa55c65bd28ad9acde6ce05) @@ -26,6 +26,7 @@ #include "FPGA.h" #include "Heaters.h" #include "LoadCell.h" +#include "ModeChemicalDisinfect.h" #include "ModeFlush.h" #include "ModeStandby.h" #include "ModeRecirculate.h" @@ -1051,8 +1052,8 @@ return result; } - /*********************************************************************//** - * @brief +/*********************************************************************//** + * @brief * The broadcastFlushData function sends out the flush mode data. * @details Inputs: none * @details Outputs: flush data msg constructed and queued @@ -1080,6 +1081,34 @@ /*********************************************************************//** * @brief + * The broadcastChemicalDisinfectData function sends out the chemical + * disinfect mode data. + * @details Inputs: none + * @details Outputs: chemical disinfect data msg constructed and queued + * @param chemDisinfectData which is flush msg constructed and queued + * @return TRUE if msg successfully queued for transmit, FALSE if not + *************************************************************************/ +BOOL broadcastChemicalDisinfectData( MODE_CHEMICAL_DISINFECT_DATA_T *chemDisinfectData ) +{ + BOOL result; + MESSAGE_T msg; + U08 *payloadPtr = msg.payload; + + // create a message record + blankMessage( &msg ); + msg.hdr.msgID = MSG_ID_DG_CHEM_DISINFECT_DATA; + msg.hdr.payloadLen = sizeof( MODE_CHEMICAL_DISINFECT_DATA_T ); + + memcpy( payloadPtr, chemDisinfectData, sizeof( MODE_CHEMICAL_DISINFECT_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 sendDGSystemRecord function sends out the DG system record. * @details Inputs: none * @details Outputs: DG system record msg constructed and queued @@ -2503,7 +2532,7 @@ memcpy( &payload, message->payload, sizeof(TEST_OVERRIDE_ARRAY_PAYLOAD_T) ); if ( FALSE == payload.reset ) { - result = testSetUVReactorHealthOverride( payload.index, (BOOL)payload.state.u32 ); + result = testSetUVReactorHealthOverride( payload.index, payload.state.u32 ); } else { @@ -2558,13 +2587,13 @@ *************************************************************************/ void handleSetFluidLeakStateDetectorOverrideRequest( MESSAGE_T *message ) { - TEST_OVERRIDE_ARRAY_PAYLOAD_T payload; + TEST_OVERRIDE_PAYLOAD_T payload; BOOL result = FALSE; // Verify payload length - if ( sizeof( TEST_OVERRIDE_ARRAY_PAYLOAD_T ) == message->hdr.payloadLen ) + if ( sizeof( TEST_OVERRIDE_PAYLOAD_T ) == message->hdr.payloadLen ) { - memcpy( &payload, message->payload, sizeof( TEST_OVERRIDE_ARRAY_PAYLOAD_T ) ); + memcpy( &payload, message->payload, sizeof( TEST_OVERRIDE_PAYLOAD_T ) ); if ( FALSE == payload.reset ) { result = testSetFluidLeakStateOverride( ( FLUID_LEAK_STATES_T)( payload.state.u32 ) ); @@ -2934,7 +2963,7 @@ /************************************************************************* * @brief * The handleStartStopDGHeatDisinfect function handles a request start or - * stop DG heat disifect cycle. + * stop DG heat disifect mode. * @details Inputs: none * @details Outputs: message handled * @param message: a pointer to the message to handle @@ -3044,8 +3073,8 @@ /*********************************************************************//** * @brief -* The handleStartStopDGFlush function handles a request to override start -* or stop DG flush mode. +* The handleStartStopDGFlush function handles a request to start or stop +* DG flush mode. * @details Inputs: none * @details Outputs: message handled * @param message a pointer to the message to handle @@ -3282,6 +3311,41 @@ } /*********************************************************************//** +* @brief +* The handleStartStopDGChemicalDisinfect function handles a request to start +* or stop DG chemical disinfect mode. +* @details Inputs: none +* @details Outputs: message handled +* @param message a pointer to the message to handle +* @return none +*************************************************************************/ +BOOL handleStartStopDGChemicalDisinfect( MESSAGE_T *message ) +{ + BOOL result = FALSE; + + if ( message->hdr.payloadLen == sizeof(U32) ) + { + BOOL startingDGChemicalDisinfect; + + memcpy( &startingDGChemicalDisinfect, message->payload, sizeof(U32) ); + + if ( TRUE == startingDGChemicalDisinfect ) + { + result = startDGChemicalDisinfect(); + } + else + { + result = stopChemicalDisinfect(); + } + } + + // Respond to request + sendAckResponseMsg( (MSG_ID_T)message->hdr.msgID, COMM_BUFFER_OUT_CAN_DG_2_HD, result ); + + return result; +} + +/*********************************************************************//** * @brief * The handleFilterFlushTimePeriodOverride function handles a request * to override the filter flush time period value. Index: firmware/App/Services/SystemCommMessages.h =================================================================== diff -u -r5a36a768d11cc597a36b894c1fb3a5e5590130f1 -re44aad7a9d5fa48aeaa55c65bd28ad9acde6ce05 --- firmware/App/Services/SystemCommMessages.h (.../SystemCommMessages.h) (revision 5a36a768d11cc597a36b894c1fb3a5e5590130f1) +++ firmware/App/Services/SystemCommMessages.h (.../SystemCommMessages.h) (revision e44aad7a9d5fa48aeaa55c65bd28ad9acde6ce05) @@ -23,6 +23,7 @@ #include "Fans.h" #include "FluidLeak.h" #include "Heaters.h" +#include "ModeChemicalDisinfect.h" #include "ModeFlush.h" #include "ModeHeatDisinfect.h" #include "MsgQueues.h" @@ -112,12 +113,18 @@ // 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_VOLTAGES_DATA BOOL broadcastVoltagesData( VOLTAGES_DATA_PAYLOAD_T data ); -// MSG_ID_DG_FLUSH_DATA -BOOL broadcastFlushData( MODE_FLUSH_DATA_T *flushData ); +// MSG_ID_DG_CHEM_DISINFECT_DATA +BOOL broadcastChemicalDisinfectData( MODE_CHEMICAL_DISINFECT_DATA_T *chemDisinfectData ); +// MSG_ID_DG_VOLTAGES_DATA +BOOL broadcastVoltagesData( VOLTAGES_DATA_PAYLOAD_T data ); + // MSG_ID_DG_COMMAND_RESPONSE void sendCommandResponseMsg( DG_CMD_RESPONSE_T *cmdResponsePtr ); @@ -354,6 +361,9 @@ // MSG_ID_DG_SET_SCHEDULED_RUNS_RECORD void handleSetDGScheduledRunsRecord( MESSAGE_T *message ); +// MSG_ID_DG_START_STOP_CHEM_DSINFECT +BOOL handleStartStopDGChemicalDisinfect( MESSAGE_T *message ); + // MSG_ID_FILTER_FLUSH_TIME_PERIOD_OVERRIDE void handleFilterFlushTimePeriodOverride( MESSAGE_T *message ); Index: firmware/source/sys_main.c =================================================================== diff -u -r1ecf1a6011246450a43592b77d0e78780f91bdde -re44aad7a9d5fa48aeaa55c65bd28ad9acde6ce05 --- firmware/source/sys_main.c (.../sys_main.c) (revision 1ecf1a6011246450a43592b77d0e78780f91bdde) +++ firmware/source/sys_main.c (.../sys_main.c) (revision e44aad7a9d5fa48aeaa55c65bd28ad9acde6ce05) @@ -56,6 +56,7 @@ #include "can.h" #include "etpwm.h" #include "gio.h" +#include "het.h" #include "mibspi.h" #include "sci.h" #include "rti.h" @@ -141,6 +142,7 @@ static void initProcessor( void ) { gioInit(); // configure GPIO pins + hetInit(); // Configure HET1 adcInit(); // configure internal ADC channels mibspiInit(); // configure MIBSPI3 and re-purpose MIBSPI1 & 5 pins for GPIO etpwmInit(); // configure PWMs