Index: firmware/App/Controllers/Heaters.c =================================================================== diff -u -rab14e70c7bac24b0c3ebd02c6763285cdd3951ce -rbcb768dd6a13286e028533394916a9f69c9f254f --- firmware/App/Controllers/Heaters.c (.../Heaters.c) (revision ab14e70c7bac24b0c3ebd02c6763285cdd3951ce) +++ firmware/App/Controllers/Heaters.c (.../Heaters.c) (revision bcb768dd6a13286e028533394916a9f69c9f254f) @@ -59,7 +59,7 @@ #define HEATERS_MAX_ALLOWED_INTERNAL_TEMPERATURE_C 170.0F ///< Heaters max allowed internal temperature in C. #define HEATERS_MAX_ALLOWED_COLD_JUNCTION_TEMPERATURE_C 80.0F ///< Heaters max allowed cold junction temperature in C. #define HEATERS_MAX_ALLOWED_INTERNAL_TEMPERATURE_TIMEOUT_MS ( 2 * SEC_PER_MIN * MS_PER_SECOND ) ///< Heaters max allowed internal temperature timeout in milliseconds. -#define HEATERS_ON_NO_FLOW_TIMEOUT_MS ( 2 * MS_PER_SECOND ) ///< Heaters on with no flow time out in milliseconds. +#define HEATERS_ON_NO_FLOW_TIMEOUT_MS ( 1 * MS_PER_SECOND ) ///< Heaters on with no flow time out in milliseconds. #define HEATERS_MAX_OPERATING_VOLTAGE_V 24.0F ///< Heaters max operating voltage in volts. #define HEATERS_VOLTAGE_MONITOR_TIME_INTERVAL ( MS_PER_SECOND / TASK_PRIORITY_INTERVAL ) ///< Heaters voltage monitor timer interval. #define HEATERS_MAX_VOLTAGE_OUT_OF_RANGE_TOL 0.2F ///< Heaters max voltage out of range tolerance. @@ -363,10 +363,8 @@ for ( heater = DG_PRIMARY_HEATER; heater < NUM_OF_DG_HEATERS; heater++ ) { - F32 maxDutyCycle = MAX( heatersStatus[ heater ].dutyCyleBeforeFlow, heatersStatus[ heater ].dutycycle ); - - // Check if a heater is on and whether is duty cycle is not zero - if ( ( TRUE == heatersStatus[ heater ].isHeaterOn ) && ( maxDutyCycle > NEARLY_ZERO ) ) + // Check if the heater is on and if it is, check the flow sensor's status + if ( TRUE == heatersStatus[ heater ].isHeaterOn ) { // TODO add the function that gets the flow of the new flow sensor for DG. For now it is assumed that trimmer heater flow sensor // is not 0 so the heater can run if needed @@ -380,29 +378,26 @@ // Check if the flow of the heater is below minimum for the first time if ( FALSE == heatersStatus[ heater ].isFlowBelowMin ) { + // Set the variables for the flow below minimum situation. + // Remember the current duty cycle of the heater heatersStatus[ heater ].isFlowBelowMin = TRUE; heatersStatus[ heater ].heaterOnWithNoFlowTimer = getMSTimerCount(); heatersStatus[ heater ].dutyCyleBeforeFlow = heatersStatus[ heater ].dutycycle; } else if ( TRUE == didTimeout( heatersStatus[ heater ].heaterOnWithNoFlowTimer, HEATERS_ON_NO_FLOW_TIMEOUT_MS ) ) { + // The flow is below minimum for a certain period of time so set the heater's duty cycle to 0. The heaters is not + // set to off and its duty cycle is set to 0 setHeaterDutyCycle( heater, HEATERS_MIN_DUTY_CYCLE ); - - /*ALARM_ID_T alarm = ( DG_PRIMARY_HEATER == heater ? ALARM_ID_DG_PRIMARY_HEATER_ON_WITH_NO_FLOW_TIMEOUT : - ALARM_ID_DG_TRIMMER_HEATER_ON_WITH_NO_FLOW_TIMEOUT ); - activateAlarmNoData( alarm ); TODO DEBUG_DENALI*/ } } else { - if ( TRUE == heatersStatus[ heater ].isFlowBelowMin ) - { - setHeaterDutyCycle( heater, heatersStatus[ heater ].dutyCyleBeforeFlow ); - } - heatersStatus[ heater ].isFlowBelowMin = FALSE; heatersStatus[ heater ].heaterOnWithNoFlowTimer = getMSTimerCount(); + // Flow is back on, set the heater to the duty cycle that was saved before zeroing the heater + setHeaterDutyCycle( heater, heatersStatus[ heater ].dutyCyleBeforeFlow ); } } } @@ -643,17 +638,37 @@ *************************************************************************/ static void setHeaterDutyCycle( DG_HEATERS_T heater, F32 pwm ) { - if ( DG_PRIMARY_HEATER == heater ) + // Only if there is a minimum flow, or if 0 duty cycle has been requested, the duty cycle can be changed + // This is to make sure while heaters are temporarily turned off due to a flow drop are not set to another + // duty cycle that might cause an over heat since there is no water flowing through + if ( ( FALSE == heatersStatus[ heater ].isFlowBelowMin ) || ( pwm < NEARLY_ZERO ) ) { - setMainPrimaryHeaterPWM( pwm ); - setSmallPrimaryHeaterPWM( pwm ); + // Check if the requested duty cycle is different from what the heater's duty cycle is. + // If the same duty cycle is requested, then it is not needed to send it again. This is to make sure + // the same duty cycle is not sent to the hardware all the time. + if ( fabs( heatersStatus[ heater ].dutycycle - pwm ) > NEARLY_ZERO ) + { + if ( DG_PRIMARY_HEATER == heater ) + { + setMainPrimaryHeaterPWM( pwm ); + setSmallPrimaryHeaterPWM( pwm ); + } + else if ( DG_TRIMMER_HEATER == heater ) + { + setTrimmerHeaterPWM( pwm ); + } + + // Updated the heater's information + heatersStatus[ heater ].dutycycle = pwm; + } } - else if ( DG_TRIMMER_HEATER == heater ) + else { - setTrimmerHeaterPWM( pwm ); + // The flow is below minimum and the heater is temporarily powered down + // Update the other duty cycle with the requested duty cycle so as soon as the + // flow is back on, the new duty cycle is set + heatersStatus[ heater ].dutyCyleBeforeFlow = pwm; } - - heatersStatus[ heater ].dutycycle = pwm; } /*********************************************************************//** @@ -861,6 +876,7 @@ { if ( ++voltageMonitorTimeCounter >= HEATERS_VOLTAGE_MONITOR_TIME_INTERVAL ) { + // TODO the voltages are disabled for now until they are implemented into the persistent alarms. F32 mainPriVoltage = getIntADCVoltageConverted( INT_ADC_PRIMARY_HEATER_24_VOLTS ); // TODO it is assumed that the main and small primary heaters have equal voltage since the PWMs are divided into 2 // before applying the PWMs to the heaters. Right now, there is no ADC channel available for the small primary @@ -877,17 +893,17 @@ // The corresponding voltage of the current PWM must be close to the sensed voltage if ( fabs( ( HEATERS_MAX_OPERATING_VOLTAGE_V * mainPri ) - mainPriVoltage ) > HEATERS_MAX_VOLTAGE_OUT_OF_RANGE_TOL * mainPriVoltage ) { - SET_ALARM_WITH_1_F32_DATA( ALARM_ID_DG_MAIN_PRIMARY_HEATER_VOLTAGE_OUT_OF_RANGE, mainPriVoltage ); + //SET_ALARM_WITH_1_F32_DATA( ALARM_ID_DG_MAIN_PRIMARY_HEATER_VOLTAGE_OUT_OF_RANGE, mainPriVoltage ); } // Check small primary heater's voltage if ( fabs( ( HEATERS_MAX_OPERATING_VOLTAGE_V * smallPri ) - smallPriVoltage ) > HEATERS_MAX_VOLTAGE_OUT_OF_RANGE_TOL * smallPriVoltage ) { - SET_ALARM_WITH_1_F32_DATA( ALARM_ID_DG_SMALL_PRIMARY_HEATER_VOLTAGE_OUT_OF_RANGE, smallPriVoltage ); + //SET_ALARM_WITH_1_F32_DATA( ALARM_ID_DG_SMALL_PRIMARY_HEATER_VOLTAGE_OUT_OF_RANGE, smallPriVoltage ); } // Check trimmer heater's voltage if ( fabs( ( HEATERS_MAX_OPERATING_VOLTAGE_V * trimmer ) - trimmerVoltage ) > HEATERS_MAX_VOLTAGE_OUT_OF_RANGE_TOL * trimmerVoltage ) { - //SET_ALARM_WITH_1_F32_DATA( ALARM_ID_DG_TRIMMER_HEATER_VOLTAGE_OUT_OF_RANGE, trimmerVoltage ); // TODO DEBUG_DENALI + //SET_ALARM_WITH_1_F32_DATA( ALARM_ID_DG_TRIMMER_HEATER_VOLTAGE_OUT_OF_RANGE, trimmerVoltage ); } voltageMonitorTimeCounter = 0; @@ -916,7 +932,7 @@ { U32 interval = value / TASK_PRIORITY_INTERVAL; - result = TRUE; + result = TRUE; heatersDataPublishInterval.ovData = interval; heatersDataPublishInterval.override = OVERRIDE_KEY; } @@ -938,7 +954,7 @@ if ( TRUE == isTestingActivated() ) { - result = TRUE; + result = TRUE; heatersDataPublishInterval.override = OVERRIDE_RESET; heatersDataPublishInterval.ovData = heatersDataPublishInterval.ovInitData; } Index: firmware/App/Controllers/LoadCell.c =================================================================== diff -u -rab14e70c7bac24b0c3ebd02c6763285cdd3951ce -rbcb768dd6a13286e028533394916a9f69c9f254f --- firmware/App/Controllers/LoadCell.c (.../LoadCell.c) (revision ab14e70c7bac24b0c3ebd02c6763285cdd3951ce) +++ firmware/App/Controllers/LoadCell.c (.../LoadCell.c) (revision bcb768dd6a13286e028533394916a9f69c9f254f) @@ -173,7 +173,7 @@ b2 = ( b2 >> 31 ); if ( TRUE == isPersistentAlarmTriggered( ALARM_ID_DG_LOAD_CELL_ADC_ERROR, ( ( a1 > 0 ) || ( a2 > 0 ) || ( b1 > 0 ) || ( b2 > 0 ) ) ) ) { - //SET_ALARM_WITH_1_U32_DATA( ALARM_ID_DG_LOAD_CELL_ADC_ERROR, ( a1 | a2 | b1 | b2 ) ) // TODO DEBUG_DENALI + SET_ALARM_WITH_1_U32_DATA( ALARM_ID_DG_LOAD_CELL_ADC_ERROR, ( a1 | a2 | b1 | b2 ) ) } // TODO use ALARM_ID_DG_LOAD_CELL_FPGA_READ_ERROR for read error Index: firmware/App/Controllers/ROPump.c =================================================================== diff -u -rab14e70c7bac24b0c3ebd02c6763285cdd3951ce -rbcb768dd6a13286e028533394916a9f69c9f254f --- firmware/App/Controllers/ROPump.c (.../ROPump.c) (revision ab14e70c7bac24b0c3ebd02c6763285cdd3951ce) +++ firmware/App/Controllers/ROPump.c (.../ROPump.c) (revision bcb768dd6a13286e028533394916a9f69c9f254f) @@ -415,7 +415,7 @@ // Check whether the Duty cycle is out of range BOOL isDCOutOfRange = ( fabs( roPumpFeedbackDutyCyclePct - roPumpDutyCyclePctSet ) > ROP_DUTY_CYCLE_OUT_OF_RANGE_TOLERANCE ? TRUE : FALSE ); - /* TODO this is commented until the DVT boards are available + /* TODO this is commented out until the DVT boards are available checkPersistentAlarm( ALARM_ID_RO_PUMP_DUTY_CYCLE_OUT_OF_RANGE, isDCOutOfRange, roPumpFeedbackDutyCyclePct, roPumpDutyCyclePctSet ); // Check if it the alarm has timed out and if the pump is supposed to be off but it is still on, activate the safety shutdown Index: firmware/App/Controllers/UVReactors.c =================================================================== diff -u -r55a8b1f7f4e8a8eaf6dc83f0d5fcf0a3e36a7027 -rbcb768dd6a13286e028533394916a9f69c9f254f --- firmware/App/Controllers/UVReactors.c (.../UVReactors.c) (revision 55a8b1f7f4e8a8eaf6dc83f0d5fcf0a3e36a7027) +++ firmware/App/Controllers/UVReactors.c (.../UVReactors.c) (revision bcb768dd6a13286e028533394916a9f69c9f254f) @@ -34,42 +34,45 @@ // ********** private definitions ********** -#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 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. -#define SELF_TEST_DELAY_TIME 1000 -#define MAX_ALLOWED_UNHEALTHY_REACTOR_PERIOD MS_PER_SECOND ///< UV reactors unhealthy state period. -#define DATA_PUBLISH_COUNTER_START_COUNT 90 ///< Data publish counter start count. +#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 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. +#define SELF_TEST_DELAY_TIME 1000 ///< Self test wait time after enabling the reactors and before checking for their health in ms. +#define MAX_ALLOWED_UNHEALTHY_REACTOR_PERIOD MS_PER_SECOND ///< UV reactors unhealthy state period. +#define DATA_PUBLISH_COUNTER_START_COUNT 90 ///< Data publish counter start count. +#define UV_REACTORS_ON_NO_FLOW_TIMEOUT_MS ( 1 * MS_PER_SECOND ) ///< UV reactors on with no flow time out in milliseconds. + /// UV reactors self test states typedef enum self_tests { - UV_REACTORS_SELF_TEST_OFF = 0, ///< UV reactors self test state off - UV_REACTORS_SELF_TEST_CHECK_HEALTH, ///< UV reactors self test check health - UV_REACTORS_SELF_TEST_COMPLETE, ///< UV reactors self test complete - NUM_OF_UV_REACTORS_SELF_TEST_STATES, ///< Number of UV reactors self test states + UV_REACTORS_SELF_TEST_OFF = 0, ///< UV reactors self test state off. + UV_REACTORS_SELF_TEST_CHECK_HEALTH, ///< UV reactors self test check health. + UV_REACTORS_SELF_TEST_COMPLETE, ///< UV reactors self test complete. + NUM_OF_UV_REACTORS_SELF_TEST_STATES, ///< Number of UV reactors self test states. } UV_REACTORS_SELF_TEST_STATE_T; /// UV reactors exec states typedef enum exec_states { - UV_REACTOR_STATE_OFF = 0, ///< UV reactor state off - UV_REACTOR_STATE_ON, ///< UV reactor state on - NUM_OF_UV_REACTOR_STATES, ///< Number of UV reactor states + UV_REACTOR_STATE_OFF = 0, ///< UV reactor state off. + UV_REACTOR_STATE_ON, ///< UV reactor state on. + NUM_OF_UV_REACTOR_STATES, ///< Number of UV reactor states. } UV_REACTOR_STATE_T; /// UV reactor status typedef struct { - UV_REACTOR_STATE_T execState; ///< UV reactor executive state - PIN_SIGNAL_STATE_T pinSignalState; ///< UV reactor pin signal state - UV_REACTOR_STATES_T switchState; ///< UV reactor turn on/turn off state - U32 reactorEnablePin; ///< UV reactor enable pin of GIO port A - U32 reactorHealthStatusPin; ///< UV reactor status pin of N2HET1 - OVERRIDE_U32_T healthStatus; ///< UV reactor current health status + UV_REACTOR_STATE_T execState; ///< UV reactor executive state. + PIN_SIGNAL_STATE_T pinSignalState; ///< UV reactor pin signal state. + UV_REACTOR_STATES_T switchState; ///< UV reactor turn on/turn off state. + U32 reactorEnablePin; ///< UV reactor enable pin of GIO port A. + U32 reactorHealthStatusPin; ///< UV reactor status pin of N2HET1. + OVERRIDE_U32_T healthStatus; ///< UV reactor current health status. + BOOL isFlowBelowMin; ///< UV reactor flag to indicate the flow is below minimum. + U32 reactorOnWithNoFlowTimer; ///< UV reactor on with no flow start time. } UV_REACTOR_STATUS_T; // ********** private data ********** @@ -129,6 +132,7 @@ reactorsStatus[ reactor ].pinSignalState = PIN_SIGNAL_LOW; reactorsStatus[ reactor ].execState = UV_REACTOR_STATE_OFF; reactorsStatus[ reactor ].switchState = TURN_OFF; + setReactorEnableStatus( reactor, PIN_SIGNAL_LOW ); } @@ -363,17 +367,22 @@ { 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; + // 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 + // Check if the a reactor is requested to be on and it is off if ( TURN_ON == reactorsStatus[ reactor ].switchState ) { - setReactorEnableStatus( reactor, PIN_SIGNAL_HIGH ); + // Check if the flow is below minimum + reactorsStatus[ reactor ].isFlowBelowMin = ( getMeasuredROFlowRateLPM() < MIN_RO_FLOWRATE_LPM ? TRUE : FALSE ); - state = UV_REACTOR_STATE_ON; + // If the flow is no longer below minimum and the reactor is requested to be on, turn it back on + if ( FALSE == reactorsStatus[ reactor ].isFlowBelowMin ) + { + setReactorEnableStatus( reactor, PIN_SIGNAL_HIGH ); + + state = UV_REACTOR_STATE_ON; + } } return state; @@ -408,6 +417,27 @@ } } + // Check if the flow is below minimum + BOOL isFlowBelowMin = ( getMeasuredROFlowRateLPM() < MIN_RO_FLOWRATE_LPM ? TRUE : FALSE ); + + if ( TRUE == isFlowBelowMin ) + { + // If the flow is below minimum for the first time, start the timer + if ( FALSE == reactorsStatus[ reactor ].isFlowBelowMin ) + { + reactorsStatus[ reactor ].isFlowBelowMin = TRUE; + reactorsStatus[ reactor ].reactorOnWithNoFlowTimer = getMSTimerCount(); + } + else if ( TRUE == didTimeout( reactorsStatus[ reactor ].reactorOnWithNoFlowTimer, UV_REACTORS_ON_NO_FLOW_TIMEOUT_MS ) ) + { + // If the flow is below minimum and the allowed time has elapsed, set the reactor's signal to be low and set its state + // to be off. + setReactorEnableStatus( reactor, PIN_SIGNAL_LOW ); + // The state is directly changed here because the switch state is not changed to be off + reactorsStatus[ reactor ].execState = UV_REACTOR_STATE_OFF; + } + } + // Check if it has been requested to turn off a reactor if ( TURN_OFF == reactorsStatus[ reactor ].switchState ) { @@ -463,6 +493,7 @@ if ( ++dataPublishCounter > getU32OverrideValue( &uvReactorsDataPublishInterval ) ) { UV_REACTORS_DATA_T uvReactorsData; + // Publish the reactors health status uvReactorsData.inletUVReactorHealthStatus = (U32)getUVReactorHealth( INLET_UV_REACTOR ); uvReactorsData.outletUVReactorHealthStatus = (U32)getUVReactorHealth( OUTLET_UV_REACTOR ); Index: firmware/App/Controllers/Voltages.c =================================================================== diff -u -rab14e70c7bac24b0c3ebd02c6763285cdd3951ce -rbcb768dd6a13286e028533394916a9f69c9f254f --- firmware/App/Controllers/Voltages.c (.../Voltages.c) (revision ab14e70c7bac24b0c3ebd02c6763285cdd3951ce) +++ firmware/App/Controllers/Voltages.c (.../Voltages.c) (revision bcb768dd6a13286e028533394916a9f69c9f254f) @@ -224,14 +224,14 @@ { if ( ++voltageAlarmPersistenceCtr[ i ] > VOLTAGES_ALARM_PERSISTENCE ) { - //SET_ALARM_WITH_2_F32_DATA( ALARM_ID_DG_VOLTAGE_OUT_OF_RANGE, (F32)i, volts ) // TODO DEBUG_DENALI + SET_ALARM_WITH_2_F32_DATA( ALARM_ID_DG_VOLTAGE_OUT_OF_RANGE, (F32)i, volts ) } } else if ( volts < MIN_VOLTAGES[ i ] ) { if ( ++voltageAlarmPersistenceCtr[ i ] > VOLTAGES_ALARM_PERSISTENCE ) { - //SET_ALARM_WITH_2_F32_DATA( ALARM_ID_DG_VOLTAGE_OUT_OF_RANGE, (F32)i, volts ) // TODO DEBUG_DENALI + SET_ALARM_WITH_2_F32_DATA( ALARM_ID_DG_VOLTAGE_OUT_OF_RANGE, (F32)i, volts ) } } else Index: firmware/App/DGCommon.h =================================================================== diff -u -r8fe65bf6222137cc7182ccacff3a5f2fb2f03753 -rbcb768dd6a13286e028533394916a9f69c9f254f --- firmware/App/DGCommon.h (.../DGCommon.h) (revision 8fe65bf6222137cc7182ccacff3a5f2fb2f03753) +++ firmware/App/DGCommon.h (.../DGCommon.h) (revision bcb768dd6a13286e028533394916a9f69c9f254f) @@ -42,7 +42,6 @@ #define DISABLE_RTC_CONFIG 1 // Not needed TODO investigate and remove - #include #include #endif