Index: firmware/App/Controllers/Heaters.c =================================================================== diff -u -r3b70632c04247a6973960e1f37ae73eb4384a6b7 -rfc11115c26447a2da7b12f5f38ff0d4af06c579b --- firmware/App/Controllers/Heaters.c (.../Heaters.c) (revision 3b70632c04247a6973960e1f37ae73eb4384a6b7) +++ firmware/App/Controllers/Heaters.c (.../Heaters.c) (revision fc11115c26447a2da7b12f5f38ff0d4af06c579b) @@ -22,21 +22,21 @@ #include "AlarmMgmt.h" #include "DGDefs.h" +#include "FlowSensors.h" #include "Heaters.h" -#include "InternalADC.h" #include "MessageSupport.h" #include "ModeFill.h" #include "NVDataMgmt.h" #include "OperationModes.h" #include "PersistentAlarm.h" #include "Reservoirs.h" -#include "ROPump.h" #include "SafetyShutdown.h" #include "SystemCommMessages.h" #include "TaskGeneral.h" #include "TaskPriority.h" #include "TemperatureSensors.h" #include "Timers.h" +#include "Voltages.h" /** * @addtogroup Heaters @@ -48,26 +48,32 @@ #define HEATERS_MAX_DUTY_CYCLE 1.00F ///< Heaters max duty cycle (100%). #define HEATERS_MIN_DUTY_CYCLE 0.00F ///< Heaters minimum duty cycle (0.00%). #define HEATERS_MIN_HEAT_DISINFECT_DUTY_CYCLE 0.6F ///< Heaters minimum duty cycle during heat disinfect. +#define HEATERS_MIN_EST_GAIN 0.2F ///< Heaters minimum estimation gain. +#define HEATERS_MAX_EST_GAIN 5.0F ///< Heaters maximum estimation gain. +#define HEATERS_NEUTRAL_EST_GAIN 1.0F ///< Heaters neutral estimation gain. #define HEATERS_DATA_PUBLISH_INTERVAL ( MS_PER_SECOND / TASK_PRIORITY_INTERVAL ) ///< Heaters data publish interval. #define MINIMUM_TARGET_TEMPERATURE 10.0F ///< Minimum allowed target temperature for the heaters. #define MAXIMUM_TARGET_TEMPERATURE 90.0F ///< Maximum allowed target temperature for the heaters. -#define HEATERS_ON_NO_FLOW_TIMEOUT_MS ( 1 * MS_PER_SECOND ) ///< Heaters on with no flow time out in milliseconds. +#define HEATERS_ON_NO_FLOW_TIMEOUT_MS ( 10 * 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_OUT_OF_RANGE_TIMEOUT_MS ( 2 * MS_PER_SECOND ) ///< Heaters voltage out of range time out in milliseconds. #define HEATERS_MAX_VOLTAGE_OUT_OF_RANGE_TOL 0.2F ///< Heaters max voltage out of range tolerance. #define TRIMMER_HEATER_MAX_POWER_W 66.5F ///< Trimmer heater maximum power in Watts. #define TRIMMER_HEATER_CONTROL_CHECK_INTERVAL_COUNT ( ( 30 * MS_PER_SECOND ) / TASK_GENERAL_INTERVAL ) ///< Trimmer heater control interval count. #define DELTA_TEMPERATURE_TIME_COSNTANT_C 8.6F ///< Delta temperature calculated from time constant. -#define PRIMARY_HEATER_DUTY_CYCLE_PER_TEMPERATURE_C 0.03F ///< Primary heaters duty cycle per temperature in C. +#define PRIMARY_HEATER_DUTY_CYCLE_PER_TEMPERATURE_C 0.015F ///< Primary heaters duty cycle per temperature in C. #define DATA_PUBLISH_COUNTER_START_COUNT 70 ///< Data publish counter start count. #define MIN_RO_HEATER_FLOWRATE_LPM 0.2F ///< Minimum target RO heater flow rate in L/min. +#define PRIMARY_HEATER_POWER_TOL 0.1F ///< Primary heater power tolerance. static const F32 WATER_SPECIFIC_HEAT_DIVIDED_BY_MINUTES = 4184 / SEC_PER_MIN; ///< Water specific heat in J/KgC / 60. static const F32 PRIMARY_HEATERS_MAXIMUM_POWER_WATTS = 475 + 237.5F; ///< Primary heaters maximum power (main primary = 475W and small primary = 237.5W). +static const F32 HEATERS_VOLTAGE_TOLERANCE_V = HEATERS_MAX_OPERATING_VOLTAGE_V * HEATERS_MAX_VOLTAGE_OUT_OF_RANGE_TOL; ///< Heaters voltage tolerance in volts. +static const F32 PRIMARY_HEATER_VOLTAGE_TOLERANCE_V = HEATERS_MAX_OPERATING_VOLTAGE_V * PRIMARY_HEATER_POWER_TOL; ///< Primary heater power voltage tolerance in volts. /// Heaters data structure typedef struct @@ -76,10 +82,10 @@ HEATERS_STATE_T state; ///< Heater state. BOOL startHeaterSignal; ///< Heater start indication flag. BOOL isHeaterOn; ///< Heater on/off status flag. - F32 dutycycle; ///< Heater duty cycle. + F32 dutyCycle; ///< Heater duty cycle. F32 targetFlow; ///< Heater target flow. BOOL hasTargetTempChanged; ///< Heater target temperature change flag indicator. - F32 heaterEstGain; ///< Heater efficiency during the run. + F32 heaterEstGain; ///< Heater estimation gain during the run. BOOL hasTargetBeenReached; ///< Heater flag to indicate whether the target temperature has been reached. F32 calculatedTemperature; ///< Heater calculated temperature. DG_RESERVOIR_ID_T inactiveRsrvr; ///< Heater inactive reservoir. @@ -131,24 +137,20 @@ heatersStatus[ heater ].state = HEATER_EXEC_STATE_OFF; heatersStatus[ heater ].startHeaterSignal = FALSE; heatersStatus[ heater ].isHeaterOn = FALSE; - heatersStatus[ heater ].dutycycle = 0.0; + heatersStatus[ heater ].dutyCycle = 0.0; heatersStatus[ heater ].targetFlow = 0.0; heatersStatus[ heater ].hasTargetTempChanged = FALSE; - heatersStatus[ heater ].heaterEstGain = 1.0; // Assuming 100% efficiency during initialization until it is updated + heatersStatus[ heater ].heaterEstGain = HEATERS_NEUTRAL_EST_GAIN; heatersStatus[ heater ].hasTargetBeenReached = FALSE; } // Initialize the persistent alarms - initPersistentAlarm( ALARM_ID_DG_MAIN_PRIMARY_HEATER_VOLTAGE_OUT_OF_RANGE, HEATERS_VOLTAGE_OUT_OF_RANGE_TIMEOUT_MS, - HEATERS_VOLTAGE_OUT_OF_RANGE_TIMEOUT_MS ); - - initPersistentAlarm( ALARM_ID_DG_SMALL_PRIMARY_HEATER_VOLTAGE_OUT_OF_RANGE, HEATERS_VOLTAGE_OUT_OF_RANGE_TIMEOUT_MS, - HEATERS_VOLTAGE_OUT_OF_RANGE_TIMEOUT_MS ); - - initPersistentAlarm( ALARM_ID_DG_TRIMMER_HEATER_VOLTAGE_OUT_OF_RANGE, HEATERS_VOLTAGE_OUT_OF_RANGE_TIMEOUT_MS, - HEATERS_VOLTAGE_OUT_OF_RANGE_TIMEOUT_MS ); - - initPersistentAlarm( ALARM_ID_DG_FLOW_TOO_LOW_WHILE_HEATER_ON, HEATERS_ON_NO_FLOW_TIMEOUT_MS, HEATERS_ON_NO_FLOW_TIMEOUT_MS ); + initPersistentAlarm( ALARM_ID_DG_MAIN_PRIMARY_HEATER_VOLTAGE_OUT_OF_RANGE, HEATERS_VOLTAGE_OUT_OF_RANGE_TIMEOUT_MS, HEATERS_VOLTAGE_OUT_OF_RANGE_TIMEOUT_MS ); + initPersistentAlarm( ALARM_ID_DG_SMALL_PRIMARY_HEATER_VOLTAGE_OUT_OF_RANGE, HEATERS_VOLTAGE_OUT_OF_RANGE_TIMEOUT_MS, HEATERS_VOLTAGE_OUT_OF_RANGE_TIMEOUT_MS ); + initPersistentAlarm( ALARM_ID_DG_TRIMMER_HEATER_VOLTAGE_OUT_OF_RANGE, HEATERS_VOLTAGE_OUT_OF_RANGE_TIMEOUT_MS, HEATERS_VOLTAGE_OUT_OF_RANGE_TIMEOUT_MS ); + initPersistentAlarm( ALARM_ID_DG_PRIMARY_HEATER_POWER_VOLTAGE_OUT_OF_RANGE, HEATERS_VOLTAGE_OUT_OF_RANGE_TIMEOUT_MS, HEATERS_VOLTAGE_OUT_OF_RANGE_TIMEOUT_MS ); + initPersistentAlarm( ALARM_ID_RO_FLOW_TOO_LOW_WHILE_PRIMARY_HEATER_IS_ON, HEATERS_ON_NO_FLOW_TIMEOUT_MS, HEATERS_ON_NO_FLOW_TIMEOUT_MS ); + initPersistentAlarm( ALARM_ID_DIALYSATE_FLOW_TOO_LOW_WHILE_TRIMMER_HEATER_IS_ON, HEATERS_ON_NO_FLOW_TIMEOUT_MS, HEATERS_ON_NO_FLOW_TIMEOUT_MS ); } /*********************************************************************//** @@ -167,6 +169,7 @@ if( heater < NUM_OF_DG_HEATERS ) { +#ifndef DISABLE_HEATERS_AND_TEMPS // Assume the target temperature has not changed heatersStatus[ heater ].hasTargetTempChanged = FALSE; @@ -177,6 +180,7 @@ heatersStatus[ heater ].hasTargetTempChanged = TRUE; result = TRUE; } +#endif } else { @@ -210,9 +214,10 @@ { BOOL status = FALSE; + if( heater < NUM_OF_DG_HEATERS ) { - if ( TRUE == heatersStatus[ heater ].hasTargetTempChanged ) + if ( HEATER_EXEC_STATE_OFF == heatersStatus[ heater ].state ) { status = TRUE; heatersStatus[ heater ].startHeaterSignal = TRUE; @@ -317,17 +322,32 @@ // 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 - F32 measFlow = ( DG_PRIMARY_HEATER == heater ? getMeasuredROFlowRateLPM() : 50.0 ); - F32 minFlow = ( DG_PRIMARY_HEATER == heater ? MIN_RO_HEATER_FLOWRATE_LPM : MIN_RO_HEATER_FLOWRATE_LPM ); - BOOL isFlowLow = ( measFlow < minFlow ? TRUE : FALSE ); + ALARM_ID_T alarm; + F32 measFlow; + F32 minFlow; + BOOL isFlowLow; - checkPersistentAlarm( ALARM_ID_DG_FLOW_TOO_LOW_WHILE_HEATER_ON, isFlowLow, measFlow, minFlow ); + if ( DG_PRIMARY_HEATER == heater ) + { + alarm = ALARM_ID_RO_FLOW_TOO_LOW_WHILE_PRIMARY_HEATER_IS_ON; + measFlow = getMeasuredFlowRateLPM( RO_FLOW_SENSOR ); + minFlow = MIN_RO_HEATER_FLOWRATE_LPM; + } + else + { + alarm = ALARM_ID_DIALYSATE_FLOW_TOO_LOW_WHILE_TRIMMER_HEATER_IS_ON; + measFlow = getMeasuredFlowRateLPM( DIALYSATE_FLOW_SENSOR ); + minFlow = MIN_DIALYSATE_FLOWRATE_LPM; + } + + isFlowLow = ( measFlow < minFlow ? TRUE : FALSE ); + + checkPersistentAlarm( alarm, isFlowLow, measFlow, minFlow ); } else { - checkPersistentAlarm( ALARM_ID_DG_FLOW_TOO_LOW_WHILE_HEATER_ON, FALSE, 0.0, 0.0 ); + checkPersistentAlarm( ALARM_ID_RO_FLOW_TOO_LOW_WHILE_PRIMARY_HEATER_IS_ON, FALSE, 0.0, 0.0 ); + checkPersistentAlarm( ALARM_ID_DIALYSATE_FLOW_TOO_LOW_WHILE_TRIMMER_HEATER_IS_ON, FALSE, 0.0, 0.0 ); } } @@ -344,20 +364,61 @@ /*********************************************************************//** * @brief - * The resetHeatersEfficiency function resets the heaters efficiency upon + * The resetHeatersEstimationGain function resets the heaters estimation gain upon * the start of a treatment. * @details Inputs: none * @details Outputs: heaterStatus * @return none *************************************************************************/ -void resetHeatersEfficiency( void ) +void resetHeatersEstimationGain( void ) { - heatersStatus[ DG_PRIMARY_HEATER ].heaterEstGain = 1.0; - heatersStatus[ DG_TRIMMER_HEATER ].heaterEstGain = 1.0; + heatersStatus[ DG_PRIMARY_HEATER ].heaterEstGain = HEATERS_NEUTRAL_EST_GAIN; + heatersStatus[ DG_TRIMMER_HEATER ].heaterEstGain = HEATERS_NEUTRAL_EST_GAIN; } /*********************************************************************//** * @brief + * The calculateHeaterEstimationGain function calculates the heater estimation + * gain. + * @details Inputs: none + * @details Outputs: heatersStatus + * @return none + *************************************************************************/ +void calculateHeaterEstimationGain( DG_HEATERS_T heater ) +{ +#ifndef _RELEASE_ + if ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_HEATERS_EFFICIENCY ) != SW_CONFIG_ENABLE_VALUE ) +#endif + { + F32 heaterEstGain = heatersStatus[ heater ].heaterEstGain; + F32 heaterDutyCycle = heatersStatus[ heater ].dutyCycle; + F32 lastFillTemperature = getAvgFillTemperature(); + F32 primaryTargetTemperature = heatersStatus[ heater ].targetTemp; + BOOL isTempUnderTarget = ( lastFillTemperature < primaryTargetTemperature ? TRUE : FALSE ); + + if ( TRUE == isTempUnderTarget ) + { + if ( heaterDutyCycle < HEATERS_MAX_DUTY_CYCLE ) + { + heaterEstGain += ( primaryTargetTemperature - lastFillTemperature ) * PRIMARY_HEATER_DUTY_CYCLE_PER_TEMPERATURE_C; + } + } + else + { + if ( heaterDutyCycle > HEATERS_MIN_DUTY_CYCLE ) + { + heaterEstGain -= ( lastFillTemperature - primaryTargetTemperature ) * PRIMARY_HEATER_DUTY_CYCLE_PER_TEMPERATURE_C; + } + } + + heaterEstGain = MAX( heaterEstGain, HEATERS_MIN_EST_GAIN ); + heaterEstGain = MIN( heaterEstGain, HEATERS_MAX_EST_GAIN ); + heatersStatus[ heater ].heaterEstGain = heaterEstGain; + } +} + +/*********************************************************************//** + * @brief * The handleHeaterStateOff function handles the heater not running state. * @details Inputs: heaterStatus * @details Outputs: heaterStatus @@ -401,17 +462,16 @@ if ( DG_MODE_FILL == opMode ) { // If the previous average fill flow rate is 0, use the nominal target RO flow from the RO pump - targetFlow = ( getAvgFillFlowRateLPM() - 0.0 > NEARLY_ZERO ? getAvgFillFlowRateLPM() : getTargetROPumpFlowRateLPM() ); + targetFlow = ( getAvgFillFlowRateLPM() - 0.0F > NEARLY_ZERO ? getAvgFillFlowRateLPM() : getTargetROPumpFlowRateLPM() ); dutyCycle = calculatePrimaryHeaterDutyCycle( targetTemperature, inletTemperature, targetFlow, TRUE ); state = HEATER_EXEC_STATE_PRIMARY_CONTROL_TO_TARGET; } else if ( ( DG_MODE_GENE == opMode ) || ( DG_MODE_DRAI == opMode ) ) { targetTemperature += DELTA_TEMPERATURE_TIME_COSNTANT_C; - // Use target flow rate during Idle and drain - targetFlow = getTargetROPumpFlowRateLPM(); - dutyCycle = calculatePrimaryHeaterDutyCycle( targetTemperature, inletTemperature, targetFlow, FALSE ); - state = HEATER_EXEC_STATE_PRIMARY_CONTROL_TO_TARGET; + targetFlow = getTargetROPumpFlowRateLPM(); + dutyCycle = calculatePrimaryHeaterDutyCycle( targetTemperature, inletTemperature, targetFlow, FALSE ); + state = HEATER_EXEC_STATE_PRIMARY_CONTROL_TO_TARGET; } else if ( ( DG_MODE_HEAT == opMode ) || ( DG_MODE_CHEM == opMode ) ) { @@ -421,6 +481,10 @@ dutyCycle = calculatePrimaryHeaterDutyCycle( targetTemperature, inletTemperature, targetFlow, FALSE ); state = HEATER_EXEC_STATE_CONTROL_TO_DISINFECT_TARGET; } + else + { + // Do nothing the mode that DG is in right now, does not need heaters to be on + } // Update the calculated target temperature heatersStatus[ DG_PRIMARY_HEATER ].calculatedTemperature = targetTemperature; @@ -472,7 +536,7 @@ state = HEATER_EXEC_STATE_PRIMARY_RAMP_TO_TARGET; } - // If the heat disifect sensor indicates that the temperature is below target temperature but the target temperature had been reached + // If the heat disinfect sensor indicates that the temperature is below target temperature but the target temperature had been reached // before turn on the heaters with 100% power if ( ( heatDisinfectSensorTemp <= heatersStatus[ heater ].targetTemp ) && ( TRUE == heatersStatus[ heater ].hasTargetBeenReached ) ) { @@ -513,7 +577,7 @@ if ( ( DG_MODE_FILL == opMode ) || ( DG_MODE_GENE == opMode ) || ( DG_MODE_DRAI == opMode ) ) { - currentTemperature = getTrimmerHeaterTargetTemperature(); + currentTemperature = getReservoirCurrentTemperature(); dutyCycle = calculateTrimmerHeaterDutyCycle( targetTemperature, currentTemperature, targetFlowLPM, TRUE ); state = HEATER_EXEC_STATE_TRIMMER_CONTROL_TO_TARGET; } @@ -529,10 +593,14 @@ } // Update the calculated target temperature + // Reset the duty cycle since the reservoir has been switched heatersStatus[ heater ].calculatedTemperature = currentTemperature; heatersStatus[ heater ].inactiveRsrvr = getInactiveReservoir(); heatersStatus[ heater ].targetFlow = targetFlowLPM; trimmerHeaterControlCounter = 0; + + // Cap the minimum duty cycle. So if it is calculated to negative, set it to 0 + dutyCycle = MAX( dutyCycle, HEATERS_MIN_DUTY_CYCLE ); setHeaterDutyCycle( heater, dutyCycle ); return state; @@ -549,6 +617,7 @@ static HEATERS_STATE_T handleHeaterStateTrimmerControlToTarget( void ) { HEATERS_STATE_T state = HEATER_EXEC_STATE_TRIMMER_CONTROL_TO_TARGET; + F32 tempDutyCycle = 0.0; // If the inactive reservoir has changed from the last run transition to ramp state to recalculate the // duty cycle for the next delivery @@ -560,14 +629,17 @@ { // When the trimmer heater is on, its duty cycle is adjusted at the control interval. For this control check, // dialysate inlet temperature sensor is used rather than the theoretical calculations. - F32 outletRedundantTemperature = getTemperatureValue( TEMPSENSORS_INLET_DIALYSATE ); // TODO Change to TRo in DVT + F32 outletRedundantTemperature = getTemperatureValue( TEMPSENSORS_OUTLET_REDUNDANT ); F32 targetTemperature = heatersStatus[ DG_TRIMMER_HEATER ].targetTemp; F32 targetFlowLPM = heatersStatus[ DG_TRIMMER_HEATER ].targetFlow; F32 dutyCycle = calculateTrimmerHeaterDutyCycle( targetTemperature, outletRedundantTemperature, targetFlowLPM, TRUE ); - trimmerHeaterControlCounter = 0; - setHeaterDutyCycle( DG_TRIMMER_HEATER, dutyCycle ); + tempDutyCycle = heatersStatus[ DG_TRIMMER_HEATER ].dutyCycle + dutyCycle; + tempDutyCycle = MIN( tempDutyCycle, HEATERS_MAX_DUTY_CYCLE ); + tempDutyCycle = MAX( tempDutyCycle, HEATERS_MIN_DUTY_CYCLE ); + + setHeaterDutyCycle( DG_TRIMMER_HEATER, tempDutyCycle ); } return state; @@ -584,24 +656,17 @@ *************************************************************************/ static void setHeaterDutyCycle( DG_HEATERS_T heater, F32 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 ) { - 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; + setMainPrimaryHeaterPWM( pwm ); + setSmallPrimaryHeaterPWM( pwm ); } + else if ( DG_TRIMMER_HEATER == heater ) + { + setTrimmerHeaterPWM( pwm ); + } + + heatersStatus[ heater ].dutyCycle = pwm; } /*********************************************************************//** @@ -617,48 +682,13 @@ *************************************************************************/ static F32 calculatePrimaryHeaterDutyCycle( F32 targetTemperature, F32 currentTemperature, F32 flow, BOOL checkEfficiency ) { - // Get the primary heater's efficiency and the last fill temperature from the ModeFill - F32 heaterEfficiency = heatersStatus[ DG_PRIMARY_HEATER ].heaterEstGain; - -#ifndef _RELEASE_ - if ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_HEATERS_EFFICIENCY ) != SW_CONFIG_ENABLE_VALUE ) -#endif - { - if ( TRUE == checkEfficiency ) - { - F32 lastFillTemperature = getLastFillTemperature(); - F32 primaryTargetTemperature = heatersStatus[ DG_PRIMARY_HEATER ].targetTemp; - - // If the last fill temperature > target temperature, it means the primary heater overshot the duty cycle - // so with its efficiency is toned down for the next fill cycle - // If the heater under-shoots the duty cycle, the efficiency increases the duty cycle for the next fill cycle - if ( lastFillTemperature - primaryTargetTemperature < 0.0F ) - { - heaterEfficiency -= ( lastFillTemperature - primaryTargetTemperature ) * PRIMARY_HEATER_DUTY_CYCLE_PER_TEMPERATURE_C; - } - else - { - heaterEfficiency += ( primaryTargetTemperature - lastFillTemperature ) * PRIMARY_HEATER_DUTY_CYCLE_PER_TEMPERATURE_C; - } - - // If the efficiency is less than 0, set it to 0 but if the efficiency is greater than 100, it is not enforced - // to be 100 since the duty cycle range check will cap the duty cycle to 100 anyways. - heaterEfficiency = MAX( heaterEfficiency, 0.0 ); - - // Update the heaters efficiency - heatersStatus[ DG_PRIMARY_HEATER ].heaterEstGain = heaterEfficiency; - } - } - // Duty cycle = ( 69.73 * flow rate * deltaT / primary heater maximum power ) ^ 1/2 // Multiply the duty cycle to the heater efficiency - F32 dutyCycle = sqrt( ( WATER_SPECIFIC_HEAT_DIVIDED_BY_MINUTES * - fabs( targetTemperature - currentTemperature ) * flow ) / PRIMARY_HEATERS_MAXIMUM_POWER_WATTS ) * heaterEfficiency; + F32 dutyCycle = sqrt( ( WATER_SPECIFIC_HEAT_DIVIDED_BY_MINUTES * fabs( targetTemperature - currentTemperature ) * flow ) / PRIMARY_HEATERS_MAXIMUM_POWER_WATTS ); + dutyCycle *= heatersStatus[ DG_PRIMARY_HEATER ].heaterEstGain; + dutyCycle = MIN( dutyCycle, HEATERS_MAX_DUTY_CYCLE ); + dutyCycle = MAX( dutyCycle, HEATERS_MIN_DUTY_CYCLE ); - // Check the boundaries of the calculated duty cycle - dutyCycle = MIN( dutyCycle, HEATERS_MAX_DUTY_CYCLE ); - dutyCycle = MAX( dutyCycle, HEATERS_MIN_DUTY_CYCLE ); - return dutyCycle; } @@ -678,26 +708,23 @@ static F32 calculateTrimmerHeaterDutyCycle( F32 targetTemperature, F32 currentTemperature, F32 flow, BOOL checkEfficiency ) { // Get the primary heater's efficiency and the last fill temperature from the ModeFill - F32 heaterEfficiency = heatersStatus[ DG_TRIMMER_HEATER ].heaterEstGain; - F32 dutyCycle = 0.0; + F32 heaterEstGain = heatersStatus[ DG_TRIMMER_HEATER ].heaterEstGain; + F32 dutyCycle = 0.0; #ifndef _RELEASE_ if ( getSoftwareConfigStatus( SW_CONFIG_DISABLE_HEATERS_EFFICIENCY ) != SW_CONFIG_ENABLE_VALUE ) #endif { if ( TRUE == checkEfficiency ) { - // TODO Do we need efficiency for the trimmer heater? + // Do nothing right now. Efficiency will be implemented later if needed } } // Duty cycle = ( 69.73 * flow rate * deltaT / primary heater maximum power ) and multiply the duty cycle to the heater efficiency - dutyCycle = ( ( flow * WATER_SPECIFIC_HEAT_DIVIDED_BY_MINUTES * - ( targetTemperature - currentTemperature ) * heaterEfficiency ) / TRIMMER_HEATER_MAX_POWER_W ) * heaterEfficiency; - - // Check the boundaries of the calculated duty cycle + dutyCycle = ( ( flow * WATER_SPECIFIC_HEAT_DIVIDED_BY_MINUTES * ( targetTemperature - currentTemperature ) ) / TRIMMER_HEATER_MAX_POWER_W ) * heaterEstGain; dutyCycle = MIN( dutyCycle, HEATERS_MAX_DUTY_CYCLE ); - dutyCycle = MAX( dutyCycle, HEATERS_MIN_DUTY_CYCLE ); + dutyCycle = MAX( dutyCycle, ( HEATERS_MAX_DUTY_CYCLE * -1.0F ) ); return dutyCycle; } @@ -739,7 +766,15 @@ *************************************************************************/ static void setMainPrimaryHeaterPWM( F32 pwm ) { - etpwmSetCmpA( etpwmREG1, (U32)( (S32)( ( pwm * (F32)(etpwmREG1->TBPRD) ) + FLOAT_TO_INT_ROUNDUP_OFFSET ) ) ); + etpwm_config_reg_t mainPriConfig; + U32 pwmValue = (U32)( (S32)( ( pwm * (F32)(etpwmREG1->TBPRD) ) + FLOAT_TO_INT_ROUNDUP_OFFSET ) ); + + etpwm1GetConfigValue( &mainPriConfig, CurrentValue ); + + if ( mainPriConfig.CONFIG_CMPA != pwmValue ) + { + etpwmSetCmpA( etpwmREG1, pwmValue ); + } } /*********************************************************************//** @@ -752,7 +787,15 @@ *************************************************************************/ static void setSmallPrimaryHeaterPWM( F32 pwm ) { - etpwmSetCmpB( etpwmREG1, (U32)( (S32)( ( pwm * (F32)(etpwmREG1->TBPRD) ) + FLOAT_TO_INT_ROUNDUP_OFFSET ) ) ); + etpwm_config_reg_t smallPriConfig; + U32 pwmValue = (U32)( (S32)( ( pwm * (F32)(etpwmREG1->TBPRD) ) + FLOAT_TO_INT_ROUNDUP_OFFSET ) ); + + etpwm1GetConfigValue( &smallPriConfig, CurrentValue ); + + if ( smallPriConfig.CONFIG_CMPB != pwmValue ) + { + etpwmSetCmpB( etpwmREG1, pwmValue ); + } } /*********************************************************************//** @@ -765,7 +808,15 @@ *************************************************************************/ static void setTrimmerHeaterPWM( F32 pwm ) { - etpwmSetCmpA( etpwmREG3, (U32)( (S32)( ( pwm * (F32)(etpwmREG3->TBPRD) ) + FLOAT_TO_INT_ROUNDUP_OFFSET ) ) ); + etpwm_config_reg_t trimmerConfig; + U32 pwmValue = (U32)( (S32)( ( pwm * (F32)(etpwmREG3->TBPRD) ) + FLOAT_TO_INT_ROUNDUP_OFFSET ) ); + + etpwm3GetConfigValue( &trimmerConfig, CurrentValue ); + + if ( trimmerConfig.CONFIG_CMPA != pwmValue ) + { + etpwmSetCmpA( etpwmREG3, pwmValue ); + } } /*********************************************************************//** @@ -782,22 +833,21 @@ { HEATERS_DATA_T data; - data.mainPrimayHeaterDC = heatersStatus[ DG_PRIMARY_HEATER ].dutycycle * 100.0; + data.mainPrimayHeaterDC = heatersStatus[ DG_PRIMARY_HEATER ].dutyCycle * 100.0; // The duty cycle of the primary heater is divided into 2 parts and is applied to main // and small primary heaters. So they are always the same. - data.smallPrimaryHeaterDC = heatersStatus[ DG_PRIMARY_HEATER ].dutycycle * 100.0; - data.trimmerHeaterDC = heatersStatus[ DG_TRIMMER_HEATER ].dutycycle * 100.0; + data.smallPrimaryHeaterDC = heatersStatus[ DG_PRIMARY_HEATER ].dutyCycle * 100.0; + data.trimmerHeaterDC = heatersStatus[ DG_TRIMMER_HEATER ].dutyCycle * 100.0; data.primaryTargetTemp = heatersStatus[ DG_PRIMARY_HEATER ].targetTemp; data.trimmerTargetTemp = heatersStatus[ DG_TRIMMER_HEATER ].targetTemp; data.primaryHeaterState = heatersStatus[ DG_PRIMARY_HEATER ].state; data.trimmerHeaterState = heatersStatus[ DG_TRIMMER_HEATER ].state; data.primaryEfficiency = heatersStatus[ DG_PRIMARY_HEATER ].heaterEstGain * 100; data.primaryCalcTargetTemp = heatersStatus[ DG_PRIMARY_HEATER ].calculatedTemperature; data.trimmerCalcCurrentTemp = heatersStatus[ DG_TRIMMER_HEATER ].calculatedTemperature; + dataPublicationTimerCounter = 0; broadcastData( MSG_ID_DG_HEATERS_DATA, COMM_BUFFER_OUT_CAN_DG_BROADCAST, (U08*)&data, sizeof( HEATERS_DATA_T ) ); - - dataPublicationTimerCounter = 0; } } @@ -810,29 +860,49 @@ *************************************************************************/ static void monitorHeatersVoltage( void ) { - 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 - // heater so the main primary heater's ADC channel is used for the small primary heater as well. - F32 smallPriVoltage = getIntADCVoltageConverted( INT_ADC_PRIMARY_HEATER_24_VOLTS ); - F32 trimmerVoltage = getIntADCVoltageConverted( INT_ADC_TRIMMER_HEATER_24_VOLTS ); + F32 mainPriVoltage = getMonitoredLineLevel( MONITORED_LINE_24V_GND_MAIN_PRIM_HTR_V ); +#ifndef _RELEASE_ + if ( SW_CONFIG_ENABLE_VALUE == getSoftwareConfigStatus( SW_CONFIG_ENABLE_V3_SYSTEM ) ) + { + // V3 use CPU based value for Primary, same as Secondary + mainPriVoltage = getMonitoredLineLevel( MONITORED_LINE_24V_GND_SMALL_PRIM_HTR_V ); + } +#endif + + F32 smallPriVoltage = getMonitoredLineLevel( MONITORED_LINE_24V_GND_SMALL_PRIM_HTR_V ); + F32 trimmerVoltage = getMonitoredLineLevel( MONITORED_LINE_24V_GND_TRIM_HTR_V ); + // Voltage to PWM is reverse. If PWM = 0 -> V = 24V - F32 mainPri = heatersStatus[ DG_PRIMARY_HEATER ].dutycycle > NEARLY_ZERO ? heatersStatus[ DG_PRIMARY_HEATER ].dutycycle : 1.0; - F32 smallPri = heatersStatus[ DG_PRIMARY_HEATER ].dutycycle > NEARLY_ZERO ? heatersStatus[ DG_PRIMARY_HEATER ].dutycycle : 1.0; - F32 trimmer = heatersStatus[ DG_TRIMMER_HEATER ].dutycycle > NEARLY_ZERO ? heatersStatus[ DG_TRIMMER_HEATER ].dutycycle : 1.0; + F32 mainPriDC = heatersStatus[ DG_PRIMARY_HEATER ].dutyCycle; + F32 smallPriDC = heatersStatus[ DG_PRIMARY_HEATER ].dutyCycle; + F32 trimmerDC = heatersStatus[ DG_TRIMMER_HEATER ].dutyCycle; - F32 mainPriVoltageTol = HEATERS_MAX_VOLTAGE_OUT_OF_RANGE_TOL * mainPriVoltage; - F32 smallPriVoltageTol = HEATERS_MAX_VOLTAGE_OUT_OF_RANGE_TOL * smallPriVoltage; - F32 trimmerVoltageTol = HEATERS_MAX_VOLTAGE_OUT_OF_RANGE_TOL * trimmerVoltage; + F32 mainPriExpectedVoltage = HEATERS_MAX_OPERATING_VOLTAGE_V * ( 1.0F - mainPriDC ); + F32 smallPriExpectedVoltage = HEATERS_MAX_OPERATING_VOLTAGE_V * ( 1.0F - smallPriDC ); + F32 trimmerExpectedVoltage = HEATERS_MAX_OPERATING_VOLTAGE_V * ( 1.0F - trimmerDC ); - BOOL isMainPriOut = ( fabs( ( HEATERS_MAX_OPERATING_VOLTAGE_V * mainPri ) - mainPriVoltage ) > mainPriVoltageTol ? TRUE : FALSE ); - BOOL isSmallPriOut = ( fabs( ( HEATERS_MAX_OPERATING_VOLTAGE_V * smallPri ) - smallPriVoltage ) > smallPriVoltageTol ? TRUE : FALSE ); - BOOL isTrimmerOut = ( fabs( ( HEATERS_MAX_OPERATING_VOLTAGE_V * trimmer ) - trimmerVoltage ) > trimmerVoltageTol ? TRUE : FALSE ); + BOOL isMainPriOut = ( fabs( mainPriExpectedVoltage - mainPriVoltage ) > HEATERS_VOLTAGE_TOLERANCE_V ? TRUE : FALSE ); + BOOL isSmallPriOut = ( fabs( smallPriExpectedVoltage - smallPriVoltage ) > HEATERS_VOLTAGE_TOLERANCE_V ? TRUE : FALSE ); + BOOL isTrimmerOut = ( fabs( trimmerExpectedVoltage - trimmerVoltage ) > HEATERS_VOLTAGE_TOLERANCE_V ? TRUE : FALSE ); - //checkPersistentAlarm( ALARM_ID_DG_MAIN_PRIMARY_HEATER_VOLTAGE_OUT_OF_RANGE, isMainPriOut, mainPri, mainPriVoltageTol ); - //checkPersistentAlarm( ALARM_ID_DG_SMALL_PRIMARY_HEATER_VOLTAGE_OUT_OF_RANGE, isSmallPriOut, smallPri, smallPriVoltageTol ); - //checkPersistentAlarm( ALARM_ID_DG_TRIMMER_HEATER_VOLTAGE_OUT_OF_RANGE, isTrimmerOut, trimmer, trimmerVoltageTol ); + if ( getCurrentOperationMode() != DG_MODE_INIT ) + { + checkPersistentAlarm( ALARM_ID_DG_MAIN_PRIMARY_HEATER_VOLTAGE_OUT_OF_RANGE, isMainPriOut, mainPriDC, HEATERS_VOLTAGE_TOLERANCE_V ); + checkPersistentAlarm( ALARM_ID_DG_SMALL_PRIMARY_HEATER_VOLTAGE_OUT_OF_RANGE, isSmallPriOut, smallPriDC, HEATERS_VOLTAGE_TOLERANCE_V ); + checkPersistentAlarm( ALARM_ID_DG_TRIMMER_HEATER_VOLTAGE_OUT_OF_RANGE, isTrimmerOut, trimmerDC, HEATERS_VOLTAGE_TOLERANCE_V ); + +#ifndef _RELEASE_ + if ( SW_CONFIG_ENABLE_VALUE != getSoftwareConfigStatus( SW_CONFIG_ENABLE_V3_SYSTEM ) ) +#endif + { + // If the system is DVT, check the primary heater's power line voltage + F32 powerMainPriVoltage = getMonitoredLineLevel( MONITORED_LINE_24V_POWER_PRIM_HTR_V ); + BOOL isPriPowerOut = ( fabs( powerMainPriVoltage - HEATERS_MAX_OPERATING_VOLTAGE_V ) > PRIMARY_HEATER_VOLTAGE_TOLERANCE_V ? TRUE : FALSE ); + + checkPersistentAlarm( ALARM_ID_DG_PRIMARY_HEATER_POWER_VOLTAGE_OUT_OF_RANGE, isPriPowerOut, powerMainPriVoltage, PRIMARY_HEATER_VOLTAGE_TOLERANCE_V ); + } + } } Index: firmware/App/Controllers/LoadCell.c =================================================================== diff -u -r3b70632c04247a6973960e1f37ae73eb4384a6b7 -rfc11115c26447a2da7b12f5f38ff0d4af06c579b --- firmware/App/Controllers/LoadCell.c (.../LoadCell.c) (revision 3b70632c04247a6973960e1f37ae73eb4384a6b7) +++ firmware/App/Controllers/LoadCell.c (.../LoadCell.c) (revision fc11115c26447a2da7b12f5f38ff0d4af06c579b) @@ -76,7 +76,7 @@ static OVERRIDE_U32_T loadCellDataPublishInterval = { LOAD_CELL_REPORT_PERIOD, LOAD_CELL_REPORT_PERIOD, 0, 0 }; ///< Broadcast load cell data publish interval. static LOADCELL_T loadcells[ NUM_OF_LOAD_CELLS ]; ///< Load cell data structures. -static U32 loadCellFilterTimerCount = 0; ///< Load cell filtering timer count. +static U32 loadCellFilterTimerCount; ///< Load cell filtering timer count. static U32 loadCellDataPublicationTimerCounter; ///< Load cell data publication timer counter to CAN bus. static U32 smallReadingsIdx; ///< Index for next sample in load cell small rolling average sample array. @@ -96,7 +96,7 @@ * @details Outputs: LoadCell module initialized. * @return none *************************************************************************/ - void initLoadCell( void ) +void initLoadCell( void ) { U32 i; U32 j; @@ -476,6 +476,8 @@ * @brief * The monitorLoadCellsWeightOutOfRange function monitors the weight of the * load cells and if they are not in range, it raises an alarm. + * Function must be called prior to applying tare so that un-tared weight + * is checked for out of range. * @details Inputs: none * @details Outputs: none * @param loadCell which is the load cell ID that its range is checked @@ -484,7 +486,7 @@ static void monitorLoadCellsWeightOutOfRange( LOAD_CELL_ID_T loadCell ) { F32 weight = getLoadCellSmallFilteredWeight( loadCell ); - BOOL isWeightOutOfRange = ( weight < LOAD_CELL_MIN_ALLOWED_WEIGHT_GRAMS ) || ( weight > LOAD_CELL_MAX_ALLOWED_WEIGHT_GRAMS ); + BOOL isWeightOutOfRange = ( ( weight < LOAD_CELL_MIN_ALLOWED_WEIGHT_GRAMS ) || ( weight > LOAD_CELL_MAX_ALLOWED_WEIGHT_GRAMS ) ? TRUE : FALSE ); checkPersistentAlarm( ALARM_ID_DG_LOAD_CELL_WEIGHT_OUT_OF_RANGE, isWeightOutOfRange, weight, LOAD_CELL_MAX_ALLOWED_WEIGHT_GRAMS ); } Index: firmware/App/Controllers/TemperatureSensors.c =================================================================== diff -u -r3b70632c04247a6973960e1f37ae73eb4384a6b7 -rfc11115c26447a2da7b12f5f38ff0d4af06c579b --- firmware/App/Controllers/TemperatureSensors.c (.../TemperatureSensors.c) (revision 3b70632c04247a6973960e1f37ae73eb4384a6b7) +++ firmware/App/Controllers/TemperatureSensors.c (.../TemperatureSensors.c) (revision fc11115c26447a2da7b12f5f38ff0d4af06c579b) @@ -76,15 +76,13 @@ #define CELSIUS_TO_KELVIN_CONVERSION 273.15F ///< Celsius to Kelvin temperature conversion. #define ADC_BOARD_TEMP_SENSORS_CONVERSION_CONST 272.5F ///< ADC board temperature sensors conversion constant. -#define TWELVE_BIT_RESOLUTION 4096U ///< 12 bit resolution conversion. #define ADC_BOARD_TEMP_SENSORS_CONST 0x800000 ///< ADC board temperature sensors constant. #define EXTERNAL_TEMP_SENSORS_ERROR_VALUE 0x80 ///< External temperature sensors error value. #define HEATERS_INTERNAL_TEMP_SENSOR_FAULT 0x01 ///< Heaters internal temperature sensor fault. #define TEMP_SENSORS_DATA_PUBLISH_INTERVAL ( MS_PER_SECOND / TASK_PRIORITY_INTERVAL ) ///< Temperature sensors publish data time interval. #define TEMP_SENSORS_FPGA_ERROR_TIMEOUT_MS ( 2 * MS_PER_SECOND ) ///< Temperature sensors FPGA error timeout in milliseconds. -#define FPGA_RAW_ADC_READ_INTERVAL_COUNT 8 ///< Time interval in counts to read the raw ADC reads from FPGA. #define TEMP_SENSORS_ERROR_BIT_TIMEOUT_MS ( 2 * MS_PER_SECOND ) ///< Temperature sensors error bit timeout in milliseconds. #define TEMP_SENSORS_MIN_ALLOWED_DEGREE_C 0.0F ///< Temperature sensors minimum allowed temperature in C. @@ -93,16 +91,9 @@ #define NON_FLUID_PATH_TEMP_SENSORS_MAX_ALLOWED_DEGREE_C 80.0F ///< Non fluid temperature sensors path maximum allowed temperature in C. #define TEMP_SENSORS_OUT_OF_RANGE_TIME_OUT_MS ( 5 * MS_PER_SECOND ) ///< Temperature sensor out of range persistent period in milliseconds. #define DATA_PUBLISH_COUNTER_START_COUNT 30 ///< Data publish counter start count. +#define BARO_SENSOR_REFERENCE_TEMP_C 2000 ///< Barometric sensor reference temperature in C. +#define BARO_SENSOR_WAIT_FOR_COEFF_TIME_OUT_MS ( 20 * MS_PER_SECOND ) ///< Barometric sensor wait for coefficients timeout in milliseconds. -// The count cannot be within 0.1V of the rail on both sides therefore: -// ADC count = ((2^12) - 1 / ref voltage) * voltage -// Max allowed voltage = 3.0 - 0.1 = 2.0V -// Min allowed voltage = 0.1 - 0.0 = 0.1V -// Max count = ((2^12) - 1 / ref voltage) * voltage -> ((4096 - 1)/3.0) * (3.0 - 0.1) -// Min count = ((2^12) - 1 / ref voltage) * voltage -> ((4096 - 1)/3.0) * (0.1 - 0.0) -#define TEMP_SENSORS_MAX_ALLOWED_ADC_COUNT 3959U ///< Temperature sensors max allowed ADC count. -#define TEMP_SESNORS_MIN_ALLOWED_ADC_COUNT 137U ///< Temperature sensors min allowed ADC count. - /// Temperature sensor exec states. typedef enum tempSensors_Exec_States { @@ -121,23 +112,32 @@ S32 rawADCReads[ MAX_NUM_OF_RAW_ADC_SAMPLES ]; ///< Raw ADC reads array S32 adcNextIndex; ///< Next ADC read index S32 adcRunningSum; ///< ADC running sum - U32 readCount; ///< Read counts from FPGA OVERRIDE_F32_T temperatureValues; ///< Temperature values with override F32 maxAllowedTemp; ///< Maximum allowed temperature of the sensor U32 alarmStartTime; ///< Alarm start time U08 sensorErrorBitStatus; ///< Temperature sensor error bit status BOOL fpgaErrorStatus; ///< Temperature sensor FPGA error status BOOL adcErrorStatus; ///< Temperature sensor ADC error status + S32 baroTempSnsrDiff; ///< Barometric sensor temperature difference } TEMP_SENSOR_T; +/// Barometric sensor temperature conversion +typedef struct +{ + U16 refTemperature; ///< Barometric sensor reference temperature. + U16 temperatureCoeff; ///< Barometric sensor temperature coefficient. + OVERRIDE_U32_T coeffsCRC; ///< Barometric sensor coefficients CRC. + U32 waitForCoeffStartTimeMS; ///< Barometric sensor wait for coefficients start time in milliseconds. + BOOL hasCRCBeenChecked; ///< Barometric sensor has CRC been checked flag. +} BARO_SENSOR_CONSTS_T; + // ********** private data ********** static TEMPSENSORS_EXEC_STATES_T tempSensorsExecState; ///< TemperatureSensor exec state. static TEMP_SENSOR_T tempSensors [ NUM_OF_TEMPERATURE_SENSORS ]; ///< Temperature sensors' data structure. -static U32 fpgaRawADCReadInterval; ///< FPGA raw ADC read interval count. static U32 elapsedTime; ///< Elapsed time variable. static U32 internalHeatersConversionTimer; ///< Conversion timer variable to calculate the heaters internal temperature. - +static BARO_SENSOR_CONSTS_T baroConvConsts; ///< Barometric sensor conversion constants. static U32 dataPublicationTimerCounter; ///< Temperature sensors data publish timer counter. static OVERRIDE_U32_T tempSensorsPublishInterval = { TEMP_SENSORS_DATA_PUBLISH_INTERVAL, TEMP_SENSORS_DATA_PUBLISH_INTERVAL, 0, 0 }; ///< Temperature sensors publish time interval override. @@ -162,22 +162,30 @@ }; ///< Thermocouple inverse coefficient for positive cold junction temperature. static const U32 TEMP_EQUATION_RESISTOR_CALC = 1 << ( TEMP_SENSORS_ADC_BITS - 1 ); ///< Temperature sensors resistor calculation (2^(24 - 1)). -static const F32 TEMP_EQUATION_COEFF_A = 3.9083E-3; ///< ADC to temperature conversion coefficient A. -static const F32 TEMP_EQUATION_COEFF_B = -5.775E-7; ///< ADC to temperature conversion coefficient B. +static const F32 TEMP_EQUATION_COEFF_A = 3.9083E-3; ///< ADC to temperature conversion coefficient A. +static const F32 TEMP_EQUATION_COEFF_B = -5.775E-7; ///< ADC to temperature conversion coefficient B. +static const U32 TWO_TO_POWER_OF_8 = ( 1 << 8 ); ///< 2^8. +static const U32 TWO_TO_POWER_OF_23 = ( 1 << 23 ); ///< 2^23. +// The count cannot be within 0.1V of the rail on both sides therefore: +// Maximum ADC count -> (2^24) * ( 3.0V - 0.1V ) / 3V +// Minimum ADC count -> (2^24) * ( 0.1V - 0.0V ) / 3V +static const U32 TEMP_SENSORS_MAX_ADC_COUNT = ( BITS_24_FULL_SCALE * ( 3.0F - 0.1F ) ) / 3.0F; ///< Temperature sensors max allowed ADC count. +static const U32 TEMP_SESNORS_MIN_ADC_COUNT = ( BITS_24_FULL_SCALE * ( 0.1F - 0.0F ) ) / 3.0F; ///< Temperature sensors min allowed ADC count. + // ********** private function prototypes ********** static TEMPSENSORS_EXEC_STATES_T handleExecStart( void ); static TEMPSENSORS_EXEC_STATES_T handleExecGetADCValues( void ); static F32 getADC2TempConversion( F32 avgADC, U32 gain, U32 refResistance, U32 zeroDegResistance, F32 adcConversionCoeff ); static void getHeaterInternalTemp( U32 TCIndex, U32 CJIndex ); -static void processTempSnsrsADCRead( U32 sensorIndex, U32 adc, U32 fpgaError, U32 fpgaCount, BOOL fpgaCheck ); -static void processHtrsTempSnsrsADCRead( U32 sensorIndex, U16 adc, U32 fpgaError, U32 fpgaCount ); -static BOOL isADCReadValid( U32 sensorIndex, U32 fpgaError, U32 fpgaCount ); +static void processTempSnsrsADCRead( U32 sensorIndex, U32 adc ); +static void processHtrsTempSnsrsADCRead( U32 sensorIndex, U16 adc ); static void processADCRead( U32 sensorIndex, S32 adc ); static void publishTemperatureSensorsData( void ); static void monitorTemperatureSenors( void ); +static void checkBaroSensorCRC( void ); static void adjustTemperatureSensorsRefResistance( void ); /*********************************************************************//** @@ -186,20 +194,20 @@ * @details Inputs: none * @details Outputs: tempSensorsSelfTestState, tempSensorsExecState, * elapsedTime, internalHeatersConversionTimer, dataPublicationTimerCounter, - * tempSensors, fpgaRawADCReadInterval + * tempSensors, baroConvConsts * @return none *************************************************************************/ void initTemperatureSensors( void ) { U08 i; + tempSensorsExecState = TEMPSENSORS_EXEC_STATE_START; + elapsedTime = 0; + internalHeatersConversionTimer = 0; + dataPublicationTimerCounter = DATA_PUBLISH_COUNTER_START_COUNT; + baroConvConsts.coeffsCRC.data = 0; + baroConvConsts.hasCRCBeenChecked = FALSE; + baroConvConsts.waitForCoeffStartTimeMS = 0; - // Initialize the variables - tempSensorsExecState = TEMPSENSORS_EXEC_STATE_START; - elapsedTime = 0; - internalHeatersConversionTimer = 0; - dataPublicationTimerCounter = DATA_PUBLISH_COUNTER_START_COUNT; - fpgaRawADCReadInterval = 0; - /* NOTE: The temperature sensors do not have conversion coefficient. * The conversion coefficients are used for the heaters internal temperature sensors and * the temperature will be calculated using a quadratic equation @@ -214,6 +222,9 @@ benignPolynomialCalRecord( &tempSensorCalRecord.tempSensors[ i ] ); } + // Initialize the barometric sensor's temperature conversion constants + memset( &baroConvConsts, 0x0, sizeof( BARO_SENSOR_CONSTS_T ) ); + // Initialize TPi, THd, and TPo constants tempSensors[ TEMPSENSORS_INLET_PRIMARY_HEATER ].gain = PRIMARY_HEATER_EXT_TEMP_SENSORS_GAIN; tempSensors[ TEMPSENSORS_INLET_PRIMARY_HEATER ].refResistance = PRIMARY_HEATER_EXT_TEMP_SENSORS_REF_RESISTANCE; @@ -269,7 +280,7 @@ tempSensors[ TEMPSENSORS_TRIMMER_HEATER_INTERNAL ].maxAllowedTemp = HEATERS_INTERNAL_TEMP_SENSORS_MAX_ALLOWED_DEGREE_C; // FPGA board temperature conversion coefficient - tempSensors[ TEMPSENSORS_FPGA_BOARD_SENSOR ].conversionCoeff = 503.975 / (F32)TWELVE_BIT_RESOLUTION; + tempSensors[ TEMPSENSORS_FPGA_BOARD_SENSOR ].conversionCoeff = 503.975 / (F32)BITS_12_FULL_SCALE; tempSensors[ TEMPSENSORS_FPGA_BOARD_SENSOR ].maxAllowedTemp = NON_FLUID_PATH_TEMP_SENSORS_MAX_ALLOWED_DEGREE_C; F32 conversionCoeff = 1.0 / 13584.0; @@ -308,10 +319,12 @@ // Persistent alarm for the temperature sensors error bit fault check initPersistentAlarm( ALARM_ID_DG_TEMPERATURE_SENSOR_ERROR_BIT_FAULT, TEMP_SENSORS_ERROR_BIT_TIMEOUT_MS, TEMP_SENSORS_ERROR_BIT_TIMEOUT_MS ); - // Persistent alarm for temperature sensors ADC error - // When the FPGA read count does not increment for a period of time, it is considered as an internal error of the temperature sensors - // driver. This is internal because FPGA does not error out if the FPGA read count does not increment. - initPersistentAlarm( ALARM_ID_DG_TEMPERATURE_SENSORS_FPGA_FAULT, TEMP_SENSORS_FPGA_ERROR_TIMEOUT_MS, TEMP_SENSORS_FPGA_ERROR_TIMEOUT_MS ); + // Initialize the FPGA persistent alarms + initFPGAPersistentAlarm( TWO_WIRE_ADC_TEMP_SENSORS, ALARM_ID_DG_TWO_WIRE_SENSORS_FPGA_FAULT, TEMP_SENSORS_FPGA_ERROR_TIMEOUT_MS, TEMP_SENSORS_FPGA_ERROR_TIMEOUT_MS); + initFPGAPersistentAlarm( THD_ADC_TEMP_SENSORS, ALARM_ID_DG_THD_SENSORS_FPGA_FAULT, TEMP_SENSORS_FPGA_ERROR_TIMEOUT_MS, TEMP_SENSORS_FPGA_ERROR_TIMEOUT_MS); + initFPGAPersistentAlarm( TDI_ADC_TEMP_SENSORS, ALARM_ID_DG_TDI_SENSORS_FPGA_FAULT, TEMP_SENSORS_FPGA_ERROR_TIMEOUT_MS, TEMP_SENSORS_FPGA_ERROR_TIMEOUT_MS); + initFPGAPersistentAlarm( TRO_ADC_TEMP_SENSORS, ALARM_ID_DG_TRO_SENSORS_FPGA_FAULT, TEMP_SENSORS_FPGA_ERROR_TIMEOUT_MS, TEMP_SENSORS_FPGA_ERROR_TIMEOUT_MS); + initFPGAPersistentAlarm( BARO_SENSOR, ALARM_ID_DG_BARO_SENSOR_FPGA_FAULT, TEMP_SENSORS_FPGA_ERROR_TIMEOUT_MS, TEMP_SENSORS_FPGA_ERROR_TIMEOUT_MS); } /*********************************************************************//** @@ -443,10 +456,34 @@ // the electrical connection of THd sensor. if ( SW_CONFIG_ENABLE_VALUE == getSoftwareConfigStatus( SW_CONFIG_ENABLE_V3_SYSTEM ) ) { - if ( ( TEMPSENSORS_HEAT_DISINFECT == sensorIndex ) || ( TEMPSENSORS_INTERNAL_THD_RTD == sensorIndex ) ) + if ( TEMPSENSORS_HEAT_DISINFECT == sensorIndex ) { - temperature = getF32OverrideValue( &tempSensors[ TEMPSENSORS_OUTLET_REDUNDANT ].temperatureValues ); + if ( OVERRIDE_KEY == tempSensors[ TEMPSENSORS_HEAT_DISINFECT ].temperatureValues.override ) + { + temperature = getF32OverrideValue( &tempSensors[ TEMPSENSORS_HEAT_DISINFECT ].temperatureValues ); + } + else + { + temperature = getF32OverrideValue( &tempSensors[ TEMPSENSORS_OUTLET_REDUNDANT ].temperatureValues ); + } } + + if ( TEMPSENSORS_INTERNAL_THD_RTD == sensorIndex ) + { + temperature = 40.0F; + } + + if ( TEMPSENSORS_OUTLET_REDUNDANT == sensorIndex ) + { + if ( OVERRIDE_KEY == tempSensors[ TEMPSENSORS_OUTLET_REDUNDANT ].temperatureValues.override ) + { + temperature = getF32OverrideValue( &tempSensors[ TEMPSENSORS_OUTLET_REDUNDANT ].temperatureValues ); + } + else + { + temperature = getF32OverrideValue( &tempSensors[ TEMPSENSORS_INLET_DIALYSATE ].temperatureValues ); + } + } } #endif } @@ -461,6 +498,19 @@ /*********************************************************************//** * @brief + * The getBaroSensorTemperatureDiff function returns the barometric pressure + * sensor's temperature difference. + * @details Inputs: tempSensors + * @details Outputs: none + * @return barometric pressure sensor temperature difference + *************************************************************************/ +S32 getBaroSensorTemperatureDiff( void ) +{ + return tempSensors[ TEMPSENSORS_BAROMETRIC_TEMP_SENSOR ].baroTempSnsrDiff; +} + +/*********************************************************************//** + * @brief * The getADC2TempConversion function calculates the temperature from the * moving average ADC samples. * @details Inputs: tempEquationCoeffA, tempEquationCoeffB @@ -565,46 +615,33 @@ * @details Outputs: none * @param sensorIndex ID of temperature sensor to process * @param adc ADC value for the temperature sensor - * @param fpgaError reported FPGA error status - * @param fpgaCount reported FPGA read count - * @param fpgaCheck whether to check the FPGA error and count prior to converting - * the ADC to temperature * @return none *************************************************************************/ -static void processTempSnsrsADCRead( U32 sensorIndex, U32 adc, U32 fpgaError, U32 fpgaCount, BOOL fpgaCheck ) +static void processTempSnsrsADCRead( U32 sensorIndex, U32 adc ) { - BOOL isADCValid = TRUE; S32 convertedADC = (S32)( adc & MASK_OFF_U32_MSB ); - if ( TRUE == fpgaCheck ) - { - // All the sensors have ADC read and count values that have to be checked - // but the FPGA read and error counts are shared among some of the sensors so if that counts has been checked - // once, do not check it again - isADCValid = isADCReadValid( sensorIndex, fpgaError, fpgaCount ); - } - - // Some of the temperature sensors have an MSB bit that is used as an - // error flag. This flag will be a TRUE by default. - BOOL isTemperatureNotValid = FALSE; - switch( sensorIndex ) { - case TEMPSENSORS_LOAD_CELL_A1_B1: // 267 - case TEMPSENSORS_LOAD_CELL_A2_B2: // 279 - case TEMPSENSORS_CONDUCTIVITY_SENSOR_1: // 283 - case TEMPSENSORS_CONDUCTIVITY_SENSOR_2: // 287 - case TEMPSENSORS_OUTLET_PRIMARY_HEATER: // 291 - case TEMPSENSORS_INLET_PRIMARY_HEATER: // 295 - case TEMPSENSORS_INTERNAL_COND_TEMP_SENSOR: // 299 - case TEMPSENSORS_OUTLET_REDUNDANT: // 303 - case TEMPSENSORS_INTERNAL_TRO_RTD: // 307 - case TEMPSENSORS_INLET_DIALYSATE: // 311 - case TEMPSENSORS_INTERNAL_TDI_RTD: // 315 + case TEMPSENSORS_LOAD_CELL_A1_B1: + case TEMPSENSORS_LOAD_CELL_A2_B2: + case TEMPSENSORS_CONDUCTIVITY_SENSOR_1: + case TEMPSENSORS_CONDUCTIVITY_SENSOR_2: + case TEMPSENSORS_OUTLET_PRIMARY_HEATER: + case TEMPSENSORS_INLET_PRIMARY_HEATER: + case TEMPSENSORS_INTERNAL_COND_TEMP_SENSOR: + case TEMPSENSORS_OUTLET_REDUNDANT: + case TEMPSENSORS_INTERNAL_TRO_RTD: + case TEMPSENSORS_INLET_DIALYSATE: + case TEMPSENSORS_INTERNAL_TDI_RTD: case TEMPSENSORS_HEAT_DISINFECT: case TEMPSENSORS_INTERNAL_THD_RTD: { U08 i; + // Some of the temperature sensors have an MSB bit that is used as an + // error flag. This flag will be a TRUE by default. + BOOL isErrorBitNotValid = FALSE; + U32 faultySensorIndex = 0; // Shift bits by 31 to right to check the error bit status tempSensors[ sensorIndex ].sensorErrorBitStatus = adc >> SHIFT_BITS_BY_31; @@ -613,22 +650,17 @@ { // If that bit is a 1, there is either CRC error or Status error that are ored on top of each other // NOTE: only a few sensors have the error bit available but for simplicity, all the sensors are looped. - // This variable is zeroed in the init function and the sensors that do not use this bit are never checked ( and set) to + // This variable is zeroed in the init function and the sensors that do not use this bit are never checked (and set) to // any other values so those sensors will never trigger this fault. // If any of the sensors have this bit to be 1, set the error occurred be 1 - isTemperatureNotValid |= ( tempSensors[ i ].sensorErrorBitStatus > 0 ? TRUE : FALSE ); + if ( tempSensors[ i ].sensorErrorBitStatus > 0 ) + { + isErrorBitNotValid = TRUE; + faultySensorIndex = i; + } } -#ifndef DISABLE_FPGA_ALARMS_UNTIL_THE_NEW_PERSISTENT - // TODO for debugging only remove - if ( TRUE == isTemperatureNotValid ) - { - BOOL test = FALSE; - } - // TODO remove for debugging only - - checkPersistentAlarm( ALARM_ID_DG_TEMPERATURE_SENSOR_ERROR_BIT_FAULT, isTemperatureNotValid, sensorIndex, TEMP_SENSORS_ERROR_BIT_TIMEOUT_MS ); -#endif + checkPersistentAlarm( ALARM_ID_DG_TEMPERATURE_SENSOR_ERROR_BIT_FAULT, isErrorBitNotValid, faultySensorIndex, TEMP_SENSORS_ERROR_BIT_TIMEOUT_MS ); } break; @@ -639,12 +671,7 @@ break; } - // To update the moving average of a temperature sensor, both ADC and internal - // error flags must be valid - if ( ( TRUE == isADCValid ) && ( FALSE == isTemperatureNotValid ) ) - { - processADCRead( sensorIndex, convertedADC ); - } + processADCRead( sensorIndex, convertedADC ); } /*********************************************************************//** @@ -658,65 +685,16 @@ * @details Outputs: none * @param sensorIndex ID of temperature sensor to process * @param adc reported ADC value for temperature sensor - * @param fpgaError reported error status by FPGA - * @param fpgaCount reported read count by FPGA * @return none *************************************************************************/ -static void processHtrsTempSnsrsADCRead( U32 sensorIndex, U16 adc, U32 fpgaError, U32 fpgaCount ) +static void processHtrsTempSnsrsADCRead( U32 sensorIndex, U16 adc ) { - if ( TRUE == isADCReadValid( sensorIndex, fpgaError, fpgaCount ) ) - { - S16 convert = (S16)adc; - processADCRead( sensorIndex, (S32)convert ); - } + S16 convert = (S16)adc; + processADCRead( sensorIndex, (S32)convert ); } /*********************************************************************//** * @brief - * The isADCReadValid function checks if there is an FPGA error and FPGA - * count. If there is any FPGA, it raises an alarm. If the count has changed - * and the ADC value is not the same as the previous ADC read, it returns a - * TRUE, signaling that the ADC is valid to be processed. - * @details Inputs: tempSensors - * @details Outputs: tempSensors - * @param sensorIndex Temperature sensor index - * @param fpgaError FPGA error count - * @param fpgaCount FPGA read count - * @return returns TRUE if ADC was valid otherwise FALSE - *************************************************************************/ -static BOOL isADCReadValid( U32 sensorIndex, U32 fpgaError, U32 fpgaCount ) -{ - U08 i; - BOOL isADCValid = FALSE; - BOOL isTemperatureNotValid = FALSE; - // Check the status of FPGA error and FPGA count - BOOL isFPGAErrorZero = ( 0 == fpgaError ? TRUE : FALSE ); - BOOL isFPGACountChanging = ( tempSensors[ sensorIndex ].readCount != fpgaCount ? TRUE : FALSE ); - - if ( ( TRUE == isFPGAErrorZero ) && ( TRUE == isFPGACountChanging ) ) - { - tempSensors[ sensorIndex ].readCount = fpgaCount; - isADCValid = TRUE; - } - - tempSensors[ sensorIndex ].fpgaErrorStatus = ( ( FALSE == isFPGACountChanging ) || ( FALSE == isFPGAErrorZero ) ? TRUE : FALSE ); - - for ( i = 0; i < NUM_OF_TEMPERATURE_SENSORS; i++ ) - { - // Loop through all the sensors and read their FPGA error status - isTemperatureNotValid |= tempSensors[ sensorIndex ].fpgaErrorStatus; - } -#ifndef DISABLE_FPGA_ALARMS_UNTIL_THE_NEW_PERSISTENT - checkPersistentAlarm( ALARM_ID_DG_TEMPERATURE_SENSORS_FPGA_FAULT, isTemperatureNotValid, sensorIndex, TEMP_SENSORS_FPGA_ERROR_TIMEOUT_MS ); - - return isADCValid; -#else - return TRUE; -#endif -} - -/*********************************************************************//** - * @brief * The processADCRead function receives the ADC value and the sensor * index and calculates the running sum and the moving average of the ADCs * The temperatureSensorsADCRead and tempSensorsAvgADCValues are updated. @@ -742,17 +720,16 @@ avgADCReads = tempSensors[ sensorIndex ].adcRunningSum >> SHIFT_BITS_BY_2_FOR_AVERAGING; // Calculate the average // Check if the average ADC is within the accepted range - tempSensors[ sensorIndex ].adcErrorStatus = ( ( (U32)avgADCReads < TEMP_SESNORS_MIN_ALLOWED_ADC_COUNT ) || - ( (U32)avgADCReads > TEMP_SENSORS_MAX_ALLOWED_ADC_COUNT ) ? TRUE : FALSE ); + tempSensors[ sensorIndex ].adcErrorStatus = ( ( (U32)avgADCReads < TEMP_SESNORS_MIN_ADC_COUNT ) || + ( (U32)avgADCReads > TEMP_SENSORS_MAX_ADC_COUNT ) ? TRUE : FALSE ); for ( i = 0; i < NUM_OF_TEMPERATURE_SENSORS; i++ ) { // Loop through the ADC errors isADCNotValid |= tempSensors[ sensorIndex ].adcErrorStatus; } -#ifndef DISABLE_FPGA_ALARMS_UNTIL_THE_NEW_PERSISTENT + checkPersistentAlarm( ALARM_ID_DG_TEMPERATURE_SENSORS_ADC_FAULT, isADCNotValid, sensorIndex, avgADCReads ); -#endif // Different sensors have different ADC to temperature conversion methods switch( sensorIndex ) @@ -775,7 +752,7 @@ case TEMPSENSORS_FPGA_BOARD_SENSOR: // Temperature(C) = ((ADC x 503.975) / 4096) - 273.15 // The value of 503.975/4096 has been calculated and stored in the conversion coefficient variable of the structure - temperature = ( avgADCReads * tempSensors[ sensorIndex ].conversionCoeff ) - CELSIUS_TO_KELVIN_CONVERSION; + temperature = ( avgADCReads * tempSensors[ sensorIndex ].conversionCoeff ) - CELSIUS_TO_KELVIN_CONVERSION; break; case TEMPSENSORS_LOAD_CELL_A1_B1: @@ -791,7 +768,12 @@ break; case TEMPSENSORS_BAROMETRIC_TEMP_SENSOR: - temperature = 30.0; + { + tempSensors[ sensorIndex ].baroTempSnsrDiff = (S32)avgADCReads - ( baroConvConsts.refTemperature * TWO_TO_POWER_OF_8 ); + U64 baroSnsrTemperature = BARO_SENSOR_REFERENCE_TEMP_C + ( ( tempSensors[ sensorIndex ].baroTempSnsrDiff * + baroConvConsts.temperatureCoeff ) / TWO_TO_POWER_OF_23 ); + temperature = (F32)( (U32)( baroSnsrTemperature ) / 100 ); + } break; default: @@ -811,7 +793,7 @@ * The handleExecStart function waits for a period of time and switches to * the state that reads the ADC values from FPGA. * @details Inputs: elapsedTime - * @details Outputs: elapsedTime + * @details Outputs: elapsedTime, baroCoeffsWaitToRcvStartTime * @return the next state of the state machine *************************************************************************/ static TEMPSENSORS_EXEC_STATES_T handleExecStart( void ) @@ -825,8 +807,9 @@ // A delay to let FPGA to boot up else if ( TRUE == didTimeout( elapsedTime, ADC_FPGA_READ_DELAY ) ) { - elapsedTime = 0; - state = TEMPSENSORS_EXEC_STATE_GET_ADC_VALUES; + elapsedTime = 0; + baroConvConsts.waitForCoeffStartTimeMS = getMSTimerCount(); + state = TEMPSENSORS_EXEC_STATE_GET_ADC_VALUES; } return state; @@ -846,66 +829,72 @@ U32 errorCount = 0; U32 readCount = 0; - // Look at the error counter and the specific error flag to make sure the error is a temperature sensor - // Add a byte array to have bits for each sensor to find out exactly what sensor failed - if ( ++fpgaRawADCReadInterval >= FPGA_RAW_ADC_READ_INTERVAL_COUNT ) - { - errorCount = (U32)getFPGARTDErrorCount(); - readCount = (U32)getFPGARTDReadCount(); - processTempSnsrsADCRead( TEMPSENSORS_INLET_PRIMARY_HEATER, getFPGATPiTemp(), errorCount, readCount, TRUE ); - processTempSnsrsADCRead( TEMPSENSORS_OUTLET_PRIMARY_HEATER, getFPGATPoTemp(), errorCount, readCount, FALSE ); - processTempSnsrsADCRead( TEMPSENSORS_CONDUCTIVITY_SENSOR_1, getFPGACD1Temp(), errorCount, readCount, FALSE ); - processTempSnsrsADCRead( TEMPSENSORS_CONDUCTIVITY_SENSOR_2, getFPGACD2Temp(), errorCount, readCount, FALSE ); + errorCount = (U32)getFPGARTDErrorCount(); + readCount = (U32)getFPGARTDReadCount(); + checkFPGAPersistentAlarms( TWO_WIRE_ADC_TEMP_SENSORS, errorCount, readCount ); + processTempSnsrsADCRead( TEMPSENSORS_INLET_PRIMARY_HEATER, getFPGATPiTemp() ); + processTempSnsrsADCRead( TEMPSENSORS_OUTLET_PRIMARY_HEATER, getFPGATPoTemp() ); + processTempSnsrsADCRead( TEMPSENSORS_CONDUCTIVITY_SENSOR_1, getFPGACD1Temp() ); + processTempSnsrsADCRead( TEMPSENSORS_CONDUCTIVITY_SENSOR_2, getFPGACD2Temp() ); + processTempSnsrsADCRead( TEMPSENSORS_INTERNAL_COND_TEMP_SENSOR, getFPGACondSnsrInternalTemp() ); + #ifndef _RELEASE_ - if ( ( getSoftwareConfigStatus( SW_CONFIG_ENABLE_V3_SYSTEM ) != SW_CONFIG_ENABLE_VALUE ) && ( getCurrentOperationMode() != DG_MODE_INIT ) ) + if ( ( getSoftwareConfigStatus( SW_CONFIG_ENABLE_V3_SYSTEM ) != SW_CONFIG_ENABLE_VALUE ) && ( getCurrentOperationMode() != DG_MODE_INIT ) ) #endif - { - errorCount = (U32)getFPGATHdErrorCount(); - readCount = (U32)getFPGATHdReadCount(); - processTempSnsrsADCRead( TEMPSENSORS_HEAT_DISINFECT, getFPGATHdTemp(), errorCount, readCount, TRUE ); - processTempSnsrsADCRead( TEMPSENSORS_INTERNAL_THD_RTD, getFPGATHdInternalTemp(), errorCount, readCount, FALSE ); - } + { + errorCount = (U32)getFPGATHdErrorCount(); + readCount = (U32)getFPGATHdReadCount(); - errorCount = (U32)getFPGATRoErrorCount(); - readCount = (U32)getFPGATRoReadCount(); - processTempSnsrsADCRead( TEMPSENSORS_OUTLET_REDUNDANT, getFPGATRoTemp(), errorCount, readCount, TRUE ); + checkFPGAPersistentAlarms( THD_ADC_TEMP_SENSORS, errorCount, readCount ); + processTempSnsrsADCRead( TEMPSENSORS_HEAT_DISINFECT, getFPGATHdTemp() ); + processTempSnsrsADCRead( TEMPSENSORS_INTERNAL_THD_RTD, getFPGATHdInternalTemp() ); - errorCount = (U32)getFPGATDiErrorCount(); - readCount = (U32)getFPGATDiReadCount(); - processTempSnsrsADCRead( TEMPSENSORS_INLET_DIALYSATE, getFPGATDiTemp(), errorCount, readCount, TRUE ); + // Make sure the baro sensor coefficients are not corrupted + checkBaroSensorCRC(); - errorCount = (U32)getFPGAPrimaryHeaterFlags(); - readCount = (U32)getFPGAPrimaryHeaterReadCount(); - processHtrsTempSnsrsADCRead( TEMPSENSORS_PRIMARY_HEATER_THERMO_COUPLE, getFPGAPrimaryHeaterTemp(), errorCount, readCount ); - processHtrsTempSnsrsADCRead( TEMPSENSORS_PRIMARY_HEATER_COLD_JUNCTION, getFPGAPrimaryColdJunctionTemp(), errorCount, readCount ); + baroConvConsts.refTemperature = getFPGABaroReferenceTemperature(); + baroConvConsts.temperatureCoeff = getFPGABaroTempCoeffOfTemperature(); + errorCount = getFPGABaroErrorCount(); + readCount = getFPGABaroReadCount(); - errorCount = (U32)getFPGATrimmerHeaterFlags(); - readCount = (U32)getFPGATrimmerHeaterReadCount(); - processHtrsTempSnsrsADCRead( TEMPSENSORS_TRIMMER_HEATER_THERMO_COUPLE, getFPGATrimmerHeaterTemp(), errorCount, readCount ); - processHtrsTempSnsrsADCRead( TEMPSENSORS_TRIMMER_HEATER_COLD_JUNCTION, getFPGATrimmerColdJunctionTemp(), errorCount, readCount ); + checkFPGAPersistentAlarms( BARO_SENSOR, errorCount, readCount ); + processTempSnsrsADCRead( TEMPSENSORS_BAROMETRIC_TEMP_SENSOR, getFPGABaroTemperature() ); + } - // NOTE: FPGA board temperature sensor is different from the rest of the sensors. This sensor does not have FPGA count and error - // coming from FPGA. It is kept here to do moving average on the values. The supporting functions need to see the FPGA read count - // incrementing internally so there will not be any errors. - U32 simulatedCounter = tempSensors[ TEMPSENSORS_FPGA_BOARD_SENSOR ].readCount; - processTempSnsrsADCRead( TEMPSENSORS_FPGA_BOARD_SENSOR, getFPGABoardTemp(), 0, ++simulatedCounter, TRUE ); - processTempSnsrsADCRead( TEMPSENSORS_LOAD_CELL_A1_B1, getFPGALoadCellsA1B1Temp(), getFPGAADC1ErrorCount(), getFPGAADC1ReadCount(), TRUE ); - processTempSnsrsADCRead( TEMPSENSORS_LOAD_CELL_A2_B2, getFPGALoadCellsA2B2Temp(), getFPGAADC2ErrorCount(), getFPGAADC2ReadCount(), TRUE ); - processTempSnsrsADCRead( TEMPSENSORS_INTERNAL_TRO_RTD, getFPGATRoInternalTemp(), getFPGATRoErrorCount(), getFPGATRoReadCount(), TRUE ); - processTempSnsrsADCRead( TEMPSENSORS_INTERNAL_TDI_RTD, getFPGATDiInternalTemp(), getFPGATDiErrorCount(), getFPGATDiReadCount(), TRUE ); - processTempSnsrsADCRead( TEMPSENSORS_INTERNAL_COND_TEMP_SENSOR, getFPGACondSnsrInternalTemp(), getFPGARTDErrorCount(), getFPGARTDReadCount(), TRUE ); - processTempSnsrsADCRead( TEMPSENSORS_BAROMETRIC_TEMP_SENSOR, getFPGABaroTemperature(), getFPGABaroErrorCount(), getFPGABaroReadCount(), TRUE ); + errorCount = (U32)getFPGATRoErrorCount(); + readCount = (U32)getFPGATRoReadCount(); - // Check if time has elapsed to calculate the internal temperature of the heaters - if ( ++internalHeatersConversionTimer >= HEATERS_INTERNAL_TEMPERTURE_CALCULATION_INTERVAL ) - { - getHeaterInternalTemp( TEMPSENSORS_PRIMARY_HEATER_THERMO_COUPLE, TEMPSENSORS_PRIMARY_HEATER_COLD_JUNCTION ); - getHeaterInternalTemp( TEMPSENSORS_TRIMMER_HEATER_THERMO_COUPLE, TEMPSENSORS_TRIMMER_HEATER_COLD_JUNCTION ); - internalHeatersConversionTimer = 0; - } + checkFPGAPersistentAlarms( TRO_ADC_TEMP_SENSORS, errorCount, readCount ); + processTempSnsrsADCRead( TEMPSENSORS_OUTLET_REDUNDANT, getFPGATRoTemp() ); + processTempSnsrsADCRead( TEMPSENSORS_INTERNAL_TRO_RTD, getFPGATRoInternalTemp() ); - fpgaRawADCReadInterval = 0; + errorCount = (U32)getFPGATDiErrorCount(); + readCount = (U32)getFPGATDiReadCount(); + + checkFPGAPersistentAlarms( TDI_ADC_TEMP_SENSORS, errorCount, readCount ); + processTempSnsrsADCRead( TEMPSENSORS_INLET_DIALYSATE, getFPGATDiTemp() ); + processTempSnsrsADCRead( TEMPSENSORS_INTERNAL_TDI_RTD, getFPGATDiInternalTemp() ); + + // The heaters' temperature sensors have read and error counts but the heaters' internal sensors are only updated for information + // and no alarm shall be raised on them including the read and error counts + processHtrsTempSnsrsADCRead( TEMPSENSORS_PRIMARY_HEATER_THERMO_COUPLE, getFPGAPrimaryHeaterTemp() ); + processHtrsTempSnsrsADCRead( TEMPSENSORS_PRIMARY_HEATER_COLD_JUNCTION, getFPGAPrimaryColdJunctionTemp() ); + processHtrsTempSnsrsADCRead( TEMPSENSORS_TRIMMER_HEATER_THERMO_COUPLE, getFPGATrimmerHeaterTemp() ); + processHtrsTempSnsrsADCRead( TEMPSENSORS_TRIMMER_HEATER_COLD_JUNCTION, getFPGATrimmerColdJunctionTemp() ); + + // The FPGA board sensor does not have read and error count. + // The load cells' temperature sensors are not read and a constant value is reported to firmware by FPGA + processTempSnsrsADCRead( TEMPSENSORS_FPGA_BOARD_SENSOR, getFPGABoardTemp() ); + processTempSnsrsADCRead( TEMPSENSORS_LOAD_CELL_A1_B1, getFPGALoadCellsA1B1Temp() ); + processTempSnsrsADCRead( TEMPSENSORS_LOAD_CELL_A2_B2, getFPGALoadCellsA2B2Temp() ); + + // Check if time has elapsed to calculate the internal temperature of the heaters + if ( ++internalHeatersConversionTimer >= HEATERS_INTERNAL_TEMPERTURE_CALCULATION_INTERVAL ) + { + getHeaterInternalTemp( TEMPSENSORS_PRIMARY_HEATER_THERMO_COUPLE, TEMPSENSORS_PRIMARY_HEATER_COLD_JUNCTION ); + getHeaterInternalTemp( TEMPSENSORS_TRIMMER_HEATER_THERMO_COUPLE, TEMPSENSORS_TRIMMER_HEATER_COLD_JUNCTION ); + internalHeatersConversionTimer = 0; } return TEMPSENSORS_EXEC_STATE_GET_ADC_VALUES; @@ -945,12 +934,6 @@ data.internalTDIRTD = getTemperatureValue( TEMPSENSORS_INTERNAL_TDI_RTD ); data.interalTHDRTD = getTemperatureValue( TEMPSENSORS_INTERNAL_THD_RTD ); data.internalCondSnsrTemp = getTemperatureValue( TEMPSENSORS_INTERNAL_COND_TEMP_SENSOR ); - data.primaryThermoCoupleRaw = getFPGAPrimaryHeaterTemp(); - data.primaryColdjuncRaw = getFPGAPrimaryColdJunctionTemp(); - data.trimmerThermoCoupleRaw = getFPGATrimmerHeaterTemp(); - data.trimmerColdjuncRaw = getFPGATrimmerColdJunctionTemp(); - data.cond1Raw = tempSensors[ TEMPSENSORS_CONDUCTIVITY_SENSOR_1 ].rawADCReads[ MAX_NUM_OF_RAW_ADC_SAMPLES - 1 ]; - data.cond2Raw = tempSensors[ TEMPSENSORS_CONDUCTIVITY_SENSOR_2 ].rawADCReads[ MAX_NUM_OF_RAW_ADC_SAMPLES - 1 ]; broadcastData( MSG_ID_DG_TEMPERATURE_DATA, COMM_BUFFER_OUT_CAN_DG_BROADCAST, (U08*)&data, sizeof( TEMPERATURE_SENSORS_DATA_T ) ); dataPublicationTimerCounter = 0; @@ -975,20 +958,48 @@ U08 i; F32 temperature = 0.0; BOOL isTemperatureOutOfRange = FALSE; + F32 alarmTemperature = 0.0; + U08 alarmIndex = 0; for ( i = 0; i < NUM_OF_TEMPERATURE_SENSORS; i++ ) { - temperature = getTemperatureValue( i ); - - // Check both temperature and to be in range - if ( ( ( temperature < TEMP_SENSORS_MIN_ALLOWED_DEGREE_C ) || ( temperature > tempSensors[ i ].maxAllowedTemp ) ) && - ( getCurrentOperationMode() != DG_MODE_INIT ) ) + switch ( i ) { - isTemperatureOutOfRange |= TRUE; + case TEMPSENSORS_INLET_PRIMARY_HEATER: + case TEMPSENSORS_HEAT_DISINFECT: + case TEMPSENSORS_OUTLET_PRIMARY_HEATER: + case TEMPSENSORS_CONDUCTIVITY_SENSOR_1: + case TEMPSENSORS_CONDUCTIVITY_SENSOR_2: + case TEMPSENSORS_OUTLET_REDUNDANT: + case TEMPSENSORS_INLET_DIALYSATE: + case TEMPSENSORS_FPGA_BOARD_SENSOR: + case TEMPSENSORS_LOAD_CELL_A1_B1: + case TEMPSENSORS_LOAD_CELL_A2_B2: + case TEMPSENSORS_INTERNAL_TRO_RTD: + case TEMPSENSORS_INTERNAL_TDI_RTD: + case TEMPSENSORS_INTERNAL_THD_RTD: + case TEMPSENSORS_INTERNAL_COND_TEMP_SENSOR: + case TEMPSENSORS_BAROMETRIC_TEMP_SENSOR: + temperature = getTemperatureValue( i ); + + // Check both temperature and to be in range + if ( ( ( temperature < TEMP_SENSORS_MIN_ALLOWED_DEGREE_C ) || ( temperature > tempSensors[ i ].maxAllowedTemp ) ) && + ( getCurrentOperationMode() != DG_MODE_INIT ) ) + { + isTemperatureOutOfRange |= TRUE; + alarmIndex = i; + alarmTemperature = temperature; + } + break; + + default: + // Ignore the rest of the sensors + break; } + } - //checkPersistentAlarm( ALARM_ID_DG_TEMPERATURE_SENSOR_OUT_OF_RANGE, isTemperatureOutOfRange, i, temperature ); + checkPersistentAlarm( ALARM_ID_DG_TEMPERATURE_SENSOR_OUT_OF_RANGE, isTemperatureOutOfRange, alarmIndex, alarmTemperature ); } } @@ -1002,7 +1013,7 @@ *************************************************************************/ static void adjustTemperatureSensorsRefResistance( void ) { - // The default are DVT changes + // The defaults are DVT values U32 primaryAndCondSensorsRefResistance = PRIMARY_HEATER_EXT_TEMP_SENSORS_REF_RESISTANCE; U32 externalTempSesnorsRefResitance = TRIMMER_HEATER_EXT_TEMP_SENSORS_REF_RESISTANCE; @@ -1026,7 +1037,61 @@ tempSensors[ TEMPSENSORS_INLET_DIALYSATE ].refResistance = externalTempSesnorsRefResitance; } +/*********************************************************************//** + * @brief + * The checkBaroSensorCRC function gets all the barometric sensor coefficients + * and calls crc4 function to calculate the CRC of the coefficients and compares + * them to the provided CRC by the manufacturer. + * @details Inputs: hasBaroCoeffsBeenChecked + * @details Outputs: hasBaroCoeffsBeenChecked + * @return none + *************************************************************************/ +static void checkBaroSensorCRC( void ) +{ + U32 baroCRC = (U32)getFPGABaroCoeffsCRC(); + BOOL hasCRCChanged = ( baroCRC != getU32OverrideValue( &baroConvConsts.coeffsCRC ) ? TRUE : FALSE ); + // Once FPGA is ready get the barometric sensor's temperature conversion constants + if ( TRUE == hasCRCChanged ) + { + U08 calculatedCRC; + struct + { + U16 mfgInfo; + U16 pressSensitivity; + U16 pressOffset; + U16 tempCoeffOfPressSens; + U16 tempCoeffPressOffset; + U16 referenceTemp; + U16 tempCoeffOfTemp; + U16 crc; + } baroCoeffs; + + baroCoeffs.mfgInfo = getFPGABaroMfgInfo(); + baroCoeffs.pressSensitivity = getFPGABaroPressureSensitivity(); + baroCoeffs.pressOffset = getFPGABaroPressureOffset(); + baroCoeffs.tempCoeffOfPressSens = getFPGABaroTempCoeffOfPressSensitvity(); + baroCoeffs.tempCoeffPressOffset = getFPGABaroTempCoeffOfPressOffset(); + baroCoeffs.referenceTemp = getFPGABaroReferenceTemperature(); + baroCoeffs.tempCoeffOfTemp = getFPGABaroTempCoeffOfTemperature(); + baroCoeffs.crc = MASK_OFF_LSB & getFPGABaroCoeffsCRC(); + calculatedCRC = crc4( (U16*)&baroCoeffs, sizeof( baroCoeffs ) ); + baroConvConsts.coeffsCRC.data = baroCRC; + baroCRC = (U16)( baroCRC & MASK_OFF_MSB ) & MASK_OFF_NIBBLE_MSB; + baroConvConsts.hasCRCBeenChecked = TRUE; + + if ( calculatedCRC != baroCRC ) + { + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DG_BAROMETRIC_SENSOR_COEFFS_BAD_CRC, calculatedCRC, baroCoeffs.crc ); + } + } + else if ( ( TRUE == didTimeout( baroConvConsts.waitForCoeffStartTimeMS, BARO_SENSOR_WAIT_FOR_COEFF_TIME_OUT_MS ) ) && + ( FALSE == baroConvConsts.hasCRCBeenChecked ) ) + { + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DG_BAROMETRIC_SENSOR_COEFFS_BAD_CRC, 0, baroCRC ); + } +} + /************************************************************************* * TEST SUPPORT FUNCTIONS *************************************************************************/ Index: firmware/App/Controllers/TemperatureSensors.h =================================================================== diff -u -r4e11c80367b5ae522aa34fb137079e516c98831b -rfc11115c26447a2da7b12f5f38ff0d4af06c579b --- firmware/App/Controllers/TemperatureSensors.h (.../TemperatureSensors.h) (revision 4e11c80367b5ae522aa34fb137079e516c98831b) +++ firmware/App/Controllers/TemperatureSensors.h (.../TemperatureSensors.h) (revision fc11115c26447a2da7b12f5f38ff0d4af06c579b) @@ -7,8 +7,8 @@ * * @file TemperatureSensors.h * -* @author (last) Dara Navaei -* @date (last) 12-Jul-2022 +* @author (last) Michael Garthwaite +* @date (last) 30-Aug-2022 * * @author (original) Dara Navaei * @date (original) 08-Apr-2020 Index: firmware/App/Modes/ModeService.c =================================================================== diff -u -r3b70632c04247a6973960e1f37ae73eb4384a6b7 -rfc11115c26447a2da7b12f5f38ff0d4af06c579b --- firmware/App/Modes/ModeService.c (.../ModeService.c) (revision 3b70632c04247a6973960e1f37ae73eb4384a6b7) +++ firmware/App/Modes/ModeService.c (.../ModeService.c) (revision fc11115c26447a2da7b12f5f38ff0d4af06c579b) @@ -17,6 +17,7 @@ #include "OperationModes.h" #include "ModeService.h" +#include "CPLD.h" /** * @addtogroup DGServiceMode Index: firmware/App/Modes/ModeStandby.c =================================================================== diff -u -r72ba5f3c63325b00306b544b2513c03500919d06 -rfc11115c26447a2da7b12f5f38ff0d4af06c579b --- firmware/App/Modes/ModeStandby.c (.../ModeStandby.c) (revision 72ba5f3c63325b00306b544b2513c03500919d06) +++ firmware/App/Modes/ModeStandby.c (.../ModeStandby.c) (revision fc11115c26447a2da7b12f5f38ff0d4af06c579b) @@ -7,8 +7,8 @@ * * @file ModeStandby.c * -* @author (last) Dara Navaei -* @date (last) 31-May-2022 +* @author (last) Michael Garthwaite +* @date (last) 07-Sep-2022 * * @author (original) Dara Navaei * @date (original) 05-Nov-2019 Index: firmware/App/Modes/OperationModes.c =================================================================== diff -u -ra7241a5e0c495e5e53c2f44fa3e5470489f88d6d -rfc11115c26447a2da7b12f5f38ff0d4af06c579b --- firmware/App/Modes/OperationModes.c (.../OperationModes.c) (revision a7241a5e0c495e5e53c2f44fa3e5470489f88d6d) +++ firmware/App/Modes/OperationModes.c (.../OperationModes.c) (revision fc11115c26447a2da7b12f5f38ff0d4af06c579b) @@ -65,7 +65,7 @@ /* SERV */{ DG_MODE_FAUL, DG_MODE_SERV, DG_MODE_NLEG, DG_MODE_NLEG, DG_MODE_NLEG, DG_MODE_NLEG, DG_MODE_NLEG, DG_MODE_NLEG, DG_MODE_NLEG, DG_MODE_NLEG, DG_MODE_NLEG }, /* INIT */{ DG_MODE_FAUL, DG_MODE_NLEG, DG_MODE_INIT, DG_MODE_STAN, DG_MODE_SOLO, DG_MODE_NLEG, DG_MODE_NLEG, DG_MODE_NLEG, DG_MODE_NLEG, DG_MODE_NLEG, DG_MODE_NLEG }, /* STAN */{ DG_MODE_FAUL, DG_MODE_SERV, DG_MODE_NLEG, DG_MODE_STAN, DG_MODE_SOLO, DG_MODE_GENE, DG_MODE_NLEG, DG_MODE_NLEG, DG_MODE_FLUS, DG_MODE_HEAT, DG_MODE_CHEM }, - /* SOLO */{ DG_MODE_FAUL, DG_MODE_SERV, DG_MODE_NLEG, DG_MODE_STAN, DG_MODE_SOLO, DG_MODE_NLEG, DG_MODE_NLEG, DG_MODE_NLEG, DG_MODE_FLUS, DG_MODE_HEAT, DG_MODE_CHEM /*DG_MODE_NLEG*/ }, // TODO for testing only + /* SOLO */{ DG_MODE_FAUL, DG_MODE_SERV, DG_MODE_NLEG, DG_MODE_STAN, DG_MODE_SOLO, DG_MODE_NLEG, DG_MODE_NLEG, DG_MODE_NLEG, DG_MODE_FLUS, DG_MODE_HEAT, DG_MODE_NLEG }, /* GENE */{ DG_MODE_FAUL, DG_MODE_NLEG, DG_MODE_NLEG, DG_MODE_STAN, DG_MODE_NLEG, DG_MODE_GENE, DG_MODE_FILL, DG_MODE_DRAI, DG_MODE_NLEG, DG_MODE_NLEG, DG_MODE_NLEG }, /* FILL */{ DG_MODE_FAUL, DG_MODE_NLEG, DG_MODE_NLEG, DG_MODE_STAN, DG_MODE_NLEG, DG_MODE_GENE, DG_MODE_FILL, DG_MODE_NLEG, DG_MODE_NLEG, DG_MODE_NLEG, DG_MODE_NLEG }, /* DRAI */{ DG_MODE_FAUL, DG_MODE_NLEG, DG_MODE_NLEG, DG_MODE_STAN, DG_MODE_NLEG, DG_MODE_GENE, DG_MODE_NLEG, DG_MODE_DRAI, DG_MODE_NLEG, DG_MODE_NLEG, DG_MODE_NLEG }, @@ -131,7 +131,6 @@ void execOperationModes( void ) { DG_OP_MODE_T newMode; - U32 priorSubMode = currentSubMode; priorSubMode = currentSubMode; @@ -150,14 +149,9 @@ if ( currentMode != newMode ) { // handle transition to new mode - priorSubMode = 0; lastMode = currentMode; transitionToNewOperationMode( newMode ); currentMode = newMode; - - // Mode is changing, write the RO generated volume to the RTC RAM and set the service flag to FALSE - // since this is not a from a service change - setROWaterGeneratedL( getROGeneratedVolumeL(), FALSE ); } // mode specific processing to be done continuously Index: firmware/App/Services/AlarmMgmtSWFaults.h =================================================================== diff -u -r3b70632c04247a6973960e1f37ae73eb4384a6b7 -rfc11115c26447a2da7b12f5f38ff0d4af06c579b --- firmware/App/Services/AlarmMgmtSWFaults.h (.../AlarmMgmtSWFaults.h) (revision 3b70632c04247a6973960e1f37ae73eb4384a6b7) +++ firmware/App/Services/AlarmMgmtSWFaults.h (.../AlarmMgmtSWFaults.h) (revision fc11115c26447a2da7b12f5f38ff0d4af06c579b) @@ -86,6 +86,7 @@ SW_FAULT_ID_CONCENTRATE_PUMP_EXEC_INVALID_STATE, // 55 SW_FAULT_ID_CONCENTRATE_PUMP_INVALID_PUMP_ID, SW_FAULT_ID_SERVICE_MODE_INVALID_EXEC_STATE, + SW_FAULT_ID_SEMAPHORE_IN_USE_TIMEOUT, 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 @@ -131,6 +132,10 @@ SW_FAULT_ID_PHANTOM_INTERRUPT, // 100 SW_FAULT_ID_ILLEGAL_MEM_ACCESS, SW_FAULT_ID_INVALID_CHEMICAL_BOTTLE_SELECTED, + SW_FAULT_ID_INVALID_FPGA_SENSOR_GROUP_SELECTED, + SW_FAULT_ID_INVALID_FLOW_SENSOR_SELECTED, + SW_FAULT_ID_INVALID_SERVICE_STATE_SELECTED, // 105 + SW_FAULT_ID_INVALID_NV_RECORD_SELECTED, NUM_OF_SW_FAULT_IDS } SW_FAULT_ID_T; Index: firmware/App/Services/Reservoirs.c =================================================================== diff -u -r3b70632c04247a6973960e1f37ae73eb4384a6b7 -rfc11115c26447a2da7b12f5f38ff0d4af06c579b --- firmware/App/Services/Reservoirs.c (.../Reservoirs.c) (revision 3b70632c04247a6973960e1f37ae73eb4384a6b7) +++ firmware/App/Services/Reservoirs.c (.../Reservoirs.c) (revision fc11115c26447a2da7b12f5f38ff0d4af06c579b) @@ -51,7 +51,7 @@ #define MAX_REDUNDANT_LOAD_CELL_DIFF 50.0F ///< Maximum difference in redundant load cells when determining if fill completed. #define MAX_DRAIN_RPM_MLP 2400.0F ///< Maximum drain RPM in mL/min. #define DATA_PUBLISH_COUNTER_START_COUNT 5 ///< Data publish counter start count. -#define ENVIRONMENT_TEMPERATURE_C 23.5F ///< Device's environment temperature in C. // TODO add this to the cal records +#define NUM_OF_ACID_AND_BICARB_NV_DATA_TO_CHECK 1 ///< Number of acid and bicarb non-volatile data to check. // ********** private data ********** @@ -98,9 +98,14 @@ static BOOL tareLoadCellRequest; ///< Flag indicates if load cell tare has been requested by HD. static DG_RESERVOIR_VOLUME_RECORD_T reservoirsCalRecord; ///< DG reservoirs non-volatile record. static DG_HEATING_CAL_RECORD_T heatingConstsCalRecord; ///< DG heating calibration record. +static DG_ACID_CONCENTRATES_RECORD_T acidConcentrateCalRecord; ///< Acid concentrate calibration record. +static DG_BICARB_CONCENTRATES_RECORD_T bicarbConcentrateCalRecord; ///< Bicarb concentrate calibration record. static F32 targetFillFlowRateLPM; ///< Target fill flow rate in L/min. static BOOL isThisTheFirstCycle; ///< Boolean flag to indicate whether this is the first cycle. static RESERVOIRS_PREVIOUS_STATUS reservoirPreviousStatus[ NUM_OF_DG_RESERVOIRS ]; ///< Reservoirs previous status. +static HD_MODE_SUB_MODE_T hdModes; ///< HD operations mode. +static BOOL hasROVolBeenWrittenToNV; ///< Boolean flag to indicate whether the RO volume has been written to NV RAM or not. +static BOOL hasDisinfectStatusBeenSet; ///< Boolean flag to indicate whether disinfect has been voided after starting treatment. /*********************************************************************//** * @brief @@ -113,15 +118,17 @@ *************************************************************************/ void initReservoirs( void ) { - activeReservoir.data = (U32)DG_RESERVOIR_1; - fillVolumeTargetMl.data = DEFAULT_FILL_VOLUME_ML; - drainVolumeTargetMl.data = DEFAULT_DRAIN_VOLUME_ML; - targetFillFlowRateLPM = 0.0; - isThisTheFirstCycle = TRUE; - dataPublishCounter = DATA_PUBLISH_COUNTER_START_COUNT; + activeReservoir.data = (U32)DG_RESERVOIR_1; + fillVolumeTargetMl.data = DEFAULT_FILL_VOLUME_ML; + drainVolumeTargetMl.data = DEFAULT_DRAIN_VOLUME_ML; + targetFillFlowRateLPM = 0.0; + isThisTheFirstCycle = TRUE; + dataPublishCounter = DATA_PUBLISH_COUNTER_START_COUNT; + hasROVolBeenWrittenToNV = FALSE; + hasDisinfectStatusBeenSet = FALSE; memset( &reservoirPreviousStatus, 0.0, sizeof( RESERVOIRS_PREVIOUS_STATUS ) * NUM_OF_DG_RESERVOIRS ); -} +} /*********************************************************************//** * @brief @@ -143,19 +150,59 @@ getNVRecord2Driver( GET_CAL_HEATING_RECORD, (U08*)&heatingConstsCalRecord, sizeof( heatingConstsCalRecord ), NUM_OF_CAL_DATA_RSRVRS, ALARM_ID_DG_HEATING_INVALID_CAL_RECORD ); } - + + if ( ( ( DG_MODE_FAUL == getCurrentOperationMode() ) || ( DG_MODE_STAN == getCurrentOperationMode() ) ) && ( FALSE == hasROVolBeenWrittenToNV ) ) + { + // If the mode is fault or it is standby and the RO volume has not been written already, write it + BOOL status; + DG_OP_MODE_T prevMode = getPreviousOperationMode(); + + switch( prevMode ) + { + case DG_MODE_GENE: + case DG_MODE_FILL: + case DG_MODE_DRAI: + case DG_MODE_FLUS: + case DG_MODE_HEAT: + case DG_MODE_CHEM: + // Mode is changing, write the RO generated volume to the RTC RAM and set the service flag to FALSE + // since this is not a from a service change. If the previous modes were any of the above modes, it means + // it has been generating water. + status = setROWaterGeneratedL( getROGeneratedVolumeL() ); + break; + } + + if ( TRUE == status ) + { + // The generated water has been successfully written + hasROVolBeenWrittenToNV = TRUE; + } + } + + if ( ( FALSE == hasDisinfectStatusBeenSet ) && ( MODE_TREA == hdModes.hdMode ) ) + { + // If the disinfect status has not been set and we are in treatment mode, void the disinfect (chemical or heat disinfects) + BOOL status = setDisinfectStatus( FALSE ); + + if ( TRUE == status ) + { + hasDisinfectStatusBeenSet = TRUE; + } + } + // publish active reservoir, fill/drain volume targets at 1 Hz. if ( ++dataPublishCounter >= RESERVOIR_DATA_PUB_INTERVAL ) { - RESERVOIR_DATA_T data; + RESERVOIR_DATA_T data; + data.activeReservoir = getU32OverrideValue( &activeReservoir ); data.fillToVolumeMl = getU32OverrideValue( &fillVolumeTargetMl ); data.drainToVolumeMl = getU32OverrideValue( &drainVolumeTargetMl ); data.timeReservoirCycleMS = heatersTempCalc.timeReservoirCycleMS; data.timeReservoirFill2SwitchMS = heatersTempCalc.timeReservoirFill2SwitchMS; data.timeUFDecayMS = heatersTempCalc.timeUFDecayMS; data.tempUFFill = heatersTempCalc.tempUFFill; - data.tempReservoirUseActual = getReservoirActualTemperature(); + data.tempReservoirUseActual = getReservoirCurrentTemperature(); data.tempReservoirEndFill = heatersTempCalc.tempReservoirEndFill; data.tempAvgFill = getAvgFillTemperature(); data.tempLastFill = getLastFillTemperature(); @@ -180,10 +227,15 @@ calStatus |= getNVRecord2Driver( GET_CAL_RSRVRS_VOL_RECORD, (U08*)&reservoirsCalRecord, sizeof( reservoirsCalRecord ), NUM_OF_CAL_DATA_RSRVRS, ALARM_ID_DG_RESERVOIRS_INVALID_CAL_RECORD ); - calStatus |= getNVRecord2Driver( GET_CAL_HEATING_RECORD, (U08*)&heatingConstsCalRecord, sizeof( heatingConstsCalRecord ), NUM_OF_CAL_DATA_RSRVRS, ALARM_ID_DG_HEATING_INVALID_CAL_RECORD ); + // Get the calibration values of acid and bicarb + calStatus |= getNVRecord2Driver( GET_CAL_ACID_CONCENTREATES, (U08*)&acidConcentrateCalRecord, sizeof( acidConcentrateCalRecord ), + NUM_OF_ACID_AND_BICARB_NV_DATA_TO_CHECK, ALARM_ID_DG_ACID_CONCENTRATE_INVALID_CAL_RECORD ); + calStatus |= getNVRecord2Driver( GET_CAL_BICARB_CONCENTRATES, (U08*)&bicarbConcentrateCalRecord, sizeof( bicarbConcentrateCalRecord ), + NUM_OF_ACID_AND_BICARB_NV_DATA_TO_CHECK, ALARM_ID_DG_BICARB_CONCENTRATE_INVALID_CAL_RECORD ); + if ( TRUE == calStatus ) { result = SELF_TEST_STATUS_PASSED; @@ -194,8 +246,8 @@ } return result; -} - +} + /*********************************************************************//** * @brief * The setActiveReservoirCmd function sets the given reservoir as active @@ -359,6 +411,9 @@ cmdResponse.rejected = TRUE; cmdResponse.rejectCode = DG_CMD_REQUEST_REJECT_REASON_NONE; + // regardless of mode, clear bad fill flag if HD is asking us to stop filling + setBadAvgConductivityDetectedFlag( FALSE ); + // stop fill command only valid in fill mode if ( DG_MODE_FILL == getCurrentOperationMode() ) { @@ -446,6 +501,35 @@ /*********************************************************************//** * @brief + * The setHDOperationMode function sets HD operation mode value. + * @details Inputs: none + * @details Outputs: hdMode + * @param mode which is HD mode + * @param subMode which is HD submode + * @return none + *************************************************************************/ +void setHDOperationMode( U32 mode, U32 subMode ) +{ + hdModes.hdMode = (HD_OP_MODE_T)mode; + hdModes.hdSubMode = subMode; +} + +/*********************************************************************//** + * @brief + * The getHDOperationMode function copies the provided buffer with the HD + * mode and submode. + * @details Inputs: none + * @details Outputs: hdMode + * @param mode* pointer to the buffer of type HD_MODE_SUB_MODE_T + * @return none + *************************************************************************/ +void getHDOperationMode( HD_MODE_SUB_MODE_T* mode ) +{ + memcpy( mode, &hdModes, sizeof( HD_MODE_SUB_MODE_T ) ); +} + +/*********************************************************************//** + * @brief * The getInactiveReservoir function gets the inactive reservoir. * @details Inputs: activeReservoir * @details Outputs: none @@ -478,6 +562,19 @@ /*********************************************************************//** * @brief + * The getTrimmerHeaterTargetTemperature function returns the trimmer heater + * target temperature in C. + * @details Inputs: none + * @details Outputs: heatersTempCalc + * @return trimmer target temperature in C + *************************************************************************/ +F32 getTrimmerHeaterTargetTemperature( void ) +{ + return heatersTempCalc.tempTargetTrimmer; +} + +/*********************************************************************//** + * @brief * The getReservoirWeight function returns the small filtered weight * of the reservoir's associated load cell. * @details Inputs: none @@ -548,45 +645,6 @@ /*********************************************************************//** * @brief - * The getReservoirActualTemperature function calculates the reservoir's - * actual temperature. - * @details Inputs: none - * @details Outputs: heatersTempCalc - * @return reservoir actual temperature - *************************************************************************/ -F32 getReservoirActualTemperature( void ) -{ - F32 UFTimeConstant = 0.0; - F32 targetFillVolML = getTargetFillVolumeML(); - F32 tempLastFill = getLastFillTemperature(); - F32 tempAvgFill = getAvgFillTemperature(); - F32 UFTauCPerMS = heatingConstsCalRecord.ultrafilterTempTauCPerMin / ( SEC_PER_MIN * MS_PER_SECOND ); - F32 RsrvrTauCPerMS = heatingConstsCalRecord.reservoirTempTauCPerMin / ( SEC_PER_MIN * MS_PER_SECOND ); - - // Only do the calculations if the fill volume is not 0.0 so the final value will not be a nan. - if ( targetFillVolML > NEARLY_ZERO ) - { - heatersTempCalc.timeUFDecayMS = (F32)heatersTempCalc.timeReservoirCycleMS - heatersTempCalc.timeReservoirFillMS; - UFTimeConstant = heatersTempCalc.timeUFDecayMS * UFTauCPerMS; - heatersTempCalc.tempUFFill = tempLastFill + UFTimeConstant; - - F32 ultrafilterPart = ( heatingConstsCalRecord.ultrafilterVolmL / targetFillVolML ) * heatersTempCalc.tempUFFill; - F32 fillPart = ( ( targetFillVolML - heatingConstsCalRecord.ultrafilterVolmL ) / targetFillVolML ) * tempAvgFill; - F32 tempReservoir0Actual = ultrafilterPart + fillPart; - - F32 tempReservoirEndfillActual = tempReservoir0Actual + ( ( heatersTempCalc.timeReservoirFillMS * HALF ) * RsrvrTauCPerMS ); - heatersTempCalc.tempReservoirUseActual = tempReservoirEndfillActual + ( heatersTempCalc.timeReservoirFill2SwitchMS * RsrvrTauCPerMS ); - } - else - { - heatersTempCalc.tempReservoirUseActual = 0.0; - } - - return heatersTempCalc.tempReservoirUseActual; -} - -/*********************************************************************//** - * @brief * The getPrimaryHeaterTargetTemperature function calculates the primary * heater target temperature and returns target temperature value. * @details Inputs: heatingConstsCalRecord @@ -633,22 +691,25 @@ if ( targetROFlowLPM > 0 ) { - priTargetTemp = ( tempTarget * ( tgtTotalFlowLPM / targetROFlowLPM ) ) - ( ENVIRONMENT_TEMPERATURE_C * ( tgtAicdFlowLPM / targetROFlowLPM ) ) - - ( ENVIRONMENT_TEMPERATURE_C * ( tgtBicarbFlowLPM / targetROFlowLPM ) ); + F32 acidTemperature = acidConcentrateCalRecord.acidConcentrate[ CAL_DATA_ACID_CONCENTRATE_1 ].acidBottleTemperature; + F32 bicarbTemperature = bicarbConcentrateCalRecord.bicarbConcentrate[ CAL_DATA_BICARB_CONCENTRATE_1 ].bicarbBottleTemperature; + + priTargetTemp = ( tempTarget * ( tgtTotalFlowLPM / targetROFlowLPM ) ) - ( acidTemperature * ( tgtAicdFlowLPM / targetROFlowLPM ) ) - + ( bicarbTemperature * ( tgtBicarbFlowLPM / targetROFlowLPM ) ); } return priTargetTemp; } /*********************************************************************//** * @brief - * The getTrimmerHeaterTargetTemperature function calculates the trimmer - * heater target temperature and returns target temperature value. + * The getReservoirCurrentTemperature function calculates the reservoir's + * current temperature and returns target temperature value. * @details Inputs: heatingConstsCalRecord * @details Outputs: heatersTempCalc * @return primary heater target temperature *************************************************************************/ -F32 getTrimmerHeaterTargetTemperature( void ) +F32 getReservoirCurrentTemperature( void ) { F32 tempRsrvrActual = 0.0; F32 fillROAvgActual = getAvgFillTemperature(); @@ -664,10 +725,13 @@ if ( tgtTotalFlowLPM > 0 ) { - heatersTempCalc.tempFillMixAvgTrimmer = ( fillROAvgActual * ( tgtTotalFlowLPM / targetROFlowLPM ) ) + - ( ENVIRONMENT_TEMPERATURE_C * ( tgtAicdFlowLPM / targetROFlowLPM ) ) + - ( ENVIRONMENT_TEMPERATURE_C * ( tgtBicarbFlowLPM / targetROFlowLPM ) ); + F32 acidTemperature = acidConcentrateCalRecord.acidConcentrate[ CAL_DATA_ACID_CONCENTRATE_1 ].acidBottleTemperature; + F32 bicarbTemperature = bicarbConcentrateCalRecord.bicarbConcentrate[ CAL_DATA_BICARB_CONCENTRATE_1 ].bicarbBottleTemperature; + heatersTempCalc.tempFillMixAvgTrimmer = ( fillROAvgActual * ( tgtTotalFlowLPM / targetROFlowLPM ) ) + + ( acidTemperature * ( tgtAicdFlowLPM / targetROFlowLPM ) ) + + ( bicarbTemperature * ( tgtBicarbFlowLPM / targetROFlowLPM ) ); + heatersTempCalc.tempRsrvr0ActualTrimmer = ( ( heatingConstsCalRecord.ultrafilterVolmL / targetFillVolML ) * tempUFFill ) + ( ( ( targetFillVolML - heatingConstsCalRecord.ultrafilterVolmL ) / targetFillVolML ) * heatersTempCalc.tempFillMixAvgTrimmer ); @@ -695,6 +759,34 @@ /*********************************************************************//** * @brief + * The getAcidConcentrateCalRecord function fills the provided buffer with + * the acid concentrate record. + * @details Inputs: acidConcentrateCalRecord + * @details Outputs: none + * @param acidRecord which is the pointer to the provided buffer + * @return none + *************************************************************************/ +void getAcidConcentrateCalRecord( DG_ACID_CONCENTRATES_RECORD_T* acidRecord ) +{ + memcpy( acidRecord, &acidConcentrateCalRecord, sizeof( DG_ACID_CONCENTRATES_RECORD_T ) ); +} + +/*********************************************************************//** + * @brief + * The getBicarbConcentrateCalRecord function fills the provided buffer with + * the bicarb concentrate record. + * @details Inputs: bicarbConcentrateCalRecord + * @details Outputs: none + * @param bicarbRecord which is the pointer to the provided buffer + * @return none + *************************************************************************/ +void getBicarbConcentrateCalRecord( DG_BICARB_CONCENTRATES_RECORD_T* bicarbRecord ) +{ + memcpy( bicarbRecord, &bicarbConcentrateCalRecord, sizeof( DG_BICARB_CONCENTRATES_RECORD_T ) ); +} + +/*********************************************************************//** + * @brief * The hasTargetFillVolumeReached function checks if the target fill volume * for specific reservoir has been reached. * @details Inputs: fillVolumeTargetMl Index: firmware/App/Services/Reservoirs.h =================================================================== diff -u -r3b70632c04247a6973960e1f37ae73eb4384a6b7 -rfc11115c26447a2da7b12f5f38ff0d4af06c579b --- firmware/App/Services/Reservoirs.h (.../Reservoirs.h) (revision 3b70632c04247a6973960e1f37ae73eb4384a6b7) +++ firmware/App/Services/Reservoirs.h (.../Reservoirs.h) (revision fc11115c26447a2da7b12f5f38ff0d4af06c579b) @@ -20,6 +20,7 @@ #include "DGCommon.h" #include "DGDefs.h" +#include "HDDefs.h" #include "NVDataMgmt.h" /** @@ -70,6 +71,13 @@ F32 dialysateFlowLPM; ///< Dialysate flow rate in L/min } DG_CMD_DIALYSATE_HEATING_PARAMS_T; +/// HD mode and HD submode +typedef struct +{ + HD_OP_MODE_T hdMode; ///< HD mode + U32 hdSubMode; ///< HD submode +} HD_MODE_SUB_MODE_T; + /// Reservoir data struct. typedef struct { @@ -104,18 +112,23 @@ void startDrainCmd( DRAIN_CMD_T drainCmd ); // handle drain command from HD void stopDrainCmd( void ); // handle stop drain command from HD +void setHDOperationMode( U32 mode, U32 subMode ); +void getHDOperationMode( HD_MODE_SUB_MODE_T* mode ); + DG_RESERVOIR_ID_T getInactiveReservoir( void ); F32 getReservoirWeight( DG_RESERVOIR_ID_T reservoirId ); void setDialysateHeatingParameters( DG_CMD_DIALYSATE_HEATING_PARAMS_T params ); U32 getTargetFillVolumeML( void ); F32 getTargetFillFlowRateLPM( void ); -F32 getReservoirActualTemperature( void ); F32 getPrimaryHeaterTargetTemperature( void ); -F32 getTrimmerHeaterTargetTemperature( void ); +F32 getReservoirCurrentTemperature( void ); F32 getTargetDialysateFlowLPM( void ); +F32 getTrimmerHeaterTargetTemperature( void ); DG_RESERVOIR_VOLUME_RECORD_T getReservoirsCalRecord( void ); +void getAcidConcentrateCalRecord( DG_ACID_CONCENTRATES_RECORD_T* acidRecord ); +void getBicarbConcentrateCalRecord( DG_BICARB_CONCENTRATES_RECORD_T* bicarbRecord ); BOOL hasTargetFillVolumeBeenReached( DG_RESERVOIR_ID_T reservoirId ); BOOL hasTargetDrainVolumeBeenReached( DG_RESERVOIR_ID_T reservoirId, U32 timeout ); Index: firmware/App/Services/SystemComm.c =================================================================== diff -u -r3b70632c04247a6973960e1f37ae73eb4384a6b7 -rfc11115c26447a2da7b12f5f38ff0d4af06c579b --- firmware/App/Services/SystemComm.c (.../SystemComm.c) (revision 3b70632c04247a6973960e1f37ae73eb4384a6b7) +++ firmware/App/Services/SystemComm.c (.../SystemComm.c) (revision fc11115c26447a2da7b12f5f38ff0d4af06c579b) @@ -811,6 +811,10 @@ handleAlarmClear( message ); break; + case MSG_ID_RTC_EPOCH: + handleRTCSyncFromHD( message ); + break; + case MSG_ID_SET_DG_DIALYSATE_TEMP_TARGETS: handleSetDialysateTemperatureCmd( message ); break; @@ -888,6 +892,9 @@ handleServiceModeRequest( message ); break; + case MSG_ID_HD_REQUEST_DG_USAGE_INFO: + break; + // NOTE: This case must be last case MSG_ID_DG_TESTER_LOGIN_REQUEST: handleTesterLogInRequest( message ); @@ -1129,11 +1136,11 @@ break; case MSG_ID_FILTER_FLUSH_TIME_PERIOD_OVERRIDE: - handleFilterFlushTimePeriodOverride( message ); + handleFilterFlushTimePeriodOverride(message); break; - case MSG_ID_DG_FANS_RPM_OVERRIDE: - handleFansRPMOverride( message ); + case MSG_ID_DG_BLOCK_MESSAGE_TRANSMISSION: + handleTestBlockMessagesRequest( message ); break; case MSG_ID_DG_STOP_RTC_CLOCK: @@ -1144,10 +1151,6 @@ handleSetDrainPumpMeasuredRPMOverrideRequest( message ); break; - case MSG_ID_DG_BLOCK_MESSAGE_TRANSMISSION: - handleTestBlockMessagesRequest( message ); - break; - case MSG_ID_DG_SUPER_CLEAR_ALARMS_CMD: handleTestSuperClearAlarmsRequest( message ); break; @@ -1160,6 +1163,10 @@ handleTestFansRPMAlarmStartTimeOffsetRequest( message ); break; + case MSG_ID_DG_FANS_RPM_OVERRIDE: + handleFansRPMOverride( message ); + break; + case MSG_ID_DG_USED_ACID_VOLUME_ML_OVERRIDE: handleTestUsedAcidVolumeMLOverrideRequest( message ); break; @@ -1200,6 +1207,10 @@ handleTestTareReservoirRequest( message ); break; + case MSG_ID_HD_REQUEST_DG_ALARMS: + handleResendAllAlarmsCommand( message ); + break; + default: // TODO - unrecognized message ID received - ignore break; Index: firmware/App/Services/SystemCommMessages.c =================================================================== diff -u -r3b70632c04247a6973960e1f37ae73eb4384a6b7 -rfc11115c26447a2da7b12f5f38ff0d4af06c579b --- firmware/App/Services/SystemCommMessages.c (.../SystemCommMessages.c) (revision 3b70632c04247a6973960e1f37ae73eb4384a6b7) +++ firmware/App/Services/SystemCommMessages.c (.../SystemCommMessages.c) (revision fc11115c26447a2da7b12f5f38ff0d4af06c579b) @@ -23,7 +23,6 @@ #include "Compatible.h" #include "ConcentratePumps.h" #include "ConductivitySensors.h" -#include "Fans.h" #include "FPGA.h" #include "Heaters.h" #include "ModeFill.h" @@ -301,6 +300,9 @@ payloadPtr += sizeof( U32 ); data = almData2.data.uInt.data; memcpy( payloadPtr, &data, sizeof( U32 ) ); + // Pad with space for 3 U32s - set to zero - unused for DG + payloadPtr += ( sizeof( U32) * 3 ); + memset( payloadPtr, 0, sizeof( U32) * 3 ); // 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_ALARM, ACK_REQUIRED ); @@ -365,7 +367,6 @@ return result; } - // *********************************************************************** // **************** Message Handling Helper Functions ******************** // *********************************************************************** @@ -390,6 +391,30 @@ /*********************************************************************//** * @brief + * The handleRTCSyncFromHD function handles an HD date/time broadcast message + * from the HD. + * @details Inputs: none + * @details Outputs: message handled + * @param message a pointer to the message to handle + * @return none + *************************************************************************/ +void handleRTCSyncFromHD( MESSAGE_T *message ) +{ + // Only sync RTC to HD date/time when ... + if ( TRUE == syncDG2HDDateTime() ) + { + if ( sizeof( RTC_DATA_T ) == message->hdr.payloadLen ) + { + RTC_DATA_T epoch; + + memcpy( &epoch, message->payload, sizeof( RTC_DATA_T ) ); + setRTCEpoch( epoch.epochTime ); + } + } +} + +/*********************************************************************//** + * @brief * The handleAlarmClear function handles a clear alarm message from the HD. * @details Inputs: none * @details Outputs: message handled @@ -427,7 +452,6 @@ if ( message->hdr.payloadLen == sizeof( DG_CMD_DIALYSATE_HEATING_PARAMS_T ) ) { DG_CMD_DIALYSATE_HEATING_PARAMS_T payload; - result = TRUE; memcpy( &payload, message->payload, sizeof( DG_CMD_DIALYSATE_HEATING_PARAMS_T ) ); setDialysateHeatingParameters( payload ); @@ -556,14 +580,15 @@ void handleDGSendConcentrateMixingRatios( MESSAGE_T *message ) { MESSAGE_T msg; - - DG_ACID_CONCENTRATES_RECORD_T acid = getAcidConcentrateCalRecord(); - DG_BICARB_CONCENTRATES_RECORD_T bicarb = getBicarbConcentrateCalRecord(); + DG_ACID_CONCENTRATES_RECORD_T acid; + DG_BICARB_CONCENTRATES_RECORD_T bicarb; // By the time these are requested, the prepare time is no longer needed since the concentrate lines are // primed before the actual treatment starts - U32 fillPrepTimeMS = 0; + U32 fillPrepTimeMS = 0; + U08 *payloadPtr = msg.payload; - U08 *payloadPtr = msg.payload; + getAcidConcentrateCalRecord( &acid ); + getBicarbConcentrateCalRecord( &bicarb ); // Create a message record blankMessage( &msg ); @@ -863,7 +888,7 @@ msg.hdr.msgID = MSG_ID_DG_SCHEDULED_RUNS_DATA; msg.hdr.payloadLen = sizeof( U32 ) + sizeof( U32 ); - // TODO this message is for Phase 1B. + // Do nothing this message is for Phase 1B. // Serialize the message (w/ sync, CRC, and appropriate CAN padding) and add serialized message data to appropriate comm buffer serializeMessage( msg, COMM_BUFFER_OUT_CAN_DG_2_UI, ACK_REQUIRED ); @@ -1103,7 +1128,7 @@ if ( TRUE == heaterCmd.startHeater ) { - BOOL isSet = setHeaterTargetTemperature( DG_TRIMMER_HEATER, heaterCmd.targetTemp ); + BOOL isSet = setHeaterTargetTemperature( DG_TRIMMER_HEATER, getTrimmerHeaterTargetTemperature() ); if ( TRUE == isSet ) { @@ -1431,12 +1456,13 @@ if ( message->hdr.payloadLen == sizeof( U32 ) + sizeof( U32 ) ) { U32 mode; + U32 subMode; - // NOTE: the HD operations modes broadcast message contains the mode and submode states - // In this case, only the mode is needed. The mode is received to check if HD is in treatment - // and therefore, DG can void the last disinfect. memcpy( payloadPtr, &mode, sizeof( U32 ) ); - setHDOperationMode( mode ); + payloadPtr += sizeof( U32 ); + memcpy( payloadPtr, &subMode, sizeof( U32 ) ); + + setHDOperationMode( mode, subMode ); status = TRUE; } @@ -3203,37 +3229,6 @@ } /*********************************************************************//** - * @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 handleStopDGRTCClock function handles a request to stop the RTC clock. * @details Inputs: none @@ -3372,10 +3367,41 @@ /*********************************************************************//** * @brief - * The handleTestFansRPMAlarmStartTimeOffsetRequest function handles a - * request to set the fans RPM alarm start time offset. + * 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 handleTestFansRPMAlarmStartTimeOverrideRequest function handles a + * request to override the fan RPM alarm start time. + * @details Inputs: none + * @details Outputs: message handled * @param message : a pointer to the message to handle * @return none *************************************************************************/ @@ -3398,7 +3424,6 @@ } /*********************************************************************//** - * @brief * The handleTestUsedAcidVolumeMLOverrideRequest function handles a * request to override the acid volume. * @details Inputs: none @@ -3758,4 +3783,29 @@ return result; } +/*********************************************************************//** + * @brief + * The sendUIServiceModeResponse function sends out the DG response to a + * UI request to go to service mode. + * @details Inputs: none + * @details Outputs: Service mode request response msg constructed and queued + * @param accepted TRUE if request was accepted, FALSE if not + * @param rejCode Reject reason code explaining why request was rejected + * @return none + *************************************************************************/ +void handleResendAllAlarmsCommand( MESSAGE_T *message ) +{ + BOOL result = FALSE; + + // verify payload length + if ( 0 == message->hdr.payloadLen ) + { + handleResendActiveAlarmsRequest(); + result = TRUE; + } + + // respond to request + sendTestAckResponseMsg( (MSG_ID_T)message->hdr.msgID, result ); +} + /**@}*/ Index: firmware/App/Services/SystemCommMessages.h =================================================================== diff -u -r3b70632c04247a6973960e1f37ae73eb4384a6b7 -rfc11115c26447a2da7b12f5f38ff0d4af06c579b --- firmware/App/Services/SystemCommMessages.h (.../SystemCommMessages.h) (revision 3b70632c04247a6973960e1f37ae73eb4384a6b7) +++ firmware/App/Services/SystemCommMessages.h (.../SystemCommMessages.h) (revision fc11115c26447a2da7b12f5f38ff0d4af06c579b) @@ -80,6 +80,9 @@ // MSG_ID_POWER_OFF_WARNING void handlePowerOffWarning( MESSAGE_T *message ); +// MSG_ID_RTC_EPOCH +void handleRTCSyncFromHD( MESSAGE_T *message ); + // MSG_ID_ALARM_CLEARED void handleAlarmClear( MESSAGE_T *message ); @@ -104,6 +107,9 @@ // MSG_ID_DG_CHANGE_VALVE_SETTING_CMD void handleChangeValveSettingCmd( MESSAGE_T *message ); +// MSG_ID_HD_REQUEST_DG_USAGE_INFO +//void handleDGSend + // MSG_ID_DG_FILL_CMD void handleFillCmd( MESSAGE_T *message ); @@ -158,6 +164,9 @@ // MSG_ID_DG_RESPONSE_SERVICE_MODE_REQUEST BOOL sendServiceModeResponse( BOOL accepted, U32 rejCode ); +// MSG_ID_HD_OP_MODE +BOOL handleSetHDOperationMode( MESSAGE_T *message ); + // *********** public test support message functions ********** // MSG_TESTER_LOG_IN @@ -365,6 +374,12 @@ // MSG_ID_DG_DRAIN_PUMP_MEASURED_RPM_OVERRIDE void handleSetDrainPumpMeasuredRPMOverrideRequest( MESSAGE_T *message ); +// MSG_ID_DG_ALARM_INFO_SEND_INTERVAL_OVERRIDE +void handleTestAlarmInfoSendIntervalOverrideRequest( MESSAGE_T *message ); + +// MSG_ID_DG_SUPER_CLEAR_ALARMS_CMD +void handleTestSuperClearAlarmsRequest( MESSAGE_T *message ); + // MSG_ID_DG_SET_FANS_RPM_ALARM_START_TIME_OFFSET void handleTestFansRPMAlarmStartTimeOffsetRequest( MESSAGE_T *message ); @@ -386,6 +401,12 @@ // MSG_ID_DG_HD_COMMUNICATION_STATUS void handleTestHDCommunicationStatusOverrideRequest(MESSAGE_T *message); +// MSG_ID_DG_USED_ACID_VOLUME_ML_OVERRIDE +void handleTestUsedAcidVolumeMLOverrideRequest(MESSAGE_T *message); + +// MSG_ID_DG_USED_BICARB_VOLUME_ML_OVERRIDE +void handleTestUsedBicarbVolumeMLOverrideRequest(MESSAGE_T *message); + // MSG_ID_DG_GET_USAGE_INFO_RECORD void handleGetDGUsageInfoRecord( MESSAGE_T *message ); @@ -401,6 +422,9 @@ // MSG_ID_HD_OP_MODE BOOL handleSetHDOperationMode( MESSAGE_T *message ); +// MSG_ID_HD_REQUEST_DG_ALARMS +void handleResendAllAlarmsCommand( MESSAGE_T *message ); + /**@}*/ #endif