Index: firmware/App/Controllers/DGInterface.c =================================================================== diff -u -r867eed1d3a71f8fac87ac6dece093a391663188a -r5addd92e279ebc0871364fee70e3ac74db21001a --- firmware/App/Controllers/DGInterface.c (.../DGInterface.c) (revision 867eed1d3a71f8fac87ac6dece093a391663188a) +++ firmware/App/Controllers/DGInterface.c (.../DGInterface.c) (revision 5addd92e279ebc0871364fee70e3ac74db21001a) @@ -61,7 +61,6 @@ // DG sensor data static F32 dgDialysateTemp = 0.0; ///< Dialysate temperature reported by the DG. static F32 dgRedundantDialysateTemp = 0.0; ///< Redundant dialysate temperature reported by the DG. -static F32 dgPrimaryTempSet = 0.0; ///< Primary heater target temperature commanded. static F32 dgPrimaryTemp = 0.0; ///< Latest RO water temperature reported by the DG. static F32 dgTrimmerTempSet = 0.0; ///< Trimmer heater target temperature commanded. static F32 dgTrimmerTemp = 0.0; ///< Latest dialysate temperature reported by the DG. @@ -113,7 +112,6 @@ dgStarted = FALSE; dgTrimmerHeaterOn = FALSE; - dgPrimaryTempSet = 0.0; dgTrimmerTempSet = 0.0; dgActiveReservoirSet = DG_RESERVOIR_2; dgReservoirFillVolumeTargetSet = 0; @@ -425,22 +423,6 @@ /*********************************************************************//** * @brief - * The setDGDialysateTemperatures function sets the latest temperature data - * reported by the DG. - * @details Inputs: none - * @details Outputs: dgPrimaryTemp, dgTrimmerTemp - * @param primaryHtrTemp Primary heater temperature reported by DG - * @param trimmerHtrTemp Trimmer heater temperature reported by DG - * @return none - *************************************************************************/ -void setDGDialysateTemperatures( F32 primaryHtrTemp, F32 trimmerHtrTemp ) -{ - dgPrimaryTemp = primaryHtrTemp; - dgTrimmerTemp = trimmerHtrTemp; -} - -/*********************************************************************//** - * @brief * The setDGReservoirsData function sets the latest reservoir data * reported by the DG. * @details Inputs: none @@ -549,19 +531,18 @@ /*********************************************************************//** * @brief - * The cmdSetDGDialysateTargetTemps function sends a target dialysate - * temperature command message to the DG. + * The cmdSetDGDialysateHeatingParams function sends the dialysate heating + * parameters to DG. * @details Inputs: none - * @details Outputs: dgPrimaryTempSet, dgTrimmerTempSet - * @param primaryHtrTemp commanded target dialysate temperature for the primary heater - * @param trimmerHtrTemp commanded target dialysate temperature for the trimmer heater + * @details Outputs: dgTrimmerTempSet + * @param heatingParams Dialysate heating parameters to be sent to DG * @return none *************************************************************************/ -void cmdSetDGDialysateTargetTemps( F32 primaryHtrTemp, F32 trimmerHtrTemp ) +void cmdSetDGDialysateHeatingParams( DG_CMD_DIALYSATE_HEATING_PARAMS_T heatingParams ) { - dgPrimaryTempSet = primaryHtrTemp; - dgTrimmerTempSet = trimmerHtrTemp; - sendDialysateTempTargetsToDG( dgPrimaryTempSet, dgTrimmerTempSet ); + dgTrimmerTempSet = heatingParams.trimmerTargetTemperature; // TODO is this needed anymore? + // TODO what should we do with the BOOL return of this function? + sendDialysateHeatingParamsToDG( &heatingParams ); } /*********************************************************************//** Index: firmware/App/Controllers/DGInterface.h =================================================================== diff -u -r182a81ed78f66f05ef286e2456c6c86f5e4f3e28 -r5addd92e279ebc0871364fee70e3ac74db21001a --- firmware/App/Controllers/DGInterface.h (.../DGInterface.h) (revision 182a81ed78f66f05ef286e2456c6c86f5e4f3e28) +++ firmware/App/Controllers/DGInterface.h (.../DGInterface.h) (revision 5addd92e279ebc0871364fee70e3ac74db21001a) @@ -111,6 +111,16 @@ U32 flushUIState; ///< DG flush UI state } DG_DISINFECT_UI_STATES_T; +/// Dialysate heating parameters +typedef struct +{ + F32 trimmerTargetTemperature; + U32 timeReservoirCycleMS; + F32 timeReservoirFillMS; + U32 timeReservoirWait2SwitchMS; + F32 dialysateFlowLPM; +} DG_CMD_DIALYSATE_HEATING_PARAMS_T; + // ********** public function prototypes ********** void initDGInterface( void ); @@ -135,14 +145,13 @@ void setDGOpMode( U32 opMode, U32 subMode ); void setDialysateTemperatureReadings( F32 temp1, F32 temp2 ); -void setDGDialysateTemperatures( F32 primaryHtrTemp, F32 trimmerHtrTemp ); void setDGReservoirsData( DG_RESERVOIR_ID_T resID, U32 fillVol, U32 drainVol ); void setDialysateFlowData( F32 flowRate ); void setNewLoadCellReadings( F32 res1Primary, F32 res1Backup, F32 res2Primary, F32 res2Backup ); void setDGDisinfectsStates( DG_DISINFECT_UI_STATES_T states ); void setDGMixingRatios( DG_MIXING_RATIOS_T ratios ); -void cmdSetDGDialysateTargetTemps( F32 primaryHtrTemp, F32 trimmerHtrTemp ); +void cmdSetDGDialysateHeatingParams( DG_CMD_DIALYSATE_HEATING_PARAMS_T heatingParams ); void cmdStartDG( void ); void cmdStopDG( void ); void cmdSetDGActiveReservoir( DG_RESERVOIR_ID_T resID ); Index: firmware/App/Controllers/Fans.c =================================================================== diff -u -r867eed1d3a71f8fac87ac6dece093a391663188a -r5addd92e279ebc0871364fee70e3ac74db21001a --- firmware/App/Controllers/Fans.c (.../Fans.c) (revision 867eed1d3a71f8fac87ac6dece093a391663188a) +++ firmware/App/Controllers/Fans.c (.../Fans.c) (revision 5addd92e279ebc0871364fee70e3ac74db21001a) @@ -186,6 +186,7 @@ // Monitor the RPM of the fans monitorFans(); + // Check for the publication time publishFansData(); } @@ -407,26 +408,27 @@ { if ( ++fansMonitorCounter >= FANS_MONITOR_INTERVAL_COUNT ) { - if ( FALSE == hasAlarmBeenRaised ) - { - FAN_NAMES_T fan; - BOOL isFanRPMOutOfRange = FALSE; - BOOL isAlarmTriggered = FALSE; - F32 rpm = 0.0; + FAN_NAMES_T fan; + BOOL isFanRPMOutOfRange = FALSE; + BOOL isAlarmTriggered = FALSE; + F32 rpm = 0.0; - // The RPM is expected to be 5500 @ 100% duty cycle - // The nominal RPM = duty cycle * 5500 / 1.0 - // The RPM tolerance is -25% to +50% of the nominal RPM - F32 fansNominalRPM = fansStatus.targetDutyCycle * FANS_MAX_ALLOWED_RPM; - F32 fansMinAllowedRPM = fansNominalRPM - ( fansNominalRPM * FANS_MIN_RPM_OUT_OF_RANGE_TOL ); - F32 fansMaxAllowedRPM = fansNominalRPM + ( fansNominalRPM * FANS_MAX_RPM_OUT_OF_RANGE_TOL ); + // The RPM is expected to be 5500 @ 100% duty cycle + // The nominal RPM = duty cycle * 5500 / 1.0 + // The RPM tolerance is -25% to +50% of the nominal RPM + F32 fansNominalRPM = fansStatus.targetDutyCycle * FANS_MAX_ALLOWED_RPM; + F32 fansMinAllowedRPM = fansNominalRPM - ( fansNominalRPM * FANS_MIN_RPM_OUT_OF_RANGE_TOL ); + F32 fansMaxAllowedRPM = fansNominalRPM + ( fansNominalRPM * FANS_MAX_RPM_OUT_OF_RANGE_TOL ); - for ( fan = FAN_INLET_1; fan < NUM_OF_FANS_NAMES; fan++ ) - { - rpm = getMeasuredFanRPM( fan ); - isFanRPMOutOfRange |= ( rpm < fansMinAllowedRPM ) || ( rpm > fansMaxAllowedRPM ); - } + // Loop through the fans and make sure the each of them have RPM in range + for ( fan = FAN_INLET_1; fan < NUM_OF_FANS_NAMES; fan++ ) + { + rpm = getMeasuredFanRPM( fan ); + isFanRPMOutOfRange |= ( ( rpm < fansMinAllowedRPM ) || ( rpm > fansMaxAllowedRPM ) ? TRUE : FALSE ); + } + if ( FALSE == hasAlarmBeenRaised ) + { isAlarmTriggered = isPersistentAlarmTriggered( ALARM_ID_HD_FAN_RPM_OUT_OF_RANGE, isFanRPMOutOfRange ); if ( TRUE == isAlarmTriggered ) @@ -449,6 +451,15 @@ hasAlarmBeenRaised = FALSE; rpmAlarmStartTimer = 0; } + else + { + // If the alarm has been raised and 24 hours has not elapsed, check if the fans RPM is back in range again + // If the fans RPM is in range again, clear the alarm + if ( FALSE == isFanRPMOutOfRange ) + { + clearAlarmCondition( ALARM_ID_HD_FAN_RPM_OUT_OF_RANGE ); + } + } fansMonitorCounter = 0; } Index: firmware/App/Modes/ModePreTreat.c =================================================================== diff -u -r182a81ed78f66f05ef286e2456c6c86f5e4f3e28 -r5addd92e279ebc0871364fee70e3ac74db21001a --- firmware/App/Modes/ModePreTreat.c (.../ModePreTreat.c) (revision 182a81ed78f66f05ef286e2456c6c86f5e4f3e28) +++ firmware/App/Modes/ModePreTreat.c (.../ModePreTreat.c) (revision 5addd92e279ebc0871364fee70e3ac74db21001a) @@ -56,7 +56,7 @@ #define PRE_TREATMENT_FILL_RESERVOIR_TWO_VOLUME_ML FILL_RESERVOIR_TO_VOLUME_ML #endif -#define PRIMARY_HEATER_TARGET_TEMP_OFFSET 2.0 ///< Primary heater target temperature offset from trimmer heater temperature. +#define PRIMARY_HEATER_TARGET_TEMP_OFFSET 2.0 //TODO remove ///< Primary heater target temperature offset from trimmer heater temperature. /// States of the pre-treatment reservoir management state machine. @@ -142,6 +142,11 @@ initConsumableSelfTest(); initPrime(); initSelfTests(); + // Reservoirs state machine is not used in Pre-treatment but the + // init function is called here to initialize all the variables in + // the reservoirs driver since an API from the reservoirs is used + // to setup the DG heaters. + initReservoirs(); resetSignalFlags(); } @@ -156,11 +161,11 @@ *************************************************************************/ U32 transitionToPreTreatmentMode( void ) { - F32 const trimmerHeaterTemp = getTreatmentParameterF32( TREATMENT_PARAM_DIALYSATE_TEMPERATURE ); - F32 const primaryHeaterTemp = trimmerHeaterTemp + PRIMARY_HEATER_TARGET_TEMP_OFFSET; + F32 trimmerHeaterTemp = getTreatmentParameterF32( TREATMENT_PARAM_DIALYSATE_TEMPERATURE ); initPreTreatmentMode(); - cmdSetDGDialysateTargetTemps( primaryHeaterTemp, trimmerHeaterTemp ); + // Set the heaters specs to start heating up the water + setHeatersTemperatureAndTime(); cmdStopDGTrimmerHeater(); // Set user alarm recovery actions allowed in this mode Index: firmware/App/Services/Reservoirs.c =================================================================== diff -u -r867eed1d3a71f8fac87ac6dece093a391663188a -r5addd92e279ebc0871364fee70e3ac74db21001a --- firmware/App/Services/Reservoirs.c (.../Reservoirs.c) (revision 867eed1d3a71f8fac87ac6dece093a391663188a) +++ firmware/App/Services/Reservoirs.c (.../Reservoirs.c) (revision 5addd92e279ebc0871364fee70e3ac74db21001a) @@ -67,6 +67,8 @@ static U32 reservoirSwitchStartTimeMS = 0; ///< Reservoir switch start time in milliseconds. static S32 timeWaitToFillMS = 0; ///< Time to wait to fill in milliseconds. static F32 targetFillFlowLPM = 0.0; ///< Target fill flow in liters/minutes. +static U32 previousDialysateFlowMLP = 0; ///< Previous dialysate flow rate in mL/min. +static F32 previousUFFlowMLP = 0.0; ///< Previous ultrafiltration flow rate in mL/min. // ********** private function prototypes ********** @@ -75,6 +77,7 @@ static void checkReservoirMaxVolume( void ); static F32 getTargetFillFlowRateLPM( void ); static U32 getFillTimeMS( void ); +static void calculateActiveReservoirCycleTime( void ); static void publishReservoirData( void ); static TREATMENT_RESERVOIR_MGMT_STATE_T handleReservoirMgmtStartState( void ); @@ -92,7 +95,8 @@ * @details Outputs: reservoirsState, timeStartMS, timeDepletionMS, volTotalMl, * volSpentMl, reservoirsPublicationCounter, dilutionLevelPct, dgOpMode, dgSubMode, * timeReservoirInUseMS, volSpentUFML, activeReservoir, recirculationLevelPct, - * reservoirSwitchStartTimeMS, timeWaitToFillMS, targetFillFlowLPM + * reservoirSwitchStartTimeMS, timeWaitToFillMS, targetFillFlowLPM, + * previousDialysateFlowRate * @return none *************************************************************************/ void initReservoirs( void ) @@ -113,6 +117,7 @@ reservoirSwitchStartTimeMS = 0; timeWaitToFillMS = 0; targetFillFlowLPM = 0.0; + previousDialysateFlowMLP = 0; } /*********************************************************************//** @@ -148,6 +153,7 @@ checkReservoirDepletionTime(); checkReservoirMaxVolume(); + calculateActiveReservoirCycleTime(); // TODO do we need this? Should we not call the reservoir management exec function in saline bolus? @@ -195,15 +201,16 @@ /*********************************************************************//** * @brief - * The getReservoirCycleTime function returns the depletion time which is the - * cycle time in milliseconds. + * The setHeatersTemperatureAndTime function is an API to call other internal + * functions to set the trimmer's heater target temperature and times that are + * required to calculated the heaters target temperature in DG. * @details Inputs: none - * @details Outputs: timeDepleteMS - * @return timeDepleteMS which is the reservoir cycle time + * @details Outputs: none + * @return none *************************************************************************/ -U32 getReservoirCycleTime( void ) +void setHeatersTemperatureAndTime( void ) { - return timeDepleteMS; + calculateActiveReservoirCycleTime(); } // ********** private functions ********** @@ -303,6 +310,51 @@ /*********************************************************************//** * @brief + * The calculateActiveReservoirCycleTime function calculates the active reservoir + * cycle time in milliseconds. If the target dialysate flow or target ultrafilter + * flow has changed the function sends the new active reservoir cycle time + * to the DG. + * @details Inputs: previousDialysateFlowMLP, previousUFFlowMLP + * @details Outputs: previousDialysateFlowMLP, previousUFFlowMLP + * @return none + *************************************************************************/ +static void calculateActiveReservoirCycleTime( void ) +{ + U32 dialysateFlowMLP = getTreatmentParameterU32( TREATMENT_PARAM_DIALYSATE_FLOW ); + F32 fillTimeMS = ( (F32)FILL_RESERVOIR_TO_VOLUME_ML / ( getTargetFillFlowRateLPM() * ML_PER_LITER ) ) * SEC_PER_MIN * MS_PER_SECOND; + F32 targetUFFlowMLP = getCurrentUFSetRate(); + F32 timeReservoirCycleMS = fillTimeMS; + + // Check if target UF flow is not zero to consider it in the calculations too + if ( targetUFFlowMLP > NEARLY_ZERO ) + { + // If UF is not 0, the active reservoir cycle time is minimum of UF depletion and fill time + F32 timeUFDepletionMS = ( (F32)FILL_RESERVOIR_TO_VOLUME_ML / targetUFFlowMLP ) * SEC_PER_MIN * MS_PER_SECOND; + timeReservoirCycleMS = MIN( fillTimeMS, timeUFDepletionMS ); + } + + // If the target dialysate flow rate has changed, it means the cycle time (depletion time) has changed + // So the new value has to be sent again. + if ( ( previousDialysateFlowMLP != dialysateFlowMLP ) || ( previousUFFlowMLP != targetUFFlowMLP ) ) + { + DG_CMD_DIALYSATE_HEATING_PARAMS_T params; + params.trimmerTargetTemperature = getTreatmentParameterF32( TREATMENT_PARAM_DIALYSATE_TEMPERATURE ); + params.timeReservoirWait2SwitchMS = RESERVOIR_SETTLE_TIME_MS + RESERVOIR_CYCLE_EXTRA_MARGIN_TIME_MS; + params.timeReservoirFillMS = fillTimeMS; + params.timeReservoirCycleMS = timeReservoirCycleMS; + params.dialysateFlowLPM = dialysateFlowMLP / ML_PER_LITER; + + cmdSetDGDialysateHeatingParams( params ); + + // Update the previous dialysate flow and UF flow regardless of which one changed + // If anything of have not changed, then the update does not change anything + previousDialysateFlowMLP = dialysateFlowMLP; + previousUFFlowMLP = targetUFFlowMLP; + } +} + +/*********************************************************************//** + * @brief * The publishReservoirData function publishes reservoirs data during treatment. * @details Inputs: reservoirsPublicationCounter * @details Outputs: reservoirsPublicationCounter @@ -411,8 +463,9 @@ // Using the fresh remaining volume, time to spent the fresh remaining is calculated by dividing the volume to // target dialysate flow rate. The target dialysate flow rate is used to be able to respond to the flow changes // by the user + U32 targetDialysateFlowMLP = getTreatmentParameterU32( TREATMENT_PARAM_DIALYSATE_FLOW ); F32 volFreshML = FILL_RESERVOIR_TO_VOLUME_ML - volSpentML; - F32 timeFreshRemainingMS = ( volFreshML / (F32)getTreatmentParameterU32( TREATMENT_PARAM_DIALYSATE_FLOW ) ) * SEC_PER_MIN * MS_PER_SECOND; + F32 timeFreshRemainingMS = ( volFreshML / (F32)targetDialysateFlowMLP ) * SEC_PER_MIN * MS_PER_SECOND; F32 volMaxUFML = FILL_RESERVOIR_TO_VOLUME_ML * MAX_RESERVOIR_DILUTION; F32 ultrafiltrationFlowMLP = getCurrentUFSetRate(); Index: firmware/App/Services/Reservoirs.h =================================================================== diff -u -r867eed1d3a71f8fac87ac6dece093a391663188a -r5addd92e279ebc0871364fee70e3ac74db21001a --- firmware/App/Services/Reservoirs.h (.../Reservoirs.h) (revision 867eed1d3a71f8fac87ac6dece093a391663188a) +++ firmware/App/Services/Reservoirs.h (.../Reservoirs.h) (revision 5addd92e279ebc0871364fee70e3ac74db21001a) @@ -31,7 +31,6 @@ U32 timeDepletionMS; U32 timeWaitFillMS; F32 tempRemoveTragetFillFlow; - } RESERVOIRS_MANAGEMENT_DATA_T; // ********** public function prototypes ********** @@ -42,7 +41,7 @@ void execReservoirs( void ); -U32 getReservoirCycleTime( void ); +void setHeatersTemperatureAndTime( void ); /**@}*/ Index: firmware/App/Services/SystemComm.c =================================================================== diff -u -r9ac7866cce73b5281c34626ab5903409778e2b19 -r5addd92e279ebc0871364fee70e3ac74db21001a --- firmware/App/Services/SystemComm.c (.../SystemComm.c) (revision 9ac7866cce73b5281c34626ab5903409778e2b19) +++ firmware/App/Services/SystemComm.c (.../SystemComm.c) (revision 5addd92e279ebc0871364fee70e3ac74db21001a) @@ -981,7 +981,7 @@ handleDGOpMode( message ); break; - case MSG_ID_DG_RESERVOIR_DATA: + case MSG_ID_DG_RESERVOIRS_DATA: handleDGReservoirData( message ); break; Index: firmware/App/Services/SystemCommMessages.c =================================================================== diff -u -r9ac7866cce73b5281c34626ab5903409778e2b19 -r5addd92e279ebc0871364fee70e3ac74db21001a --- firmware/App/Services/SystemCommMessages.c (.../SystemCommMessages.c) (revision 9ac7866cce73b5281c34626ab5903409778e2b19) +++ firmware/App/Services/SystemCommMessages.c (.../SystemCommMessages.c) (revision 5addd92e279ebc0871364fee70e3ac74db21001a) @@ -1365,15 +1365,17 @@ /*********************************************************************//** * @brief - * The sendDialysateTempTargetsToDG function constructs a dialysate temperature - * set points message for DG and queues the msg for transmit on the appropriate CAN channel. + * The sendDialysateTempTargetsAndReservoirCycleTimeToDG function constructs a + * dialysate temperature set points message and the active reservoir cycle time + * for DG and queues the msg for transmit on the appropriate CAN channel. * @details Inputs: none * @details Outputs: Dialysate temperature set points msg constructed and queued. - * @param primary temperature set point for primary heater - * @param trimmer temperature set point for trimmer heater + * @param trimmer temperature set point for trimmer heater + * @param rsrvrCycleTime active reservoir cycle time in milliseconds + * @param rsrvrWait2Switch time to switch the inactive and active reservoirs in milliseconds * @return TRUE if msg successfully queued for transmit, FALSE if not *************************************************************************/ -BOOL sendDialysateTempTargetsToDG( F32 primary, F32 trimmer ) +BOOL sendDialysateHeatingParamsToDG( DG_CMD_DIALYSATE_HEATING_PARAMS_T *params ) { BOOL result; MESSAGE_T msg; @@ -1382,11 +1384,9 @@ // Create a message record blankMessage( &msg ); msg.hdr.msgID = MSG_ID_SET_DG_DIALYSATE_TEMP_TARGETS; - msg.hdr.payloadLen = sizeof( F32 ) + sizeof( F32 ); + msg.hdr.payloadLen = sizeof( DG_CMD_DIALYSATE_HEATING_PARAMS_T ); - memcpy( payloadPtr, &primary, sizeof( F32 ) ); - payloadPtr += sizeof( F32 ); - memcpy( payloadPtr, &trimmer, sizeof( F32 ) ); + memcpy( payloadPtr, params, sizeof( DG_CMD_DIALYSATE_HEATING_PARAMS_T ) ); // Serialize the message (w/ sync, CRC, and appropriate CAN padding) and add serialized message data to appropriate comm buffer result = serializeMessage( msg, COMM_BUFFER_OUT_CAN_HD_2_DG, ACK_REQUIRED ); @@ -2324,11 +2324,11 @@ *************************************************************************/ void handleDialysateFlowData( MESSAGE_T *message ) { - if ( message->hdr.payloadLen == sizeof(DIALYSATE_FLOW_METER_DATA_T) ) + if ( message->hdr.payloadLen == sizeof( DIALYSATE_FLOW_METER_DATA_T ) ) { DIALYSATE_FLOW_METER_DATA_T payload; - memcpy( &payload, message->payload, sizeof(DIALYSATE_FLOW_METER_DATA_T) ); + memcpy( &payload, message->payload, sizeof( DIALYSATE_FLOW_METER_DATA_T ) ); setDialysateFlowData( payload.measuredDialysateFlowRate ); } } Index: firmware/App/Services/SystemCommMessages.h =================================================================== diff -u -r9ac7866cce73b5281c34626ab5903409778e2b19 -r5addd92e279ebc0871364fee70e3ac74db21001a --- firmware/App/Services/SystemCommMessages.h (.../SystemCommMessages.h) (revision 9ac7866cce73b5281c34626ab5903409778e2b19) +++ firmware/App/Services/SystemCommMessages.h (.../SystemCommMessages.h) (revision 5addd92e279ebc0871364fee70e3ac74db21001a) @@ -350,7 +350,7 @@ // *********** public DG command functions ********** // MSG_ID_SET_DG_DIALYSATE_TEMP_TARGETS -BOOL sendDialysateTempTargetsToDG( F32 primary, F32 trimmer ); +BOOL sendDialysateHeatingParamsToDG( DG_CMD_DIALYSATE_HEATING_PARAMS_T *params ); // MSG_ID_DG_SWITCH_RESERVOIR_CMD BOOL sendDGSwitchReservoirCommand( U32 activeReservoir );