Index: firmware/App/Controllers/DryBiCart.c =================================================================== diff -u -rfd897db8177752330ad08d877e0a13620513dbdc -r158684426a4bd277a7b21626393eb6f41e705165 --- firmware/App/Controllers/DryBiCart.c (.../DryBiCart.c) (revision fd897db8177752330ad08d877e0a13620513dbdc) +++ firmware/App/Controllers/DryBiCart.c (.../DryBiCart.c) (revision 158684426a4bd277a7b21626393eb6f41e705165) @@ -8,7 +8,7 @@ * @file DryBiCart.c * * @author (last) Sameer Kalliadan Poyil -* @date (last) 16-Apr-2026 +* @date (last) 29-Apr-2026 * * @author (original) Vinayakam Mani * @date (original) 19-Nov-2025 @@ -45,14 +45,18 @@ #define DRY_BICART_DATA_PUBLISH_INTERVAL ( 250 / TASK_GENERAL_INTERVAL ) ///< Interval (ms/task time) at which the balancing chamber data published. // Dry Bicart Fill -#define DRY_BICART_FILL_DURATION_MIN_MS ( 2 * MS_PER_SECOND ) ///< Minimum fill duration to be met to end the fill cycle. +#define DRY_BICART_FILL_PERSISTANCE_DURATION_MS 200 ///< Fill persistence duration to overcome the pressure over shoot for beta 1.9 and beta 2.0. +#define DRY_BICART_FILL_DURATION_MIN_MS ( ( 2 * MS_PER_SECOND ) + \ + DRY_BICART_FILL_PERSISTANCE_DURATION_MS ) ///< Minimum fill duration to be met to end the fill cycle. #define DRY_BICART_FILL_COMPLETE_TIME_MS ( 1 * MS_PER_SECOND ) ///< Wait time to reset the request flag after fill complete #define DRY_BICART_FILL_DURATION_DIFF_MS 750 ///< Fill duration difference between last and current fill cycle. -#define PRESSURE_OFFSET 2 ///< Dry bicart pressure offset -#define DRY_BICART_FILL_COMPLETE_PRESSURE ( 10.0F + PRESSURE_OFFSET ) ///< Maximum pressure reached to indicate the dry bicart fill being completed. -#define DRY_BICART_FILL_INITIATE_PRESSURE 3.0F ///< Minimum pressure required to initiate the dry bicart fill process. -#define DRY_BICART_FILL_COMPLETE_SUPPLY_PRESSURE 6.0F ///< Maximum pressure allowed at bicart fill during supply process/state + +#define PRESSURE_OFFSET_PSI 1.0F ///< Dry bicart pressure offset. +#define DRY_BICART_FILL_COMPLETE_PRESSURE ( 10.0F + PRESSURE_OFFSET_PSI ) ///< Maximum pressure reached to indicate the dry bicart fill being completed. +#define DRY_BICART_FILL_INITIATE_PRESSURE 1.5F ///< Minimum pressure required to initiate the dry bicart fill process. +#define DRY_BICART_FILL_COMPLETE_SUPPLY_PRESSURE 8.0F ///< Maximum pressure allowed at bicart fill during supply process/state #define DRY_BICART_FILL_INITIATE_SUPPLY_PRESSURE 3.0F ///< Minimum pressure required to initiate the dry bicart fill during supply process/state +#define MAX_DRY_BICART_FILL_COMPLETE_PRESSURE 15.0F ///< Very max dry bicart fill complete pressure for persistence on d66 #define DRY_BICART_DEFAULT_MAX_FILL_CYCLE_CNT 10 ///< Default max fill cycle allowed for dry bicart fill/mix with water. #define DRY_BICART_MAX_FILL_CYCLE_CNT 30 ///< Max fill cycle allowed (by override) for dry bicart fill/mix with water. @@ -62,9 +66,14 @@ #define DRY_BICART_FILL_VENT_COMPLETE_PRESSURE 1.5F ///< Pressure reached to indicate the dry bicart venting being completed. // Bicarb chamber fill/Supply -#define DRY_BICART_SUPPLY_VALVE_D80_OPEN_TIME_MS ( 3 * MS_PER_SECOND ) ///< Max time allowed for supply (opening D80 valve) during bicarb chamber (F) fill. +#ifdef CONDUCTIVE_LEVEL_SENSOR_ENABLED +#define DRY_BICART_SUPPLY_VALVE_D80_OPEN_TIME_MS ( 10 * MS_PER_SECOND ) ///< Max time allowed for supply (opening D80 valve) during bicarb chamber (F) fill using level sensor +#else +#define DRY_BICART_SUPPLY_VALVE_D80_OPEN_TIME_MS ( 3 * MS_PER_SECOND ) ///< Max time allowed for supply (opening D80 valve) during bicarb chamber (F) fill time based fill +#endif #define DRY_BICART_SUPPLY_VENT_TIME_MS ( 1 * MS_PER_SECOND ) ///< Wait time to vent dry bicart gas before actuating Bicarb chamber(F) venting. -#define DRY_BICART_SUPPLY_VENT_MAX_TIME_MS ( 1.1 * MS_PER_SECOND ) ///< Max time to vent both dry bicart and Chamber F. +#define DRY_BICART_SUPPLY_VENT_MAX_TIME_MS ( 1 * MS_PER_SECOND ) ///< Max time to vent both dry bicart and Chamber F. +#define DRY_BICART_SUPPLY_COMPLETE_TIME_MS ( 2 * MS_PER_SECOND ) ///< Wait time to close the D80 valve after D65 is closed // Dry Bicart Drain #define LARGE_DRY_BICART_MAX_DRAIN_TIME_MS ( 8 * SEC_PER_MIN * MS_PER_SECOND ) ///< Max drain time for large dry bicart in ms. @@ -76,13 +85,13 @@ #define DRY_BICART_DRAIN_COND_STABLE_SAMPLES 10U ///< Debounce samples (10*50ms=500ms) // drybicarb mixing -#define BICARB_VOL_CONTROL_P_COEFFICIENT 0.00008484 ///< Bicarb proportional gain (kp) -#define BICARB_VOL_CONTROL_I_COEFFICIENT 0.00033936 ///< Bicarb integral gain. (ki) +#define BICARB_VOL_CONTROL_P_COEFFICIENT ( 0.00008484 * 2 ) ///< Bicarb proportional gain (kp) +#define BICARB_VOL_CONTROL_I_COEFFICIENT ( 0.00033936 / 5 ) ///< Bicarb integral gain. (ki) #define MIN_BICARB_VOLUME_ML 0.868686869 ///< Minimum bicarb volume in mL #define MAX_BICARB_VOLUME_ML 1.8 ///< Maximum bicarb volume in mL -#define ACID_VOL_CONTROL_P_COEFFICIENT (0.00000997/2) ///< Acid proportional gain (kp) -#define ACID_VOL_CONTROL_I_COEFFICIENT (0.00003988/2) ///< Acid integral gain. (ki) +#define ACID_VOL_CONTROL_P_COEFFICIENT ( 0.00000997 / 2 ) ///< Acid proportional gain (kp) +#define ACID_VOL_CONTROL_I_COEFFICIENT ( 0.00003988 / 2 ) ///< Acid integral gain. (ki) #define MIN_ACID_VOLUME_ML 0.3 ///< Minimum acid volume in mL #define MAX_ACID_VOLUME_ML 1.0 ///< Maximum acid volume in mL/min. @@ -101,9 +110,13 @@ #define MIX_NO_FEED_FORWARD 0.0F ///< Feedforward term for dialysate closed loop control -#define MIXING_CONTROL_INTERVAL_MS ( 15 * MS_PER_SECOND ) ///< Dialysate mixing control interval in ms -#define MIXING_CONTROL_INTERVAL ( MIXING_CONTROL_INTERVAL_MS /\ - TASK_GENERAL_INTERVAL ) ///< Interval (ms/task time) at which the dialysate mixing is controlled. +#define MIX_CONTROL_INTERVAL_MS ( 15 * MS_PER_SECOND ) ///< Dialysate mixing control interval in ms +#define BICARB_MIX_CONTROL_INTERVAL ( 3 * MS_PER_SECOND /\ + TASK_GENERAL_INTERVAL ) ///< Interval (ms/task time) at which the dialysate mix is controlled. +#define ACID_MIX_CONTROL_INTERVAL ( MIX_CONTROL_INTERVAL_MS /\ + TASK_GENERAL_INTERVAL ) ///< Interval (ms/task time) at which the dialysate mix is controlled. +#define BICARB_DEADBAND_CONTROL 50.0F ///< Dry Bicarb dead band control +#define ACID_DEADBAND_CONTROL 100.0F ///< Acid dead band control /// Payload record structure for dry bicart fill request typedef struct @@ -142,8 +155,8 @@ /// Dialysate Mixing state machine data structure typedef struct { - U32 controlTimerCounter; ///< Timer counter to perform control on dialysate mixing. - DIALYSATE_MIXING_STATE_T dialysateMixingState; ///< Current state of dialysate mixing controller state machine. + U32 controlTimerCounter; ///< Timer counter to perform control on dialysate mixing. + DIALYSATE_MIXING_STATE_T dialysateMixingState; ///< Current state of dialysate mixing controller state machine. } DIALYSATE_MIXING_DATA_T; // ********** private data ********** @@ -179,6 +192,8 @@ static U32 dryBiCartDrainCondStableCount; ///< Debounce counter for "zero" conductivity static U32 dryBiCartDrainTimePeriod; ///< Dry bicart drain time period +static U32 dryBiCartPersistanceStartTime; ///< Dry bicart fill start time. +static BOOL dryBiCartPressureDecayStartTimeFlag; ///< Dry bicart d66 pressure decay start timer. static DRY_BICART_OPERATION_T dryBicartStartRequest; ///< Dry bicart operation, fill or supply or drain request // drybicart mixing @@ -199,7 +214,7 @@ static OVERRIDE_F32_T dryBiCartDialysateTargetConductivity; ///< Acid bicarb mix conductivity static OVERRIDE_F32_T dryBiCartDialysateDeltaConductivity; ///< Acid bicarb delta conductivity -static OVERRIDE_F32_T dryBiCartMixControlInterval; ///< Mix control interval +static OVERRIDE_U32_T dryBiCartMixControlInterval; ///< Mix control interval static PI_CONTROLLER_SIGNALS_DATA bicarbControlSignals; ///< Bicarb closed loop control signal data static PI_CONTROLLER_SIGNALS_DATA acidControlSignals; ///< Acid closed loop control signal data @@ -230,7 +245,7 @@ static DRY_BICART_DRAIN_EXEC_STATE_T handleDryBicartFluidDrainDurationCheckState( void ); static DRY_BICART_DRAIN_EXEC_STATE_T handleDryBicartFluidDrainEndState( void ); -// dosing control loop +// Mixing control loop static DIALYSATE_MIXING_STATE_T handleDialysateMixOpenLoopState( DIALYSATE_MIXING_ID_T mixId ); static DIALYSATE_MIXING_STATE_T handleDialysateMixRampToTargetState( DIALYSATE_MIXING_ID_T mixId ); static DIALYSATE_MIXING_STATE_T handleDialysateMixControlToTargetState( DIALYSATE_MIXING_ID_T mixId ); @@ -247,7 +262,7 @@ static F32 getAcidKiGainCoefficient( void ); static F32 getDryBicartLowerCartPressure( void ); static F32 getDryBicartUpperCartPressure( void ); -static F32 getDryBicartMixControlInterval( void ); +static U32 getDryBicartMixControlInterval( void ); // publish the status static void publishDryBicartData( void ); @@ -366,11 +381,12 @@ dryBiCartLowerCartPressure.ovInitData = 0.0F; dryBiCartLowerCartPressure.override = OVERRIDE_RESET; - dryBiCartMixControlInterval.data = MIXING_CONTROL_INTERVAL; - dryBiCartMixControlInterval.ovData = MIXING_CONTROL_INTERVAL; - dryBiCartMixControlInterval.ovInitData = 0.0F; + dryBiCartMixControlInterval.data = BICARB_MIX_CONTROL_INTERVAL; + dryBiCartMixControlInterval.ovData = BICARB_MIX_CONTROL_INTERVAL; + dryBiCartMixControlInterval.ovInitData = 0; dryBiCartMixControlInterval.override = OVERRIDE_RESET; + dryBiCartPressureDecayStartTimeFlag = FALSE; dryBiCartFillStartTime = 0; lastFillDurationInMS = 0; currentFillDurationInMS = 0; @@ -382,6 +398,7 @@ dryBiCartDrainLastCondSampleTime = 0; dryBiCartDrainCondStableCount = 0; dryBiCartDrainTimePeriod = 0; + dryBiCartPersistanceStartTime = 0; initializePIController( PI_CONTROLLER_ID_BICARB_VOL, 0.0F,\ getBicarbKpGainCoefficient(), getBicarbKiGainCoefficient(),\ @@ -408,9 +425,9 @@ /*********************************************************************//** * @brief * The execDialysateCompositionMixingController function executes the dialysate mixing controller. - * @details \b Inputs: dialysateDosingState - * @details \b Outputs: dialysateDosingState - * @details \b Alarms: ALARM_ID_DD_SOFTWARE_FAULT if invalid dialysate dosing + * @details \b Inputs: dialysateMix[ mixId ].dialysateMixingState + * @details \b Outputs:dialysateMix[ mixId ].dialysateMixingState + * @details \b Alarms: ALARM_ID_DD_SOFTWARE_FAULT if invalid dialysate mixing * state machine found. * @return none *************************************************************************/ @@ -463,13 +480,12 @@ if( getCurrentBalancingChamberExecState() > BAL_CHAMBER_STATE_IDLE ) { - // closed loop bicarb and acid dosing controller + // closed loop bicarb and acid mixing controller execDialysateCompositionMixingController(); } // top level state machine selection DRY_BICART_OPERATION_T dryBicartState = dryBicartStartRequest; - U32 dryBicartSubstate; switch ( dryBicartState ) { @@ -998,9 +1014,9 @@ * @details \b Outputs: none * @return TRUE if successful, FALSE if not. *************************************************************************/ -static F32 getDryBicartMixControlInterval( void ) +static U32 getDryBicartMixControlInterval( void ) { - F32 result = getF32OverrideValue( &dryBiCartMixControlInterval ); + U32 result = getU32OverrideValue( &dryBiCartMixControlInterval ); return result; } @@ -1020,23 +1036,32 @@ if ( BICARB_MIX_ID == mixId ) { - result = DIALYSATE_MIXING_OPEN_LOOP_STATE; F32 measuredBicarbConductivity = getFilteredConductivity( D17_COND ); - // if measured conductivity crossed (targetConductivity- deltaConuctivity) , switch to closed loop - if ( measuredBicarbConductivity >= ( getBicarbTargetConductivity() - getBicarbDeltaConductivity() ) ) + + result = DIALYSATE_MIXING_OPEN_LOOP_STATE; + + if ( TRUE != getTestConfigStatus( TEST_CONFIG_DD_ENABLE_DOSING_OPEN_LOOP_CONTROL ) ) { - result = DIALYSATE_MIXING_RAMP_UP_STATE; + // if measured conductivity crossed (targetConductivity- deltaConuctivity) , switch to closed loop + if ( measuredBicarbConductivity >= ( getBicarbTargetConductivity() - getBicarbDeltaConductivity() ) ) + { + result = DIALYSATE_MIXING_RAMP_UP_STATE; + } } } else if ( ACID_MIX_ID == mixId ) { - result = DIALYSATE_MIXING_OPEN_LOOP_STATE; F32 measuredAcidBicarbMixConductivity = getFilteredConductivity( D27_COND ); - // if measured conductivity crossed (targetConductivity- deltaConuctivity) , switch to closed loop - if ( measuredAcidBicarbMixConductivity >= ( getAcidBicarbTargetConductivity() - getAcidBicarbDeltaConductivity() ) ) + result = DIALYSATE_MIXING_OPEN_LOOP_STATE; + + if ( TRUE != getTestConfigStatus( TEST_CONFIG_DD_ENABLE_DOSING_OPEN_LOOP_CONTROL ) ) { - result = DIALYSATE_MIXING_RAMP_UP_STATE; + // if measured conductivity crossed (targetConductivity- deltaConuctivity) , switch to closed loop + if ( measuredAcidBicarbMixConductivity >= ( getAcidBicarbTargetConductivity() - getAcidBicarbDeltaConductivity() ) ) + { + result = DIALYSATE_MIXING_RAMP_UP_STATE; + } } } @@ -1084,38 +1109,53 @@ { DIALYSATE_MIXING_STATE_T state = DIALYSATE_MIXING_CONTROL_TO_TARGET_STATE; - // control at set minimum interval or interval is expired and balance chamber fill is complete - if ( ( ++dialysateMix[ mixId ].controlTimerCounter >= getDryBicartMixControlInterval() ) ) + if ( BICARB_MIX_ID == mixId ) { - dialysateMix[ mixId ].controlTimerCounter = 0; - - // Control based on the measured and target conductivity - if ( BICARB_MIX_ID == mixId ) + // control interval for bicarb + if ( ( ++dialysateMix[ mixId ].controlTimerCounter >= getDryBicartMixControlInterval() ) ) { + F32 bicarbMixVol; + + dialysateMix[ mixId ].controlTimerCounter = 0; + + // Control based on the measured and target conductivity PI_CONTROLLER_SIGNALS_DATA debugBicarbControl; F32 measuredBicarbConductivity; measuredBicarbConductivity = getFilteredConductivity( D17_COND ); - F32 bicarbMixVol = runPIController( PI_CONTROLLER_ID_BICARB_VOL, getBicarbTargetConductivity(), measuredBicarbConductivity ); - //Set bicarb dosing vol - setBicarbMixVol( bicarbMixVol ); + if ( fabs ( getBicarbTargetConductivity() - measuredBicarbConductivity ) > BICARB_DEADBAND_CONTROL ) + { + bicarbMixVol = runPIController( PI_CONTROLLER_ID_BICARB_VOL, getBicarbTargetConductivity(), measuredBicarbConductivity ); + //Set bicarb mix vol only if its above dead band threshold, else use the previous set vlaue + setBicarbMixVol( bicarbMixVol ); + } + debugBicarbControl = getDebugPIControllerSignals( PI_CONTROLLER_ID_BICARB_VOL ); memcpy( (void*)&bicarbControlSignals, (void*)&debugBicarbControl, sizeof(PI_CONTROLLER_SIGNALS_DATA) ); } - // ACID Mix - else if ( ACID_MIX_ID == mixId ) + } + + if ( ACID_MIX_ID == mixId ) + { + // control interval for acid + if ( ( ++dialysateMix[ mixId ].controlTimerCounter >= ACID_MIX_CONTROL_INTERVAL ) ) { - F32 measuredAcidBicarbMixConductivity; - PI_CONTROLLER_SIGNALS_DATA debugAcidControl; + F32 acidMixVol; - measuredAcidBicarbMixConductivity = getFilteredConductivity( D27_COND ); + dialysateMix[ mixId ].controlTimerCounter = 0; - F32 acidMixVol = runPIController( PI_CONTROLLER_ID_ACID_VOL, getAcidBicarbTargetConductivity(), measuredAcidBicarbMixConductivity ); - //Set acid dosing vol - setAcidMixVol( acidMixVol ); + F32 measuredAcidBicarbMixConductivity = getFilteredConductivity( D27_COND ); + PI_CONTROLLER_SIGNALS_DATA debugAcidControl; + if ( fabs ( getAcidBicarbTargetConductivity() - measuredAcidBicarbMixConductivity ) > ACID_DEADBAND_CONTROL ) + { + acidMixVol = runPIController( PI_CONTROLLER_ID_ACID_VOL, getAcidBicarbTargetConductivity(), measuredAcidBicarbMixConductivity ); + // set acid mix volume if its above dead band threshold , else use previous set value + setAcidMixVol( acidMixVol ); + } + debugAcidControl = getDebugPIControllerSignals( PI_CONTROLLER_ID_ACID_VOL ); memcpy( (void*)&acidControlSignals, (void*)&debugAcidControl, sizeof(PI_CONTROLLER_SIGNALS_DATA) ); @@ -1174,11 +1214,12 @@ //if(FP_MODE_GENP == getCurrentFPOperationMode()) { // TODO: pre gen should start the D12 pump and D14 valve - //setValveState( D14_VALV, VALVE_STATE_OPEN ); + setValveState( D14_VALV, VALVE_STATE_OPEN ); setDialysatePumpTargetRPM( D12_PUMP, FRESH_DIAL_PUMP_INITIAL_RPM_B1_9_B2_0, TRUE ); state = DRY_BICART_FILL_WATER_START_STATE; } + // TODO: alarm if fill requested without IOFP in Gen mode } return state; @@ -1227,15 +1268,40 @@ DRY_BICART_FILL_EXEC_STATE_T state = DRY_BICART_FILL_WATER_END_STATE; F32 d66Pressure = getFilteredPressure( D66_PRES ); - // Close dry bicart inlet water if bicart is filled with water + // Close dry bicart inlet water if D66 pressure is 11 PSIr if ( d66Pressure >= DRY_BICART_FILL_COMPLETE_PRESSURE ) { - setValveState( D65_VALV, VALVE_STATE_CLOSED ); - lastFillDurationInMS = currentFillDurationInMS; - currentFillDurationInMS = calcTimeSince( dryBiCartFillStartTime ); - //Increment number of fill cycle - biCartFillCycleCounter++; - state = DRY_BICART_DEGAS_START_STATE; + // start the persistance timer once d66 reaches 11 PSI + if ( 0 == dryBiCartPersistanceStartTime ) + { + dryBiCartPersistanceStartTime = getMSTimerCount(); + } + //check the the maximum cart pressure during persistence on D66 + if ( d66Pressure >= MAX_DRY_BICART_FILL_COMPLETE_PRESSURE ) + { + setValveState( D65_VALV, VALVE_STATE_CLOSED ); + + lastFillDurationInMS = currentFillDurationInMS; + currentFillDurationInMS = calcTimeSince( dryBiCartFillStartTime ); + //Increment number of fill cycle + biCartFillCycleCounter++; + dryBiCartPersistanceStartTime = 0; + + state = DRY_BICART_DEGAS_START_STATE; + } + // 200 ms persistence on D66 pressure since pressure overshoot just after D65 opening + if ( TRUE == didTimeout( dryBiCartPersistanceStartTime, DRY_BICART_FILL_PERSISTANCE_DURATION_MS ) ) + { + setValveState( D65_VALV, VALVE_STATE_CLOSED ); + + lastFillDurationInMS = currentFillDurationInMS; + currentFillDurationInMS = calcTimeSince( dryBiCartFillStartTime ); + //Increment number of fill cycle + biCartFillCycleCounter++; + dryBiCartPersistanceStartTime = 0; + + state = DRY_BICART_DEGAS_START_STATE; + } } //TODO:Handle timeout alarm for opening D65 valve too long @@ -1258,7 +1324,7 @@ //Close D64 setValveState( D64_VALV, VALVE_STATE_CLOSED); - //Vent bicart + //Vent bicart to chamber F setValveState( D85_VALV, VALVE_STATE_OPEN ); //Initiate timer to measure length of bicart vent @@ -1283,11 +1349,11 @@ if ( TRUE == didTimeout( dryBiCartFillStartTime, DRY_BICART_FILL_VENT_TIME_MS ) ) { - //Vent chamber F + //Vent chamber F to atmosphere setValveState( D64_VALV, VALVE_STATE_OPEN ); } - // D66 pressure drops or time out + // D66 pressure drops to below 1.5 PSI or time out if ( ( d66Pressure <= DRY_BICART_FILL_VENT_COMPLETE_PRESSURE ) || ( TRUE == didTimeout( dryBiCartFillStartTime, DRY_BICART_FILL_VENT_MAX_TIME_MS ) ) ) { @@ -1371,8 +1437,8 @@ if ( TRUE == didTimeout( dryBiCartFillStartTime, DRY_BICART_FILL_COMPLETE_TIME_MS ) ) { currentFillDurationInMS = 0; - lastFillDurationInMS = 0; - biCartFillCycleCounter = 0; + lastFillDurationInMS = 0; + biCartFillCycleCounter = 0; // Go idle dryBiCartFillRequested.data = FALSE; // for this request override also cleared @@ -1409,6 +1475,8 @@ { BICARB_CHAMBER_FILL_EXEC_STATE_T state = BICARB_CHAMBER_START_STATE; + dryBiCartPressureDecayStartTimeFlag = FALSE; + if ( TRUE == getU32OverrideValue( &bicarbChamberFillRequested ) ) { state = BICARB_CARTRIDGE_FILL_WATER_START_STATE; @@ -1428,13 +1496,17 @@ BICARB_CHAMBER_FILL_EXEC_STATE_T state = BICARB_CARTRIDGE_FILL_WATER_END_STATE; // Close vent valves and descaling valve + setValveState( D80_VALV, VALVE_STATE_CLOSED ); setValveState( D81_VALV, VALVE_STATE_CLOSED ); - setValveState( D64_VALV, VALVE_STATE_CLOSED ); setValveState( D85_VALV, VALVE_STATE_CLOSED ); // open inlet water to bicart setValveState( D65_VALV, VALVE_STATE_OPEN ); + setValveState( D64_VALV, VALVE_STATE_OPEN ); + dryBiCarbSupplyStartTime = getMSTimerCount(); + dryBiCartPersistanceStartTime = 0; + return state; } @@ -1450,11 +1522,28 @@ BICARB_CHAMBER_FILL_EXEC_STATE_T state = BICARB_CARTRIDGE_FILL_WATER_END_STATE; F32 d66Pressure = getFilteredPressure( D66_PRES ); - if ( d66Pressure >= getDryBicartUpperCartPressure() ) + // check D66 is 11 PSI + if ( d66Pressure >= DRY_BICART_FILL_COMPLETE_PRESSURE ) { - // Close water inlet valve as D66 pressure reaches 15 PSI. - setValveState( D65_VALV, VALVE_STATE_CLOSED ); - state = BICARB_CHAMBER_CHECK_LEVEL_STATE; + // persistence + // check the the maximum cart pressure during persistence on D66 + if ( d66Pressure >= MAX_DRY_BICART_FILL_COMPLETE_PRESSURE ) + { + // Close water inlet valve as D66 pressure reaches max PSI(14-15) after persistence + setValveState( D65_VALV, VALVE_STATE_CLOSED ); + dryBiCartPersistanceStartTime = 0; + + state = BICARB_CHAMBER_CHECK_LEVEL_STATE; + } + // 200 ms persistence on D66 pressure since pressure overshoot just after D65 opening + if ( TRUE == didTimeout( dryBiCartPersistanceStartTime, DRY_BICART_FILL_PERSISTANCE_DURATION_MS ) ) + { + // Close water inlet valve as D66 pressure reaches 11 PSI after persistence + setValveState( D65_VALV, VALVE_STATE_CLOSED ); + dryBiCartPersistanceStartTime = 0; + + state = BICARB_CHAMBER_CHECK_LEVEL_STATE; + } } return state; @@ -1471,23 +1560,17 @@ static BICARB_CHAMBER_FILL_EXEC_STATE_T handleBicarbChamberCheckLevelState( void ) { BICARB_CHAMBER_FILL_EXEC_STATE_T state = BICARB_CHAMBER_CHECK_LEVEL_STATE; - LEVEL_STATE_T bicarbChamberLevel = getBicarbChamberLevelStatus(); - // TODO: Confirm D80 open on chamber low or end of balancing chamber switching? - // TODO: Enable the below code once level sensor is working - //if ( LEVEL_STATE_LOW == bicarbChamberLevel ) - { - // if ( getBalancingChamberFillinProgressStatus() == FALSE ) - { - // Open the Bicarb chamber inlet valve - setValveState( D80_VALV, VALVE_STATE_OPEN ); + // TODO: set supply in progress to inform BC control to disable alarm + setValveState( D64_VALV, VALVE_STATE_CLOSED ); + // Open the Bicarb chamber inlet valve + setValveState( D80_VALV, VALVE_STATE_OPEN ); - // Start a timer when bicarb supply started to chamber F - dryBiCarbSupplyStartTime = getMSTimerCount(); + // Start a timer when bicarb supply started to chamber F + dryBiCarbSupplyStartTime = getMSTimerCount(); - state = BICARB_CHAMBER_FILL_STATE; - } - } + state = BICARB_CHAMBER_FILL_STATE; + // TODO: alarm return state; @@ -1505,10 +1588,10 @@ { BICARB_CHAMBER_FILL_EXEC_STATE_T state = BICARB_CHAMBER_FILL_STATE; F32 d66Pressure = getFilteredPressure( D66_PRES ); - LEVEL_STATE_T bicarbChamberLevel = getBicarbChamberLevelStatus(); + LVL_STATE_T bicarbChamberLevel = getBicarbChamberLevelStatus(); // Once level reached, close the valve - if ( LEVEL_STATE_HIGH == bicarbChamberLevel ) + if ( LVL_STATE_HIGH == bicarbChamberLevel ) { setValveState( D80_VALV, VALVE_STATE_CLOSED ); state = BICARB_CHAMBER_PRESSURE_CHECK_STATE; @@ -1539,26 +1622,59 @@ { BICARB_CHAMBER_FILL_EXEC_STATE_T state = BICARB_CHAMBER_PRESSURE_CHECK_STATE; F32 d66Pressure = getFilteredPressure( D66_PRES ); - LEVEL_STATE_T bicarbChamberLevel = getBicarbChamberLevelStatus(); + LVL_STATE_T bicarbChamberLevel = getBicarbChamberLevelStatus(); - // Once level reached, close the valve - if ( ( LEVEL_STATE_HIGH == bicarbChamberLevel ) || + // Once level reached, close the valve, timeout is for safety in case level sensor didn't work, or else its a time based filling + if ( ( LVL_STATE_HIGH == bicarbChamberLevel ) || ( TRUE == didTimeout( dryBiCarbSupplyStartTime, DRY_BICART_SUPPLY_VALVE_D80_OPEN_TIME_MS ) ) ) { setValveState( D65_VALV, VALVE_STATE_CLOSED ); - setValveState( D80_VALV, VALVE_STATE_CLOSED ); - dryBiCarbSypplyVentStartTime = getMSTimerCount(); - state = BICARB_SUPPLY_VENT_START_STATE; + // start the timer for d66 pressure decay + if( FALSE == dryBiCartPressureDecayStartTimeFlag ) + { + dryBiCarbSupplyStartTime = getMSTimerCount(); + dryBiCartPressureDecayStartTimeFlag = TRUE; + } + + // do not close the D80 valve, wait till d66 decays to 3 PSI + if ( TRUE == didTimeout( dryBiCarbSupplyStartTime, DRY_BICART_SUPPLY_COMPLETE_TIME_MS ) ) + { + if ( d66Pressure <= getDryBicartLowerCartPressure() ) + { + setValveState( D80_VALV, VALVE_STATE_CLOSED ); + setValveState( D85_VALV, VALVE_STATE_OPEN ); + dryBiCarbSypplyVentStartTime = getMSTimerCount(); + + state = BICARB_SUPPLY_VENT_START_STATE; + } + } } - /*else if ( d66Pressure <= getDryBicartLowerCartPressure() ) + else if ( d66Pressure <= getDryBicartLowerCartPressure() ) { - setValveState( D65_VALV, VALVE_STATE_OPEN ); } + setValveState( D65_VALV, VALVE_STATE_OPEN ); + } // Close water inlet valve as fill is complete. else if ( d66Pressure >= getDryBicartUpperCartPressure() ) { - setValveState( D65_VALV, VALVE_STATE_CLOSED ); - }*/ + // start persistance timer + if ( 0 == dryBiCartPersistanceStartTime ) + { + dryBiCartPersistanceStartTime = getMSTimerCount(); + } + //check the the maximum cart pressure during persistence on D66 + if ( d66Pressure >= MAX_DRY_BICART_FILL_COMPLETE_PRESSURE ) + { + setValveState( D65_VALV, VALVE_STATE_CLOSED ); + dryBiCartPersistanceStartTime = 0; + } + // 200 ms persistence on D66 pressure since pressure overshoot just after D65 opening + if ( TRUE == didTimeout( dryBiCartPersistanceStartTime, DRY_BICART_FILL_PERSISTANCE_DURATION_MS ) ) + { + setValveState( D65_VALV, VALVE_STATE_CLOSED ); + dryBiCartPersistanceStartTime = 0; + } + } return state; } @@ -1574,64 +1690,21 @@ static BICARB_CHAMBER_FILL_EXEC_STATE_T handleBicarbChamberSupplyVentStartState(void) { BICARB_CHAMBER_FILL_EXEC_STATE_T state = BICARB_SUPPLY_VENT_START_STATE; - float setpoint; - U32 startTime; F32 d66Pressure = getFilteredPressure( D66_PRES ); - F32 tmpD66Pressure = getFilteredPressure( D66_PRES ); - setpoint = d66Pressure - 1.0; - - if ( ( d66Pressure > DRY_BICART_FILL_INITIATE_SUPPLY_PRESSURE ) ) + // open D64 after 1 sec + if ( TRUE == didTimeout( dryBiCarbSypplyVentStartTime, DRY_BICART_SUPPLY_VENT_MAX_TIME_MS ) ) { setValveState( D64_VALV, VALVE_STATE_OPEN ); - state = BICARB_SUPPLY_VENT_END_STATE; } - //if ( TRUE == didTimeout( dryBiCarbSupplyStartTime, 10 ) ) -#if 0 - while ( tmpD66Pressure >= getDryBicartLowerCartPressure() && tmpD66Pressure >= setpoint ) { - //setpoint = d66Pressure - 1.0; - - // Venting loop: stay open until target PSI is reached - setValveState( D64_VALV, VALVE_STATE_CLOSED ); - setValveState( D85_VALV, VALVE_STATE_OPEN ); - startTime = getMSTimerCount(); - while ( TRUE != didTimeout( startTime, 12 ) ) - { - } - // close the vallve - setValveState( D85_VALV, VALVE_STATE_CLOSED ); - setValveState( D64_VALV, VALVE_STATE_OPEN ); - startTime = getMSTimerCount(); - while ( TRUE != didTimeout( startTime, 100 ) ) - { - } - tmpD66Pressure = getFilteredPressure( D66_PRES ); - //sleep - } -#endif - else if ( TRUE == didTimeout( dryBiCarbSypplyVentStartTime, DRY_BICART_SUPPLY_VENT_TIME_MS ) ) + // D66 pressure drops to 1.5 or time out + if ( ( d66Pressure <= DRY_BICART_FILL_VENT_COMPLETE_PRESSURE ) || + ( TRUE == didTimeout( dryBiCarbSypplyVentStartTime, DRY_BICART_FILL_VENT_MAX_TIME_MS ) ) ) { - //Vent bicart after 1 sec - setValveState( D85_VALV, VALVE_STATE_OPEN ); - } - else if ( TRUE == didTimeout( dryBiCarbSypplyVentStartTime, DRY_BICART_SUPPLY_VENT_MAX_TIME_MS ) ) - { setValveState( D85_VALV, VALVE_STATE_CLOSED ); - //Vent chamber F after 200 ms - setValveState( D64_VALV, VALVE_STATE_OPEN ); - dryBiCarbSypplyVentStartTime = getMSTimerCount(); - //state = BICARB_SUPPLY_VENT_END_STATE; - } - // D66 pressure drops or time out - else if ( ( d66Pressure <= DRY_BICART_FILL_INITIATE_SUPPLY_PRESSURE ) /*|| - ( TRUE == didTimeout( dryBiCarbSypplyVentStartTime, DRY_BICART_FILL_VENT_MAX_TIME_MS ) )*/ ) - { - setValveState( D64_VALV, VALVE_STATE_OPEN ); - setValveState( D85_VALV, VALVE_STATE_CLOSED ); - dryBiCarbSypplyVentStartTime = getMSTimerCount(); state = BICARB_SUPPLY_VENT_END_STATE; } @@ -1650,19 +1723,14 @@ { BICARB_CHAMBER_FILL_EXEC_STATE_T state = BICARB_SUPPLY_VENT_END_STATE; - // close bicart vent and chamber f vent after 1 sec - if ( TRUE == didTimeout( dryBiCarbSypplyVentStartTime, DRY_BICART_SUPPLY_VENT_TIME_MS ) ) - { - setValveState( D85_VALV, VALVE_STATE_CLOSED ); - //setValveState( D64_VALV, VALVE_STATE_CLOSED); - - bicarbChamberFillRequested.data = FALSE; - // for this request override also cleared - bicarbChamberFillRequested.ovData = FALSE; + bicarbChamberFillRequested.data = FALSE; + // for this request override also cleared + bicarbChamberFillRequested.ovData = FALSE; - state = BICARB_CHAMBER_START_STATE; - } + dryBiCartPressureDecayStartTimeFlag = FALSE; + state = BICARB_CHAMBER_START_STATE; + return state; } @@ -1869,20 +1937,20 @@ data.dryBiCartDrainTimePeriod = dryBiCartDrainTimePeriod; // TODO: remove after feature testing - memcpy( &data.dryBiCartBicarbDosingControl, &bicarbControlSignals, sizeof( PI_CONTROLLER_SIGNALS_DATA ) ); + memcpy( &data.dryBiCartBicarbMixingControl, &bicarbControlSignals, sizeof( PI_CONTROLLER_SIGNALS_DATA ) ); // TODO: remove after feature testing - memcpy( &data.dryBiCartAcidDosingControl , &acidControlSignals , sizeof( PI_CONTROLLER_SIGNALS_DATA ) ); + memcpy( &data.dryBiCartAcidMixingControl , &acidControlSignals , sizeof( PI_CONTROLLER_SIGNALS_DATA ) ); data.dryBiCartAcidMixVolume = getAcidMixVol(); data.dryBiCartBicarbMixVolume = getBicarbMixVol(); // TODO: remove after feature testing - data.dryBiCartBicarbDosingKPgain = getBicarbKpGainCoefficient(); + data.dryBiCartBicarbMixingKPgain = getBicarbKpGainCoefficient(); // TODO: remove after feature testing - data.dryBiCartBicarbDosingKIgain = getBicarbKiGainCoefficient(); + data.dryBiCartBicarbMixingKIgain = getBicarbKiGainCoefficient(); - data.dryBiCartAcidDosingKPgain = getAcidKpGainCoefficient(); - data.dryBiCartAcidDosingKIgain = getAcidKiGainCoefficient(); + data.dryBiCartAcidMixingKPgain = getAcidKpGainCoefficient(); + data.dryBiCartAcidMixingKIgain = getAcidKiGainCoefficient(); broadcastData( MSG_ID_DD_DRY_BICART_DATA, COMM_BUFFER_OUT_CAN_DD_BROADCAST, (U08*)&data, sizeof( DRY_BICART_DATA_T ) ); @@ -1999,11 +2067,11 @@ /*********************************************************************//** * @brief * The testDryBiCartAcidMixVolumeOverride function sets the override value - * of the acid concentrate dosing volume. + * of the acid concentrate mixing volume. * @details Inputs: dryBiCartAcidMixVolume * @details Outputs: dryBiCartAcidMixVolume * @param message Override message from Dialin which includes the override - * value to override the acid concentrate dosing volume. + * value to override the acid concentrate mixing volume. * @return TRUE if override successful, FALSE if not *************************************************************************/ BOOL testDryBiCartAcidMixVolumeOverride( MESSAGE_T *message ) @@ -2016,11 +2084,11 @@ /*********************************************************************//** * @brief * The testDryBiCartBicarbMixVolumeOverride function sets the override value - * of the bicarb concentrate dosing volume. + * of the bicarb concentrate mixing volume. * @details Inputs: dryBiCartBicarbMixVolume * @details Outputs: dryBiCartBicarbMixVolume * @param message Override message from Dialin which includes the override - * value to override the bicarb concentrate dosing volume. + * value to override the bicarb concentrate mixing volume. * @return TRUE if override successful, FALSE if not *************************************************************************/ BOOL testDryBiCartBicarbMixVolumeOverride( MESSAGE_T *message ) @@ -2033,11 +2101,11 @@ /*********************************************************************//** * @brief * The testDryBiCartBicarbMixVolControlKpGainOverride function sets the override value - * of the Kp gain coefficient for closed loop bicarb dosing volume control + * of the Kp gain coefficient for closed loop bicarb mixing volume control * @details Inputs: dryBiCartBicarbMixVolumeKpGain * @details Outputs: dryBiCartBicarbMixVolumeKpGain * @param message Override message from Dialin which includes the override - * value to override the bicarb concentrate dosing volume kp gain. + * value to override the bicarb concentrate mixing volume kp gain. * @return TRUE if override successful, FALSE if not *************************************************************************/ BOOL testDryBiCartBicarbMixVolControlKpGainOverride( MESSAGE_T *message ) @@ -2054,11 +2122,11 @@ /*********************************************************************//** * @brief * The testDryBiCartBicarbMixVolControlKiGainOverride function sets the override value - * of the Ki gain coefficient for closed loop bicarb concentrate dosing volume control + * of the Ki gain coefficient for closed loop bicarb concentrate mixing volume control * @details Inputs: dryBiCartBicarbMixVolumeKiGain * @details Outputs: dryBiCartBicarbMixVolumeKiGain * @param message Override message from Dialin which includes the override - * value to override the bicarb concentrate dosing volume ki gain. + * value to override the bicarb concentrate mixing volume ki gain. * @return TRUE if override successful, FALSE if not *************************************************************************/ BOOL testDryBiCartBicarbMixVolControlKiGainOverride( MESSAGE_T *message ) @@ -2075,11 +2143,11 @@ /*********************************************************************//** * @brief * The testDryBiCartAcidMoxVolControlKpGainOverride function sets the override value - * of the Kp gain coefficient for closed loop acid concentrate dosing volume control + * of the Kp gain coefficient for closed loop acid concentrate mixing volume control * @details Inputs: dryBiCartAcidMixVolumeKpGain * @details Outputs: dryBiCartAcidMixVolumeKpGain * @param message Override message from Dialin which includes the override - * value to override the acid concentrate dosing volume kp gain. + * value to override the acid concentrate mixing volume kp gain. * @return TRUE if override successful, FALSE if not *************************************************************************/ BOOL testDryBiCartAcidMixVolControlKpGainOverride( MESSAGE_T *message ) @@ -2096,11 +2164,11 @@ /*********************************************************************//** * @brief * The testDryBiCartAcidMixVolControlKiGainOverride function sets the override value - * of the Ki gain coefficient for closed loop acid concentrate dosing volume control + * of the Ki gain coefficient for closed loop acid concentrate mixing volume control * @details Inputs: dryBiCartAcidMixVolumeKiGain * @details Outputs: dryBiCartAcidMixVolumeKiGain * @param message Override message from Dialin which includes the override - * value to override the bicarb concentrate dosing volume ki gain. + * value to override the bicarb concentrate mixing volume ki gain. * @return TRUE if override successful, FALSE if not *************************************************************************/ BOOL testDryBiCartAcidMixVolControlKiGainOverride( MESSAGE_T *message ) @@ -2217,4 +2285,21 @@ return result; } +/*********************************************************************//** + * @brief + * The testDryBiCartMixControlIntervalOverride function sets the override value + * of mix control interval + * @details Inputs: dryBiCartMixControlInterval + * @details Outputs: dryBiCartMixControlInterval + * @param message Override message from Dialin which includes the override + * value to override the bicart lower pressure. + * @return TRUE if override successful, FALSE if not + *************************************************************************/ +BOOL testDryBiCartMixControlIntervalOverride( MESSAGE_T *message ) +{ + BOOL result = u32Override( message, &dryBiCartMixControlInterval, 0, BICARB_MIX_CONTROL_INTERVAL ); + + return result; +} + /**@}*/