Index: firmware/App/Controllers/Fans.c =================================================================== diff -u -rddb9707d9e6e46c4b384782aeec20d41f3822996 -r22f1a58ac8e419353ec004b04e7c765c1d59df2b --- firmware/App/Controllers/Fans.c (.../Fans.c) (revision ddb9707d9e6e46c4b384782aeec20d41f3822996) +++ firmware/App/Controllers/Fans.c (.../Fans.c) (revision 22f1a58ac8e419353ec004b04e7c765c1d59df2b) @@ -52,7 +52,7 @@ typedef struct { F32 targetDutyCycle; ///< Fan's target duty cycle that was fed to the fans. - U32 rpm[ NUM_OF_FANS_NAMES ]; ///< Fan's current tachometers reading in RPM. + OVERRIDE_F32_T rpm[ NUM_OF_FANS_NAMES ]; ///< Fan's current tachometers reading in RPM. } FAN_STATUS_T; static FAN_STATUS_T fansStatus; ///< Fans status. @@ -86,14 +86,16 @@ /*********************************************************************//** * @brief * The initFans function initializes the fans module. - * @details Inputs: fansExecState, fansStatus, fansControlCounter, - * fansPublishCounter + * @details Inputs: none * @details Outputs: fansExecState, fansStatus, fansControlCounter, - * fansPublishCounter + * fansPublishCounter, fansMonitorCounter, isPOSTComplete, hasAlarmBeenRaised, + * rpmAlarmStartTimer * @return none *************************************************************************/ void initFans( void ) { + FAN_NAMES_T fan; + // Initialize the variables fansExecState = FANS_EXEC_STATE_WAIT_FOR_POST_STATE; fansControlCounter = 0; @@ -103,6 +105,15 @@ hasAlarmBeenRaised = FALSE; rpmAlarmStartTimer = 0; + // Initialize the fans + for ( fan = FAN_INLET_1; fan < NUM_OF_FANS_NAMES; fan++ ) + { + fansStatus.rpm[ fan ].data = 0.0; + fansStatus.rpm[ fan ].ovData = 0.0; + fansStatus.rpm[ fan ].ovInitData = 0.0; + fansStatus.rpm[ fan ].override = OVERRIDE_RESET; + } + // Initialize a persistent alarm for fans RPM out of range initPersistentAlarm( ALARM_ID_DG_FAN_RPM_OUT_OF_RANGE, FANS_MAX_ALLOWED_RPM_OUT_OF_RANGE_INTERVAL, FANS_MAX_ALLOWED_RPM_OUT_OF_RANGE_INTERVAL ); } @@ -171,12 +182,18 @@ *************************************************************************/ F32 getMeasuredFanRPM( FAN_NAMES_T fan ) { - F32 rpm = 0.0; + F32 rpm; // Check if the called fan is in range if ( fan < NUM_OF_FANS_NAMES ) { - rpm = fansStatus.rpm[ fan ]; + // Assume there is no override + rpm = fansStatus.rpm[ fan ].data; + + if ( OVERRIDE_KEY == fansStatus.rpm[ fan ].override ) + { + rpm = fansStatus.rpm[ fan ].ovData; + } } else { @@ -380,12 +397,12 @@ // Otherwise, convert the pulse to RPM if ( togglePeriods[ fan ] == FANS_ZERO_RPM_TOGGLE_PERIOD_VALUE ) { - fansStatus.rpm[ fan ] = 0; + fansStatus.rpm[ fan ].data = 0; } else { // Convert toggle period to RPM - fansStatus.rpm[ fan ] = TOGGLE_PERIOD_2_RPM_COEFFICIENT / togglePeriods[ fan ]; + fansStatus.rpm[ fan ].data = TOGGLE_PERIOD_2_RPM_COEFFICIENT / togglePeriods[ fan ]; } } } @@ -417,8 +434,8 @@ for ( fan = FAN_INLET_1; fan < NUM_OF_FANS_NAMES; fan++ ) { - isFanRPMOutOfRange = ( fansStatus.rpm[ fan ] < fansMinAllowedRPM ) || ( fansStatus.rpm[ fan ] > fansMaxAllowedRPM ); - checkPersistentAlarm( ALARM_ID_DG_FAN_RPM_OUT_OF_RANGE, isFanRPMOutOfRange, fansStatus.rpm[ fan ], FANS_MAX_ALLOWED_RPM ); + isFanRPMOutOfRange = ( getMeasuredFanRPM( fan ) < fansMinAllowedRPM ) || ( getMeasuredFanRPM( fan ) > fansMaxAllowedRPM ); + checkPersistentAlarm( ALARM_ID_DG_FAN_RPM_OUT_OF_RANGE, isFanRPMOutOfRange, getMeasuredFanRPM( fan ), FANS_MAX_ALLOWED_RPM ); // If the RPM out of range alarm has been raised, do not raise it again, until its alarm silence time has been elapsed hasAlarmBeenRaised = ( TRUE == isAlarmActive( ALARM_ID_DG_FAN_RPM_OUT_OF_RANGE ) ? TRUE : FALSE ); @@ -473,12 +490,12 @@ FANS_DATA_T fansData; fansData.fansTargetDutyCycle = fansStatus.targetDutyCycle * FRACTION_TO_PERCENT_FACTOR; - fansData.fanInlet1RPM = fansStatus.rpm[ FAN_INLET_1 ]; - fansData.fanInlet2RPM = fansStatus.rpm[ FAN_INLET_2 ]; - fansData.fanInlet3RPM = fansStatus.rpm[ FAN_INLET_3 ]; - fansData.fanOutlet1RPM = fansStatus.rpm[ FAN_OUTLET_1 ]; - fansData.fanOutlet2RPM = fansStatus.rpm[ FAN_OUTLET_2 ]; - fansData.fanOutlet3RPM = fansStatus.rpm[ FAN_OUTLET_3 ]; + fansData.fanInlet1RPM = getMeasuredFanRPM( FAN_INLET_1 ); + fansData.fanInlet2RPM = getMeasuredFanRPM( FAN_INLET_2 ); + fansData.fanInlet3RPM = getMeasuredFanRPM( FAN_INLET_3 ); + fansData.fanOutlet1RPM = getMeasuredFanRPM( FAN_OUTLET_1 ); + fansData.fanOutlet2RPM = getMeasuredFanRPM( FAN_OUTLET_2 ); + fansData.fanOutlet3RPM = getMeasuredFanRPM( FAN_OUTLET_3 ); broadcastFansData( &fansData ); @@ -539,4 +556,55 @@ return result; } +/*********************************************************************//** + * @brief + * The testSetFanRPMOverride function overrides the RPM of a fan. + * @details Inputs: none + * @details Outputs: fansStatus + * @param fanId fan ID + * @param rpm the RPM override value + * @return TRUE if override successful, FALSE if not + *************************************************************************/ +BOOL testSetFanRPMOverride( U32 fanId, F32 rpm ) +{ + BOOL result = FALSE; + + if ( fanId < NUM_OF_FANS_NAMES ) + { + if ( TRUE == isTestingActivated() ) + { + result = TRUE; + fansStatus.rpm[ fanId ].ovData = rpm; + fansStatus.rpm[ fanId ].override = OVERRIDE_KEY; + } + } + + return result; +} + +/*********************************************************************//** + * @brief + * The testResetFanRPMOverride function resets the override value of a fan. + * @details Inputs: none + * @details Outputs: fansStatus + * @param fanId fan index + * @return TRUE if override successful, FALSE if not + *************************************************************************/ +BOOL testResetFanRPMOverride( U32 fanId ) +{ + BOOL result = FALSE; + + if ( fanId < NUM_OF_FANS_NAMES ) + { + if ( TRUE == isTestingActivated() ) + { + result = TRUE; + fansStatus.rpm[ fanId ].ovData = fansStatus.rpm[ fanId ].ovInitData; + fansStatus.rpm[ fanId ].override = OVERRIDE_RESET; + } + } + + return result; +} + /**@}*/ Index: firmware/App/Controllers/Fans.h =================================================================== diff -u -r0b17c6271cdc3c55697a74ecaadb477d9c8f5687 -r22f1a58ac8e419353ec004b04e7c765c1d59df2b --- firmware/App/Controllers/Fans.h (.../Fans.h) (revision 0b17c6271cdc3c55697a74ecaadb477d9c8f5687) +++ firmware/App/Controllers/Fans.h (.../Fans.h) (revision 22f1a58ac8e419353ec004b04e7c765c1d59df2b) @@ -47,6 +47,9 @@ BOOL testSetFanPublishIntervalOverride( U32 value ); BOOL testResetFanPublishIntervalOverride( void ); +BOOL testSetFanRPMOverride( U32 fanId, F32 rpm ); +BOOL testResetFanRPMOverride( U32 fanId ); + /**@}*/ #endif Index: firmware/App/Controllers/LoadCell.c =================================================================== diff -u -r97e0100921ccad633b39b509a93a7237e4d80446 -r22f1a58ac8e419353ec004b04e7c765c1d59df2b --- firmware/App/Controllers/LoadCell.c (.../LoadCell.c) (revision 97e0100921ccad633b39b509a93a7237e4d80446) +++ firmware/App/Controllers/LoadCell.c (.../LoadCell.c) (revision 22f1a58ac8e419353ec004b04e7c765c1d59df2b) @@ -34,17 +34,19 @@ // 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_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 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 MAX_ALLOWED_EXTRA_WEIGHT_BEFORE_TARE_GRAMS 300 ///< Max allowed extra weight before tare in grams. +#define LOAD_CELL_ADC_ERROR_PERSISTENCE 500 ///< Alarm persistence period (in ms) for load cell ADC errors. +#define LOAD_CELL_MIN_ALLOWED_WEIGHT_GRAMS 1600 ///< Load cell minimum allowed weight in grams. +#define LOAD_CELL_MAX_ALLOWED_WEIGHT_GRAMS 4500 ///< Load cell maximum allowed weight in grams. +#define MAX_ALLOWED_EXTRA_WEIGHT_BEFORE_TARE_GRAMS 300 ///< Max allowed extra weight before tare in grams. +#define LOAD_CELL_WEIGHT_OUT_RANGE_PERSISTENT_PERIOD_MS (5 * MS_PER_SECOND) ///< Load cell weight out of range persistent period in milliseconds. /// Load cell data structure. typedef struct @@ -79,6 +81,7 @@ static U32 getLoadCellDataPublishInterval( void ); static BOOL processCalibrationData( void ); +static void monitorLoadCellsWeightOutOfRange( void ); /*********************************************************************//** * @brief @@ -87,7 +90,7 @@ * @details Outputs: LoadCell module initialized. * @return none *************************************************************************/ -void initLoadCell( void ) + void initLoadCell( void ) { U32 cell; U32 i; @@ -126,18 +129,11 @@ loadcells[ i ].loadCellVelocity_g_min = 0.0; } - for ( cell = CAL_DATA_LOAD_CELL_A1; cell < NUM_OF_CAL_DATA_LOAD_CELLS; cell++ ) - { - // Reset the calibration variables - loadCellsCalRecord.loadCells[ cell ].fourthOrderCoeff = 0.0; - loadCellsCalRecord.loadCells[ cell ].thirdOrderCoeff = 0.0; - loadCellsCalRecord.loadCells[ cell ].secondOrderCoeff = 0.0; - loadCellsCalRecord.loadCells[ cell ].gain = 1.0; - loadCellsCalRecord.loadCells[ cell ].offset = 0.0; - } - // Initialize persistent alarm(s) initPersistentAlarm( ALARM_ID_DG_LOAD_CELL_ADC_ERROR, 0, LOAD_CELL_ADC_ERROR_PERSISTENCE ); + + initPersistentAlarm( ALARM_ID_DG_LOAD_CELL_WEIGHT_OUT_OF_RANGE, LOAD_CELL_WEIGHT_OUT_RANGE_PERSISTENT_PERIOD_MS, + LOAD_CELL_WEIGHT_OUT_RANGE_PERSISTENT_PERIOD_MS ); } /*********************************************************************//** @@ -244,6 +240,9 @@ loadCellDataPublicationTimerCounter = 0; } + + // Monitor the weight of the load cells + monitorLoadCellsWeightOutOfRange(); } /*********************************************************************//** @@ -292,7 +291,7 @@ { // For the first tare, the weight of the reservoir should be considered // The current weight of the load cell should not be greater than the weight of the reservoir + the extra weight - F32 deltaWeight = fabs( weight - EMPTY_RESERVOIR_WEIGHT_GRAMS ); + F32 deltaWeight = fabs( weight - LOAD_CELL_MIN_ALLOWED_WEIGHT_GRAMS ); isWeightOutOfRange = ( deltaWeight > MAX_ALLOWED_EXTRA_WEIGHT_BEFORE_TARE_GRAMS ? TRUE : FALSE ); } else @@ -493,7 +492,34 @@ return status; } +/*********************************************************************//** + * @brief + * The monitorLoadCellsWeightOutOfRange function monitors the weight of the + * load cells and if they are not in range, it raises an alarm. + * @details Inputs: loadcells + * @details Outputs: none + * @return none + *************************************************************************/ +static void monitorLoadCellsWeightOutOfRange( void ) +{ + LOAD_CELL_ID_T loadCell; + BOOL isWeightOutOfRange; + F32 weight; + for ( loadCell = LOAD_CELL_RESERVOIR_1_PRIMARY; loadCell < NUM_OF_LOAD_CELLS; loadCell++ ) + { + // The load cells must have been tared before checking for the weight range + if ( loadcells[ loadCell ].autoCalOffset != 0 ) + { + weight = getLoadCellSmallFilteredWeight( loadCell ); + isWeightOutOfRange = ( weight < LOAD_CELL_MIN_ALLOWED_WEIGHT_GRAMS ) || ( weight > LOAD_CELL_MAX_ALLOWED_WEIGHT_GRAMS ); + + checkPersistentAlarm( ALARM_ID_DG_LOAD_CELL_WEIGHT_OUT_OF_RANGE, isWeightOutOfRange, weight, LOAD_CELL_MAX_ALLOWED_WEIGHT_GRAMS ); + } + } +} + + /************************************************************************* * TEST SUPPORT FUNCTIONS *************************************************************************/ Index: firmware/App/Controllers/Thermistors.c =================================================================== diff -u -rddb9707d9e6e46c4b384782aeec20d41f3822996 -r22f1a58ac8e419353ec004b04e7c765c1d59df2b --- firmware/App/Controllers/Thermistors.c (.../Thermistors.c) (revision ddb9707d9e6e46c4b384782aeec20d41f3822996) +++ firmware/App/Controllers/Thermistors.c (.../Thermistors.c) (revision 22f1a58ac8e419353ec004b04e7c765c1d59df2b) @@ -126,6 +126,15 @@ break; } + // First convert the values + convertADC2Temperature(); + + // Monitor the values for a gross range check + // Monitor is called in this function because this driver is constantly reading + // the thermistor values. Also the internal ADC values are processed with moving average in the internalADC driver + // So the thermistors drivers just gets the latest ADC value and converts it to temperature + monitorThermistors(); + // Check if it is time to publish any data publishThermistorsData(); } @@ -205,12 +214,6 @@ thermistorsStatus[ THERMISTOR_POWER_SUPPLY_1 ].rawADCRead = getIntADCReading( INT_ADC_POWER_SUPPLY_1_THERMISTOR ); thermistorsStatus[ THERMISTOR_POWER_SUPPLY_2 ].rawADCRead = getIntADCReading( INT_ADC_POWER_SUPPLY_2_THERMISTOR ); - // Monitor the values for a gross range check - // Monitor is called in this function because this driver is constantly reading - // the thermistor values. Also the internal ADC values are processed with moving average in the internalADC driver - // So the thermistors drivers just gets the latest ADC value and converts it to temperature - monitorThermistors(); - // Zero the counter for the next round of reading adcReadCounter = 0; } @@ -231,13 +234,10 @@ THERMISTORS_TEMP_SENSORS_T thermistor; F32 temperature; - // First convert the values - convertADC2Temperature(); - for ( thermistor = THERMISTOR_ONBOARD_NTC; thermistor < NUM_OF_THERMISTORS; thermistor++ ) { temperature = getThermistorTemperatureValue( thermistor ); - BOOL const isTempOutOfRange = ( temperature > MAX_ALLOWED_TEMPERATURE ) || ( temperature < MIN_ALLOWED_TEMPERATURE ); + BOOL isTempOutOfRange = ( temperature > MAX_ALLOWED_TEMPERATURE ) || ( temperature < MIN_ALLOWED_TEMPERATURE ); checkPersistentAlarm( ALARM_ID_DG_THERMISTORS_TEMPERATURE_OUT_OF_RANGE, isTempOutOfRange, temperature, MAX_ALLOWED_TEMPERATURE ); } Index: firmware/App/Services/SystemComm.c =================================================================== diff -u -r3ca2e68a33885153648ba20346e3548438b58724 -r22f1a58ac8e419353ec004b04e7c765c1d59df2b --- firmware/App/Services/SystemComm.c (.../SystemComm.c) (revision 3ca2e68a33885153648ba20346e3548438b58724) +++ firmware/App/Services/SystemComm.c (.../SystemComm.c) (revision 22f1a58ac8e419353ec004b04e7c765c1d59df2b) @@ -1286,9 +1286,13 @@ break; case MSG_ID_FILTER_FLUSH_TIME_PERIOD_OVERRIDE: - handleFilterFlushTimePeriodOverride(message); + handleFilterFlushTimePeriodOverride( message ); break; + case MSG_ID_DG_FANS_RPM_OVERRIDE: + handleFansRPMOverride( message ); + break; + default: // TODO - unrecognized message ID received - ignore break; Index: firmware/App/Services/SystemCommMessages.c =================================================================== diff -u -r3ca2e68a33885153648ba20346e3548438b58724 -r22f1a58ac8e419353ec004b04e7c765c1d59df2b --- firmware/App/Services/SystemCommMessages.c (.../SystemCommMessages.c) (revision 3ca2e68a33885153648ba20346e3548438b58724) +++ firmware/App/Services/SystemCommMessages.c (.../SystemCommMessages.c) (revision 22f1a58ac8e419353ec004b04e7c765c1d59df2b) @@ -22,6 +22,7 @@ #include "Accel.h" #include "ConcentratePumps.h" #include "ConductivitySensors.h" +#include "Fans.h" #include "FPGA.h" #include "Heaters.h" #include "ModeFlush.h" @@ -3537,6 +3538,37 @@ } /*********************************************************************//** + * @brief + * The handleFansRPMOverride function handles a request to override a fans RPM value. + * @details Inputs: none + * @details Outputs: message handled + * @param message a pointer to the message to handle + * @return none + *************************************************************************/ +void handleFansRPMOverride( MESSAGE_T *message ) +{ + TEST_OVERRIDE_ARRAY_PAYLOAD_T payload; + BOOL result = FALSE; + + // verify payload length + if ( sizeof(TEST_OVERRIDE_ARRAY_PAYLOAD_T) == message->hdr.payloadLen ) + { + memcpy( &payload, message->payload, sizeof(TEST_OVERRIDE_ARRAY_PAYLOAD_T) ); + if ( FALSE == payload.reset ) + { + result = testSetFanRPMOverride( payload.index, payload.state.f32 ); + } + else + { + result = testResetFanRPMOverride( payload.index ); + } + } + + // respond to request + sendTestAckResponseMsg( (MSG_ID_T)message->hdr.msgID, result ); +} + +/*********************************************************************//** * @brief * The handleStartStopDGChemicalDisinfect function handles a request to start * or stop DG chemical disinfect mode. Index: firmware/App/Services/SystemCommMessages.h =================================================================== diff -u -r3ca2e68a33885153648ba20346e3548438b58724 -r22f1a58ac8e419353ec004b04e7c765c1d59df2b --- firmware/App/Services/SystemCommMessages.h (.../SystemCommMessages.h) (revision 3ca2e68a33885153648ba20346e3548438b58724) +++ firmware/App/Services/SystemCommMessages.h (.../SystemCommMessages.h) (revision 22f1a58ac8e419353ec004b04e7c765c1d59df2b) @@ -384,6 +384,9 @@ // MSG_ID_FILTER_FLUSH_TIME_PERIOD_OVERRIDE void handleFilterFlushTimePeriodOverride( MESSAGE_T *message ); +// MSG_ID_DG_FANS_RPM_OVERRIDE +void handleFansRPMOverride( MESSAGE_T *message ); + /**@}*/ #endif Index: firmware/App/Services/WatchdogMgmt.c =================================================================== diff -u -r67021fbc633259e8e1bce76749dbef7d0cb51998 -r22f1a58ac8e419353ec004b04e7c765c1d59df2b --- firmware/App/Services/WatchdogMgmt.c (.../WatchdogMgmt.c) (revision 67021fbc633259e8e1bce76749dbef7d0cb51998) +++ firmware/App/Services/WatchdogMgmt.c (.../WatchdogMgmt.c) (revision 22f1a58ac8e419353ec004b04e7c765c1d59df2b) @@ -167,7 +167,7 @@ } else { - activateAlarmNoData( ALARM_ID_WATCHDOG_POST_TEST_FAILED ); + activateAlarmNoData( ALARM_ID_DG_WATCHDOG_POST_TEST_FAILED ); watchdogSelfTestStatus = SELF_TEST_STATUS_FAILED; } watchdogSelfTestTimerCount = getMSTimerCount();