Index: firmware/App/Modes/ModePreTreat.c =================================================================== diff -u -rb4342a0db8b6db5d9f413648e243d5127d186c3c -r938fc2beedbb6153a2ac69c0d0c6b8abe209901d --- firmware/App/Modes/ModePreTreat.c (.../ModePreTreat.c) (revision b4342a0db8b6db5d9f413648e243d5127d186c3c) +++ firmware/App/Modes/ModePreTreat.c (.../ModePreTreat.c) (revision 938fc2beedbb6153a2ac69c0d0c6b8abe209901d) @@ -109,10 +109,10 @@ break; case PRE_TREATMENT_SELF_TEST_WET_STATE: - currentPreTreatmentState = PRE_TREATMENT_RECIRC_STATE; + currentPreTreatmentState = PRE_TREATMENT_RECIRCULATE_STATE; break; - case PRE_TREATMENT_RECIRC_STATE: + case PRE_TREATMENT_RECIRCULATE_STATE: currentPreTreatmentState = PRE_TREATMENT_PATIENT_CONNECTION_STATE; break; Index: firmware/App/Modes/Prime.c =================================================================== diff -u -rc7ffa13e306681a647ad25513a89250c6918e6a4 -r938fc2beedbb6153a2ac69c0d0c6b8abe209901d --- firmware/App/Modes/Prime.c (.../Prime.c) (revision c7ffa13e306681a647ad25513a89250c6918e6a4) +++ firmware/App/Modes/Prime.c (.../Prime.c) (revision 938fc2beedbb6153a2ac69c0d0c6b8abe209901d) @@ -18,9 +18,12 @@ #include "AirTrap.h" #include "AlarmMgmt.h" #include "BloodFlow.h" +#include "DialInFlow.h" +#include "DialOutFlow.h" #include "DGInterface.h" #include "Prime.h" #include "TaskGeneral.h" +#include "Timers.h" #include "Valves.h" /** @@ -35,6 +38,10 @@ #define NO_AIR_DETECTED_COUNT ( 10 * MS_PER_SECOND / TASK_GENERAL_INTERVAL ) ///< No air detected time period count. #define PURGE_AIR_TIME_OUT_COUNT ( 30 * MS_PER_SECOND / TASK_GENERAL_INTERVAL ) ///< Time period count for purge air time out. +#define DIALYSATE_PUMP_PRIME_FLOW_RATE 300 ///< Dialysate pump flow rate during priming fluid path. +#define LOAD_CELL_VOLUME_NOISE_TOLERANCE 0.05 ///< Allow 5% tolerance on load cell readings. +#define MIN_LOAD_CELL_STEADY_VOLUME_TIME ( 10 * MS_PER_SECOND ) ///< Minimum time load cell reading need to remain steady in ms. + #define PRIME_DRAIN_RESERVOIR_TO_VOLUME_ML 100 ///< Drain reservoir to this volume (in mL) during prime. #define PRIME_FILL_RESERVOIR_TO_VOLUME_ML 1700 ///< Fill reservoir to this volume (in mL) during prime. @@ -61,6 +68,9 @@ static U32 noAirDetectedTimerCounter; ///< No air detected timer counter. static U32 purgeAirTimeOutTimerCount; ///< Timer counter for purse air state time out. +static U32 previousLoadCellReading; ///< Previous load cell reading. +static U32 loadcellSteadyVolumeStartTime; ///< Load cell steady volume starting time. + // ********** private function prototypes ********** static void execPreTreatmentReservoirMgmt( void ); @@ -71,6 +81,8 @@ static PRE_TREATMENT_PRIME_STATE_T handlePrimeCircBloodCircuitState( void ); static PRE_TREATMENT_PRIME_STATE_T handlePrimeReservoirOneFillCompleteState( void ); static PRE_TREATMENT_PRIME_STATE_T handlePrimeDialysateDialyzerState( void ); +static PRE_TREATMENT_PRIME_STATE_T handlePrimeReservoirTwoFillCompleteState( void ); +static PRE_TREATMENT_PRIME_STATE_T handlePrimeDialysateBypassState( void ); /*********************************************************************//** * @brief @@ -102,6 +114,9 @@ primeStartReqReceived = TRUE; purgeAirTimeOutTimerCount = 0; + previousLoadCellReading = 0; + loadcellSteadyVolumeStartTime = 0; + reservoirFilledStatus[ DG_RESERVOIR_1 ] = FALSE; reservoirFilledStatus[ DG_RESERVOIR_2 ] = FALSE; } @@ -143,6 +158,14 @@ currentPrimeState = handlePrimeDialysateDialyzerState(); break; + case PRIME_RESERVOIR_TWO_FILL_COMPLETE_STATE: + currentPrimeState = handlePrimeReservoirTwoFillCompleteState(); + break; + + case PRIME_DIALYSATE_BYPASS_STATE: + currentPrimeState = handlePrimeDialysateBypassState(); + break; + default: currentPrimeState = PRIME_START_STATE; SET_ALARM_WITH_2_U32_DATA( ALARM_ID_HD_SOFTWARE_FAULT, SW_FAULT_ID_MODE_PRE_TREATMENT_PRIME_INVALID_STATE, (U32)currentReservoirMgmtState ); @@ -358,7 +381,7 @@ * The handlePrimeReservoirOneFillCompleteState function waits for DG to finish * filling reservoir 1 before moving to priming dialyzer. * @details Inputs: reservoirFilledStatus[] - * @details Outputs: none + * @details Outputs: update valves and pumps configuration on state change * @return current state *************************************************************************/ static PRE_TREATMENT_PRIME_STATE_T handlePrimeReservoirOneFillCompleteState( void ) @@ -367,6 +390,17 @@ if ( TRUE == reservoirFilledStatus[ DG_RESERVOIR_1 ] ) { + setValvePosition( VDI, VALVE_POSITION_B_OPEN ); + setValvePosition( VDO, VALVE_POSITION_B_OPEN ); + setValvePosition( VBA, VALVE_POSITION_C_CLOSE ); + setValvePosition( VBV, VALVE_POSITION_C_CLOSE ); + setValveAirTrap( STATE_CLOSED ); + + setDialInPumpTargetFlowRate( DIALYSATE_PUMP_PRIME_FLOW_RATE, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); + setDialOutPumpTargetRate( DIALYSATE_PUMP_PRIME_FLOW_RATE, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); + + previousLoadCellReading = 0; + loadcellSteadyVolumeStartTime = 0; state = PRIME_DIALYSATE_DIALYZER_STATE; } @@ -377,15 +411,88 @@ * @brief * The handlePrimeDialysateDialyzerState function handles priming for * dialysate dialyzer fluid path. - * @details Inputs: none - * @details Outputs: isPrimeCompleted + * @details Inputs: reservoir 1 filtered weight + * @details Outputs: primed dialysate dialyzer fluid path * @return current state *************************************************************************/ static PRE_TREATMENT_PRIME_STATE_T handlePrimeDialysateDialyzerState( void ) { - // TODO: Add priming for dialysate circuit - isPrimeCompleted = TRUE; - return PRIME_DIALYSATE_DIALYZER_STATE; + PRE_TREATMENT_PRIME_STATE_T state = PRIME_DIALYSATE_DIALYZER_STATE; + + F32 const loadcellWeight = getReservoirWeightSmallFilter( LOAD_CELL_RESERVOIR_1_PRIMARY ); + F32 const weightChange = fabs( 1.0 - ( previousLoadCellReading / loadcellWeight ) ); + + if ( weightChange < LOAD_CELL_VOLUME_NOISE_TOLERANCE ) + { + if ( TRUE == didTimeout( loadcellSteadyVolumeStartTime, MIN_LOAD_CELL_STEADY_VOLUME_TIME ) ) + { + state = PRIME_RESERVOIR_TWO_FILL_COMPLETE_STATE; + } + } + else + { + previousLoadCellReading = loadcellWeight; + loadcellSteadyVolumeStartTime = getMSTimerCount(); + } + + return state; } +/*********************************************************************//** + * @brief + * The handlePrimeReservoirTwoFillCompleteState function waits for DG to finish + * filling reservoir 2 before moving to pre-treatment re-circulation. + * @details Inputs: reservoirFilledStatus[] + * @details Outputs: update valves and pumps configuration on state change + * @return current state + *************************************************************************/ +static PRE_TREATMENT_PRIME_STATE_T handlePrimeReservoirTwoFillCompleteState( void ) +{ + PRE_TREATMENT_PRIME_STATE_T state = PRIME_DIALYSATE_DIALYZER_STATE; + + if ( TRUE == reservoirFilledStatus[ DG_RESERVOIR_2 ] ) + { + signalDialOutPumpHardStop(); + setDialInPumpTargetFlowRate( DIALYSATE_PUMP_PRIME_FLOW_RATE, MOTOR_DIR_FORWARD, PUMP_CONTROL_MODE_OPEN_LOOP ); + + setValvePosition( VDI, VALVE_POSITION_C_CLOSE ); + setValvePosition( VDO, VALVE_POSITION_C_CLOSE ); + setValvePosition( VBA, VALVE_POSITION_C_CLOSE ); + setValvePosition( VBV, VALVE_POSITION_C_CLOSE ); + setValveAirTrap( STATE_CLOSED ); + + previousLoadCellReading = 0; + loadcellSteadyVolumeStartTime = getMSTimerCount(); + state = PRIME_DIALYSATE_BYPASS_STATE; + } + + return state; +} + +/*********************************************************************//** + * @brief + * The handlePrimeDialysateDialyzerState function handles priming for + * dialysate dialyzer fluid path. + * @details Inputs: reservoir 2 filtered weight + * @details Outputs: primed dialysate bypass fluid path + * @return current state + *************************************************************************/ +static PRE_TREATMENT_PRIME_STATE_T handlePrimeDialysateBypassState( void ) +{ + F32 const loadcellWeight = getReservoirWeightSmallFilter( LOAD_CELL_RESERVOIR_2_PRIMARY ); + F32 const weightChange = fabs( 1.0 - ( previousLoadCellReading / loadcellWeight ) ); + + if ( weightChange < LOAD_CELL_VOLUME_NOISE_TOLERANCE ) + { + isPrimeCompleted = didTimeout( loadcellSteadyVolumeStartTime, MIN_LOAD_CELL_STEADY_VOLUME_TIME ); + } + else + { + previousLoadCellReading = loadcellWeight; + loadcellSteadyVolumeStartTime = getMSTimerCount(); + } + + return PRIME_DIALYSATE_BYPASS_STATE; +} + /**@}*/