Index: firmware/App/Controllers/DryBiCart.c =================================================================== diff -u -rbd522c8ffdf75130571e5b6a79d1b1d6acd78b1c -r917d510b37f14e22cde8c28b223f8e4894aeda94 --- firmware/App/Controllers/DryBiCart.c (.../DryBiCart.c) (revision bd522c8ffdf75130571e5b6a79d1b1d6acd78b1c) +++ firmware/App/Controllers/DryBiCart.c (.../DryBiCart.c) (revision 917d510b37f14e22cde8c28b223f8e4894aeda94) @@ -46,18 +46,20 @@ #define DRY_BICART_DATA_PUBLISH_INTERVAL ( 250 / TASK_GENERAL_INTERVAL ) ///< Interval (ms/task time) at which the drybicart data published. #define WCDI2_PRESSURE_OFFSET_PSI 7.0F ///< The difference between the actual pressure measured at bicart assembly and the measured D66 pressure based on the placement of the sensor for WCID1 #define WCID1_PRESSURE_OFFSET_PSI 1.0F ///< The difference between the actual pressure measured at bicart assembly and the measured D66 pressure based on the placement of the sensor for WCID2 -#define DRY_BICART_PERSISTENCE_DURATION_MS 200 ///< Fill persistence duration to overcome the pressure overshoot/ drop for beta 1.9 and above. +#define DRY_BICART_PERSISTENCE_DURATION_MS 500 ///< Fill persistence duration to overcome the pressure overshoot/ drop for beta 1.9 and above. +//#define DRY_BICART_FILL_PERSISTENCE_DURATION_MS ( 1 * MS_PER_SECOND ) ///< Fill persistence duration to overcome the pressure overshoot/ drop for beta 1.9 and above. // Dry Bicart Fill #define DRY_BICART_FILL_COMPLETE_TIME_MS ( 1 * MS_PER_SECOND ) ///< Wait time to reset the request flag after fill complete #define DRY_BICART_WCID2_FILL_COMPLETE_PRESSURE_PSI ( 10.0F + WCDI2_PRESSURE_OFFSET_PSI ) ///< Maximum pressure reached to indicate the dry bicart fill being completed for WCID2 -#define DRY_BICART_WCID1_FILL_COMPLETE_PRESSURE_PSI ( 10.0F + WCID1_PRESSURE_OFFSET_PSI ) ///< Maximum pressure reached to indicate the dry bicart fill being completed for WCID1 +#define DRY_BICART_WCID1_FILL_COMPLETE_PRESSURE_PSI ( 10.0F + WCID1_PRESSURE_OFFSET_PSI ) ///< Maximum pressure reached to indicate the dry bicart fill being completed for WCID1. #define GET_FILL_COMPLETE_PRESSURE_PSI (getTestConfigStatus( TEST_CONFIG_DD_ENABLE_WCID_1 ) != TRUE ? \ DRY_BICART_WCID2_FILL_COMPLETE_PRESSURE_PSI : DRY_BICART_WCID1_FILL_COMPLETE_PRESSURE_PSI ) ///< Get fill complete pressure based on the WCID configuration #define DRY_BICART_FILL_INITIATE_PRESSURE_PSI 1.5F ///< Minimum pressure required to initiate the dry bicart fill process. -#define DRY_BICART_FILL_COMPLETE_SUPPLY_PRESSURE_PSI 10.0F ///< Maximum pressure allowed at bicart fill during supply process/state -#define DRY_BICART_FILL_INITIATE_SUPPLY_PRESSURE_PSI 3.0F ///< Minimum pressure required to initiate the dry bicart fill during supply process/state +//#define DRY_BICART_FILL_COMPLETE_SUPPLY_PRESSURE_PSI 10.0F ///< Maximum pressure allowed at bicart fill during supply process/state +#define DRY_BICART_FILL_COMPLETE_SUPPLY_PRESSURE_PSI 17.0F ///< Maximum pressure allowed at bicart fill during supply process/state +#define DRY_BICART_FILL_INITIATE_SUPPLY_PRESSURE_PSI 4.0F ///< Minimum pressure required to initiate the dry bicart fill during supply process/state #define DRY_BICART_MAX_FILL_CYCLE_CNT 10 ///< Max fill cycle allowed (by override) for dry bicart fill/mix with water. #define DRY_BICART_MINIMUM_FILL_CYCLE_CNT 3 ///< Minimum fill cycle count for filling dry bicart // Dry Bicart Fill Vent @@ -67,13 +69,15 @@ // Bicarb chamber fill/Supply #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 +#define DRY_BICART_SUPPLY_VALVE_D80_OPEN_TIME_MS ( 60 * 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 * 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 +#define DRY_BICART_SUPPLY_DECAY_COMPLETE_PRESSURE_PSI 4.0F ///< Minimum decay pressure needed to end the supply process. +#define DRY_BICART_SUPPLY_VENT_CYCLE_TIME_MS ( 15 * SEC_PER_MIN * MS_PER_SECOND ) ///< Vent cycle time to initiate D85 opening. // 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. @@ -141,6 +145,8 @@ static U32 dryBiCartPersistenceStartTime; ///< Dry bicart Persistence time. static U32 drybicartPersistenceOnLowercartPressureStartTime; ///< Dry bicart Persistence on lower cart pressure start time. static BOOL dryBiCartPressureDecayStartTimeFlag; ///< Dry bicart d66 pressure decay start timer. +static BOOL dryBiCartVentCycleWaitTimeStartedFlag; ///< Flag indicating venting cycle timer started for opening D85. +static U32 dryBiCartVentCycleStartTime; ///< Dry bicart Vent cycle start time. static DRY_BICART_OPERATION_T dryBicartStartRequest; ///< Dry bicart operation, fill or supply or drain request static DRY_BICART_OPERATION_T prevDryBicartState; ///< Dry BiCart State Change Tracker @@ -164,6 +170,8 @@ static BICARB_CHAMBER_FILL_EXEC_STATE_T handleBicarbChamberPressureCheckState( void ); static BICARB_CHAMBER_FILL_EXEC_STATE_T handleBicarbChamberSupplyVentStartState(void); static BICARB_CHAMBER_FILL_EXEC_STATE_T handleBicarbChamberSupplyVentEndState(void); +static BOOL isDryBicartChamberFillWindowOpen( void ); +static void closeD65IfBalChamberSwitchImminent( void ); // Drain static DRY_BICART_DRAIN_EXEC_STATE_T handleDryBicartDrainStartState( void ); static DRY_BICART_DRAIN_EXEC_STATE_T handleDryBicartFluidDrainState( void ); @@ -237,7 +245,9 @@ dryBiCartLowerCartPressure.override = OVERRIDE_RESET; dryBiCartPressureDecayStartTimeFlag = FALSE; + dryBiCartVentCycleWaitTimeStartedFlag = FALSE; dryBiCartFillVentTimeOut = FALSE; + dryBiCartVentCycleStartTime = 0; dryBiCartFillStartTime = 0; lastFillDurationInMS = 0; currentFillDurationInMS = 0; @@ -551,6 +561,46 @@ /*********************************************************************//** * @brief + * The isDryBicartChamberFillWindowOpen function checks whether D65 may be + * opened for dry bicarb refill: fresh-side BC valves closed and BC switch not + * within the 50 ms valve-close window. + * @details \b Inputs: getBalChamberFreshSideValvesClosedStatus, isBalChamberSwitchImminent + * @details \b Outputs: none + * @return TRUE when the BC fill is completed and allow D65 to fill Chamber F + *************************************************************************/ +static BOOL isDryBicartChamberFillWindowOpen( void ) +{ + BOOL result = FALSE; + + if ( ( TRUE == getBalChamberFreshSideValvesClosedStatus() ) && + ( FALSE == isBalChamberSwitchImminent() ) ) + { + result = TRUE; + } + + return result; +} + +/*********************************************************************//** + * @brief + * The closeD65IfBalChamberSwitchImminent function closes D65 when the balancing + * chamber is within 100 ms of switching. + * @details \b Inputs: isBalChamberSwitchImminent + * @details \b Outputs: valve states + * @return none + *************************************************************************/ +static void closeD65IfBalChamberSwitchImminent( void ) +{ + if ( TRUE == isBalChamberSwitchImminent() ) + { + setValveState( D65_VALV, VALVE_STATE_CLOSED ); + // Open D80 only in supply state + setValveState( D80_VALV, VALVE_STATE_OPEN ); + } +} + +/*********************************************************************//** + * @brief * The setBicartFillRequested function sets the bicart fill request * flag value to be True. * @details \b Inputs: bicarbChamberFillRequested, dryBiCartDrainRequested, @@ -838,16 +888,16 @@ F32 d66Pressure = getFilteredPressure( D66_PRES ); F32 fillCompletePressure = GET_FILL_COMPLETE_PRESSURE_PSI; - // Close dry bicart inlet water if D66 pressure is 17 PSI + // Close dry bicart inlet water if D66 pressure is equal to fill complete pressure if ( d66Pressure >= fillCompletePressure ) { - // start the persistence timer once d66 reaches 17 PSI + // start the persistence timer once d66 reaches fill complete pressure if ( 0 == dryBiCartPersistenceStartTime ) { dryBiCartPersistenceStartTime = getMSTimerCount(); } - // 200 ms persistence on D66 pressure since pressure overshoot just after D65 opening + // defined persistence on D66 pressure since pressure overshoot just after D65 opening if ( TRUE == didTimeout( dryBiCartPersistenceStartTime, DRY_BICART_PERSISTENCE_DURATION_MS ) ) { setValveState( D65_VALV, VALVE_STATE_CLOSED ); @@ -914,15 +964,15 @@ //Vent chamber F to atmosphere setValveState( D64_VALV, VALVE_STATE_OPEN ); - // D66 pressure drops to below 1.5 PSI + // D66 pressure drops to below fill vent complete pressure if ( ( d66Pressure <= DRY_BICART_FILL_VENT_COMPLETE_PRESSURE_PSI ) ) { - // start the persistence timer once d66 reaches 1.5 PSI + // start the persistence timer once d66 reaches fill vent complete pressure if ( 0 == dryBiCartPersistenceStartTime ) { dryBiCartPersistenceStartTime = getMSTimerCount(); } - // 200 ms persistence on D66 pressure since pressure drop below 1.5 PSI after opening D64 + // defined persistence on D66 pressure since pressure drop below fill vent complete pressure after opening D64 if ( TRUE == didTimeout( dryBiCartPersistenceStartTime, DRY_BICART_PERSISTENCE_DURATION_MS ) ) { setValveState( D85_VALV, VALVE_STATE_CLOSED ); @@ -1046,8 +1096,9 @@ * @brief * The handleBicarbChamberStartState function wait for bicarb chamber fill request * @details \b Inputs: bicarbChamberFillRequested - * @details \b Outputs: none - * @return the next drybicart fluid drain state. + * @details \b Outputs: dryBiCartVentCycleWaitTimeStartedFlag, dryBiCartPressureDecayStartTimeFlag, + * dryBiCartVentCycleStartTime. + * @return the next drybicart fluid supply state. *************************************************************************/ static BICARB_CHAMBER_FILL_EXEC_STATE_T handleBicarbChamberStartState( void ) { @@ -1057,7 +1108,13 @@ if ( TRUE == getU32OverrideValue( &bicarbChamberFillRequested ) ) { - state = BICARB_CARTRIDGE_FILL_WATER_START_STATE; + state = BICARB_CHAMBER_SUPPLY_STATE; + + if ( FALSE == dryBiCartVentCycleWaitTimeStartedFlag ) + { + dryBiCartVentCycleWaitTimeStartedFlag = TRUE; + dryBiCartVentCycleStartTime = getMSTimerCount(); + } } return state; @@ -1071,27 +1128,32 @@ *************************************************************************/ static BICARB_CHAMBER_FILL_EXEC_STATE_T handleBicarbChamberCartridgeFillWaterStartState( void ) { - BICARB_CHAMBER_FILL_EXEC_STATE_T state = BICARB_CARTRIDGE_FILL_WATER_END_STATE; + BICARB_CHAMBER_FILL_EXEC_STATE_T state = BICARB_CARTRIDGE_FILL_WATER_START_STATE; - // Close vent valves and descaling valve - setValveState( D80_VALV, VALVE_STATE_CLOSED ); - setValveState( D81_VALV, VALVE_STATE_CLOSED ); - setValveState( D85_VALV, VALVE_STATE_CLOSED ); + if ( TRUE == isDryBicartChamberFillWindowOpen() ) + { + // Close vent valves and descaling valve + setValveState( D80_VALV, VALVE_STATE_CLOSED ); + setValveState( D81_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 ); + // open inlet water to bicart only when fresh-side BC valves are closed + setValveState( D65_VALV, VALVE_STATE_OPEN ); + setValveState( D64_VALV, VALVE_STATE_OPEN ); - dryBiCarbSupplyStartTime = getMSTimerCount(); - dryBiCartPersistenceStartTime = 0; + dryBiCarbSupplyStartTime = getMSTimerCount(); + dryBiCartPersistenceStartTime = 0; + state = BICARB_CARTRIDGE_FILL_WATER_END_STATE; + } + return state; } /*********************************************************************//** * @brief - * The handleBicarbChamberCartridgeFillWaterStartState function stop water in the dry bicart - * @details \b Inputs: D66 pressure, dryBiCartPersistenceStartTime + * The handleBicarbChamberCartridgeFillWaterStartState function stop water in the fill water end state + * @details \b Inputs: dryBiCartPersistenceStartTime * @details \b Outputs: valve states * @return the next bicarb chamber check level state. *************************************************************************/ @@ -1100,8 +1162,18 @@ BICARB_CHAMBER_FILL_EXEC_STATE_T state = BICARB_CARTRIDGE_FILL_WATER_END_STATE; F32 d66Pressure = getFilteredPressure( D66_PRES ); F32 fillCompletePressure = GET_FILL_COMPLETE_PRESSURE_PSI; + LVL_STATE_T bicarbChamberLevel = getBicarbChamberLevelStatus(); - // check D66 pressure greater than or equal to 17 PSI + if ( FALSE == isDryBicartChamberFillWindowOpen() ) + { + setValveState( D65_VALV, VALVE_STATE_CLOSED ); + } + else if ( TRUE == isDryBicartChamberFillWindowOpen() ) + { + setValveState( D65_VALV, VALVE_STATE_OPEN ); + } + + // check D66 pressure greater than or equal to Fill complete pressure if ( d66Pressure >= fillCompletePressure ) { // start the persistence timer once d66 reaches 17 PSI @@ -1110,21 +1182,30 @@ dryBiCartPersistenceStartTime = getMSTimerCount(); } - // 200 ms persistence on D66 pressure since pressure overshoot just after D65 opening + // Defined persistence on D66 pressure since pressure overshoot just after D65 opening only for chamber fill if ( TRUE == didTimeout( dryBiCartPersistenceStartTime, DRY_BICART_PERSISTENCE_DURATION_MS ) ) { // Close water inlet valve as D66 pressure reaches 11 PSI after persistence setValveState( D65_VALV, VALVE_STATE_CLOSED ); dryBiCartPersistenceStartTime = 0; - state = BICARB_CHAMBER_SUPPLY_STATE; + //state = BICARB_CHAMBER_SUPPLY_STATE; + state = BICARB_SUPPLY_VENT_END_STATE; + } } else { dryBiCartPersistenceStartTime = 0; } + //Additional code + if ( LVL_STATE_LOW == bicarbChamberLevel ) + { + //Force transition to end state to allow next supply + state = BICARB_SUPPLY_VENT_END_STATE; + } + return state; } @@ -1140,7 +1221,8 @@ BICARB_CHAMBER_FILL_EXEC_STATE_T state = BICARB_CHAMBER_PRESSURE_CHECK_STATE; // TODO: set supply in progress to inform BC control to disable alarm - setValveState( D64_VALV, VALVE_STATE_CLOSED ); + setValveState( D64_VALV, VALVE_STATE_OPEN ); + // Open the Bicarb chamber inlet valve setValveState( D80_VALV, VALVE_STATE_OPEN ); @@ -1156,10 +1238,9 @@ * @brief * The handleBicarbChamberPressureCheckStartState function actuates the vent valve * present in the Bicart assembly. - * @details \b Inputs: D66 Pressure, D63 level, dryBiCarbSupplyStartTime, - * dryBiCarbSypplyVentStartTime, dryBiCartPersistenceStartTime, bicarbChamberLevel, - * dryBiCartPressureDecayStartTimeFlag, drybicartPersistenceOnLowercartPressureStartTime - * @details \b Outputs: dryBiCarbSypplyVentStartTime + * @details \b Inputs: dryBiCarbSupplyStartTime, dryBiCarbSypplyVentStartTime, dryBiCartPersistenceStartTime, + * bicarbChamberLevel, dryBiCartPressureDecayStartTimeFlag, drybicartPersistenceOnLowercartPressureStartTime + * @details \b Outputs: dryBiCarbSypplyVentStartTime, valve states * @return the next bicarb chamber Supply Vent Start state. *************************************************************************/ static BICARB_CHAMBER_FILL_EXEC_STATE_T handleBicarbChamberPressureCheckState( void ) @@ -1168,32 +1249,46 @@ F32 d66Pressure = getFilteredPressure( D66_PRES ); LVL_STATE_T bicarbChamberLevel = getBicarbChamberLevelStatus(); + // Close D65 irrespective of pressure for balancing chamber fresh side fill to complete. + closeD65IfBalChamberSwitchImminent(); + // Once upper level reached high , close the valve, timeout is for safety in case level sensor didn't work(10 sec), or else its a time based filling (3 sec) if ( ( LVL_STATE_HIGH == bicarbChamberLevel ) || ( TRUE == didTimeout( dryBiCarbSupplyStartTime, DRY_BICART_SUPPLY_VALVE_D80_OPEN_TIME_MS ) ) ) { - setValveState( D65_VALV, VALVE_STATE_CLOSED ); - - // start the timer for d66 pressure decay - if( FALSE == dryBiCartPressureDecayStartTimeFlag ) + if ( TRUE == didTimeout( dryBiCartVentCycleStartTime, DRY_BICART_SUPPLY_VENT_CYCLE_TIME_MS ) ) { - 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() ) + // start the timer for d66 pressure decay + if ( FALSE == dryBiCartPressureDecayStartTimeFlag ) { - setValveState( D80_VALV, VALVE_STATE_CLOSED ); - setValveState( D85_VALV, VALVE_STATE_OPEN ); - dryBiCarbSupplyStartTime = getMSTimerCount(); - dryBiCarbSypplyVentStartTime = getMSTimerCount(); + dryBiCartPressureDecayStartTimeFlag = TRUE; + } + // do not close the D80 valve, wait till d66 decays to supply decay complete pressure + if ( TRUE == didTimeout( dryBiCarbSupplyStartTime, DRY_BICART_SUPPLY_COMPLETE_TIME_MS ) ) + { + if ( d66Pressure <= DRY_BICART_SUPPLY_DECAY_COMPLETE_PRESSURE_PSI ) + { + setValveState( D80_VALV, VALVE_STATE_CLOSED ); + setValveState( D64_VALV, VALVE_STATE_CLOSED ); + setValveState( D85_VALV, VALVE_STATE_OPEN ); - state = BICARB_SUPPLY_VENT_START_STATE; + dryBiCarbSupplyStartTime = getMSTimerCount(); + dryBiCarbSypplyVentStartTime = getMSTimerCount(); + + state = BICARB_SUPPLY_VENT_START_STATE; + } } } + else + { + setValveState( D65_VALV, VALVE_STATE_CLOSED ); + setValveState( D80_VALV, VALVE_STATE_CLOSED ); + dryBiCarbSupplyStartTime = getMSTimerCount(); + + state = BICARB_CARTRIDGE_FILL_WATER_START_STATE; + + } } else if ( d66Pressure <= getDryBicartLowerCartPressure() ) { @@ -1202,10 +1297,13 @@ { drybicartPersistenceOnLowercartPressureStartTime = getMSTimerCount(); } - // 200 ms persistence on D66 pressure - if ( TRUE == didTimeout( drybicartPersistenceOnLowercartPressureStartTime, DRY_BICART_PERSISTENCE_DURATION_MS ) ) + + // defined persistence on D66 pressure + if ( ( TRUE == didTimeout( drybicartPersistenceOnLowercartPressureStartTime, DRY_BICART_PERSISTENCE_DURATION_MS ) ) && + ( TRUE == isDryBicartChamberFillWindowOpen() ) ) { setValveState( D65_VALV, VALVE_STATE_OPEN ); + setValveState( D80_VALV, VALVE_STATE_CLOSED ); drybicartPersistenceOnLowercartPressureStartTime = 0; } } @@ -1218,10 +1316,11 @@ dryBiCartPersistenceStartTime = getMSTimerCount(); } - // 200 ms persistence on D66 pressure since pressure overshoot just after D65 opening + // defined persistence on D66 pressure since pressure overshoot just after D65 opening if ( TRUE == didTimeout( dryBiCartPersistenceStartTime, DRY_BICART_PERSISTENCE_DURATION_MS ) ) { setValveState( D65_VALV, VALVE_STATE_CLOSED ); + setValveState( D80_VALV, VALVE_STATE_OPEN ); dryBiCartPersistenceStartTime = 0; } } @@ -1239,7 +1338,7 @@ * The handleBicarbChamberSupplyVentStartState function actuates the vent valve * present in the Bicart assembly. * @details \b Inputs: dryBiCarbSypplyVentStartTime, dryBiCartPersistenceStartTime - * @details \b Outputs: dryBiCarbSypplyVentStartTime + * @details \b Outputs: dryBiCarbSypplyVentStartTime, valve states * @return the next bicarb chamber Supply Vent End state. *************************************************************************/ static BICARB_CHAMBER_FILL_EXEC_STATE_T handleBicarbChamberSupplyVentStartState(void) @@ -1252,20 +1351,20 @@ //Vent chamber F to atmosphere setValveState( D64_VALV, VALVE_STATE_OPEN ); - // D66 pressure drops to below 1.5 PSI or time out + // D66 pressure drops to below fill vent complete pressure or time out if ( ( d66Pressure <= DRY_BICART_FILL_VENT_COMPLETE_PRESSURE_PSI ) ) { - // start the persistence timer once d66 reaches if it drops below 1.5 + // start the persistence timer once d66 reaches if it drops below fill vent complete pressure if ( 0 == dryBiCartPersistenceStartTime ) { dryBiCartPersistenceStartTime = getMSTimerCount(); } - // 200 ms persistence on D66 pressure since pressure overshoot just after D65 opening + // defined persistence on D66 pressure since pressure overshoot just after D65 opening if ( TRUE == didTimeout( dryBiCartPersistenceStartTime, DRY_BICART_PERSISTENCE_DURATION_MS ) ) { setValveState( D85_VALV, VALVE_STATE_CLOSED ); dryBiCartPersistenceStartTime = 0; - + dryBiCartVentCycleWaitTimeStartedFlag = FALSE; state = BICARB_SUPPLY_VENT_END_STATE; } } @@ -1274,6 +1373,7 @@ setValveState( D85_VALV, VALVE_STATE_CLOSED ); dryBiCartPersistenceStartTime = 0; dryBiCartFillVentTimeOut = TRUE; + dryBiCartVentCycleWaitTimeStartedFlag = FALSE; state = BICARB_SUPPLY_VENT_END_STATE; } @@ -1619,7 +1719,7 @@ * @details \b Outputs: dryBiCartDataPublishInterval * @param Override message from Dialin which includes the interval * (in ms) to override the DD dry bicart data publish interval to. - * @return TRUE if override successful, FALSE if not + * @return TRUE if override successful, FALSE if not. *************************************************************************/ BOOL testDryBiCartDataPublishIntervalOverride( MESSAGE_T *message ) { Index: firmware/App/Controllers/MixingControl.c =================================================================== diff -u -rbd522c8ffdf75130571e5b6a79d1b1d6acd78b1c -r917d510b37f14e22cde8c28b223f8e4894aeda94 --- firmware/App/Controllers/MixingControl.c (.../MixingControl.c) (revision bd522c8ffdf75130571e5b6a79d1b1d6acd78b1c) +++ firmware/App/Controllers/MixingControl.c (.../MixingControl.c) (revision 917d510b37f14e22cde8c28b223f8e4894aeda94) @@ -46,8 +46,8 @@ #define MIXING_CONTROL_DATA_PUBLISH_INTERVAL ( 250 / TASK_GENERAL_INTERVAL ) ///< Interval (ms/task time) at which the mixing control data published. // drybicarb mixing -#define BICARB_VOL_CONTROL_P_COEFFICIENT ( 0.00008484F * 2 ) ///< Bicarb proportional gain (kp) -#define BICARB_VOL_CONTROL_I_COEFFICIENT ( 0.00033936F / 4 ) ///< Bicarb integral gain. (ki) +#define BICARB_VOL_CONTROL_P_COEFFICIENT ( 0.00008484F ) ///< Bicarb proportional gain (kp) +#define BICARB_VOL_CONTROL_I_COEFFICIENT ( 0.00033936F / 8 ) ///< Bicarb integral gain. (ki) #define MIN_BICARB_VOLUME_ML 0.4F ///< Minimum bicarb volume in mL #define MAX_BICARB_VOLUME_ML 1.8F ///< Maximum bicarb volume in mL @@ -69,11 +69,11 @@ #define MIX_NO_FEED_FORWARD 0.0F ///< Feed forward term for dialysate closed loop control -#define BICARB_MIX_CONTROL_INTERVAL ( 9 * MS_PER_SECOND / TASK_GENERAL_INTERVAL ) ///< Interval (ms/task time) at which the bicarb mix is controlled. -#define ACID_MIX_CONTROL_INTERVAL ( 15 * MS_PER_SECOND / TASK_GENERAL_INTERVAL ) ///< Interval (ms/task time) at which the dialysate mix is controlled. +#define BICARB_MIX_CONTROL_INTERVAL_MULTIPLIER ( 3 * MS_PER_SECOND / TASK_GENERAL_INTERVAL ) ///< Interval (ms/task time) at which the bicarb mix is controlled. +#define ACID_MIX_CONTROL_INTERVAL_MULTIPLIER ( 5 * MS_PER_SECOND / TASK_GENERAL_INTERVAL ) ///< Interval (ms/task time) at which the dialysate mix is controlled. -#define BICARB_DEADBAND_CONTROL 15.0F ///< Bicarb dead band control -#define ACID_DEADBAND_CONTROL 50.0F ///< Acid dead band control +#define BICARB_DEADBAND_CONTROL 30.0F ///< Bicarb dead band control +#define ACID_DEADBAND_CONTROL 70.0F ///< Acid dead band control // Proportioning Ratios: 1 Part Acid : 1.72 Parts Bicarb : 42.28 Parts Water // Total parts = 1 + 1.72 + 42.28 = 45.0 @@ -201,6 +201,7 @@ static void setBicarbMixVol( F32 targetValue ); static void setAcidMixVol( F32 targetValue ); +static void updatedCMixingControlInterval( void ); static F32 getBicarbDeltaConductivity( void ); static F32 getBicarbTargetConductivity( void ); @@ -312,13 +313,13 @@ mixingControlTargetAdjBicarbSettings.ovInitData = 0.0F; mixingControlTargetAdjBicarbSettings.override = OVERRIDE_RESET; - mixingControlBicarbControlInterval.data = BICARB_MIX_CONTROL_INTERVAL; - mixingControlBicarbControlInterval.ovData = BICARB_MIX_CONTROL_INTERVAL; + mixingControlBicarbControlInterval.data = BICARB_MIX_CONTROL_INTERVAL_MULTIPLIER; + mixingControlBicarbControlInterval.ovData = BICARB_MIX_CONTROL_INTERVAL_MULTIPLIER; mixingControlBicarbControlInterval.ovInitData = 0; mixingControlBicarbControlInterval.override = OVERRIDE_RESET; - mixingControlAcidControlInterval.data = ACID_MIX_CONTROL_INTERVAL; - mixingControlAcidControlInterval.ovData = ACID_MIX_CONTROL_INTERVAL; + mixingControlAcidControlInterval.data = ACID_MIX_CONTROL_INTERVAL_MULTIPLIER; + mixingControlAcidControlInterval.ovData = ACID_MIX_CONTROL_INTERVAL_MULTIPLIER; mixingControlAcidControlInterval.ovInitData = 0; mixingControlAcidControlInterval.override = OVERRIDE_RESET; @@ -361,6 +362,8 @@ { if ( getCurrentBalancingChamberExecState() > BAL_CHAMBER_STATE_IDLE ) { + updatedCMixingControlInterval(); + // closed loop bicarb and acid mixing controller handleDialysateCompositionMixing(); } @@ -427,6 +430,36 @@ /*********************************************************************//** * @brief + * The updatedCMixingControlInterval function sets both acid and bicarb + * Mix volume provided by the controller + * @details \b Inputs: none + * @details \b Outputs: mixingControlBicarbMixVolume + * @param targetValue bicarb Mix volume + * @return TRUE if successful, FALSE if not. + *************************************************************************/ +static void updatedCMixingControlInterval( void ) +{ + F32 tdDialysateFlowRate = 0.0F; + F32 balChamberSwitchingFreq = 0.0F; + U32 balChamberSwitchingPeriod = 0; + + tdDialysateFlowRate = getTDDialysateFlowrate(); + + balChamberSwitchingFreq = tdDialysateFlowRate / 30.0; + balChamberSwitchingPeriod = ( SEC_PER_MIN ) / (U32)balChamberSwitchingFreq; + + // For acid control period, we are using 3 cycles of balancing chamber switching period (for ex: At Qd = 600, switching period = 3sec, so acid control interval = 3*3 = 9sec + // For bicarb control period, we are using 5 cycles of balancing chamber switching period (for ex: At Qd = 600, switching period = 3sec, so bicarb control interval = 3*5 = 15sec + + if ( balChamberSwitchingPeriod > 0) + { + mixingControlAcidControlInterval.data = ACID_MIX_CONTROL_INTERVAL_MULTIPLIER * balChamberSwitchingPeriod; + mixingControlBicarbControlInterval.data = BICARB_MIX_CONTROL_INTERVAL_MULTIPLIER * balChamberSwitchingPeriod; + } +} + +/*********************************************************************//** + * @brief * The getBicarbDeltaConductivity function gets the delta target conductivity * @details \b Inputs: mixingControlBicarbDeltaConductivity * @details \b Outputs: none @@ -1114,7 +1147,7 @@ *************************************************************************/ BOOL testMixingControlBicarbControlIntervalOverride( MESSAGE_T *message ) { - BOOL result = u32Override( message, &mixingControlBicarbControlInterval, 0, BICARB_MIX_CONTROL_INTERVAL ); + BOOL result = u32Override( message, &mixingControlBicarbControlInterval, 0, BICARB_MIX_CONTROL_INTERVAL_MULTIPLIER ); return result; } @@ -1131,7 +1164,7 @@ *************************************************************************/ BOOL testMixingControlAcidControlIntervalOverride( MESSAGE_T *message ) { - BOOL result = u32Override( message, &mixingControlAcidControlInterval, 0, BICARB_MIX_CONTROL_INTERVAL ); + BOOL result = u32Override( message, &mixingControlAcidControlInterval, 0, ACID_MIX_CONTROL_INTERVAL_MULTIPLIER ); return result; } Index: firmware/App/Controllers/MixingControl.h =================================================================== diff -u -r313fa2d93236d6aa9de1a7e8e65c8c908e6b0c59 -r917d510b37f14e22cde8c28b223f8e4894aeda94 --- firmware/App/Controllers/MixingControl.h (.../MixingControl.h) (revision 313fa2d93236d6aa9de1a7e8e65c8c908e6b0c59) +++ firmware/App/Controllers/MixingControl.h (.../MixingControl.h) (revision 917d510b37f14e22cde8c28b223f8e4894aeda94) @@ -8,7 +8,7 @@ * @file MixingControl.h * * @author (last) Sameer Kalliadan Poyil -* @date (last) 16-Jun-2026 +* @date (last) 17-Jul-2026 * * @author (original) Sameer Kalliadan Poyil * @date (original) 15-Jun-2026 @@ -48,6 +48,10 @@ F32 lastBicarbMixVolume; ///< Mixing control last bicarb mix volume F32 currentAcidMixVolume; ///< Mixing control current acid mix volume F32 lastAcidMixVolume; ///< Mixing control last acid mix volume + F32 bicarbConductivityPreMix; ///< Bicarb conductivity pre mix + F32 bicarbConductivityPostMix; ///< Bicarb conductivity post mix + F32 acidConductivityPostMix; ///< Acid conductivity post mix + F32 totalConductivity; ///< Total Conductivity(Acid+Bicab)or Dialysate conductivity // TODO: remove after closed loops stabilized PI_CONTROLLER_SIGNALS_DATA bicarbData; ///< Mixing control bicarb mixing closed loop control signals data PI_CONTROLLER_SIGNALS_DATA acidData; ///< Mixing control acid mixing closed loop control signals data Index: firmware/App/Monitors/Conductivity.c =================================================================== diff -u -rd47b9bcbd4796a8c51d9e87436422c5868292ac6 -r917d510b37f14e22cde8c28b223f8e4894aeda94 --- firmware/App/Monitors/Conductivity.c (.../Conductivity.c) (revision d47b9bcbd4796a8c51d9e87436422c5868292ac6) +++ firmware/App/Monitors/Conductivity.c (.../Conductivity.c) (revision 917d510b37f14e22cde8c28b223f8e4894aeda94) @@ -17,12 +17,14 @@ #include // Used for calculating the polynomial calibration equation. #include // For memcpy +#include "BalancingChamber.h" #include "Conductivity.h" #include "MessageSupport.h" #include "Messaging.h" #include "ModeGenPermeate.h" #include "OperationModes.h" #include "TaskPriority.h" +#include "TDInterface.h" #include "Utilities.h" /** @@ -38,9 +40,9 @@ #define FP_CONDUCTIVITY_DATA_PUBLISH_COUNTER_START_COUNT 41 ///< FP Conductivity data publish counter start count. #define RO_DATA_PUBLISH_COUNTER_START_COUNT 42 ///< FP RO Data publish counter start count. #define RESISTANCE_DATA_PUBLISH_COUNTER_START_COUNT 43 ///< DD Resistance data publish counter start count. -#define CONDUCTIVITY_SAMPLE_FILTER_MS ( 210 ) ///< Filter conductivity data for given time. Currently set to have 5 samples over 3.5s ( 700ms sample rate ) +#define CONDUCTIVITY_MAX_FILTER_SIZE_MULTIPLIER ( 252 ) ///< Maximum conductivity filter sample count (At 50qd, we switch once for every 36sec, so 36 * FILTER_SIZE_MULTIPLIER = 252). #define CONDUCTIVITY_TEMP_SAMPLE_FILTER_MS ( 30 ) ///< Filter conductivity temperature data for given time. Currently set to have 5 samples over 3.5s ( 700ms sample rate ) -#define SIZE_OF_COND_ROLLING_AVG ( CONDUCTIVITY_SAMPLE_FILTER_MS / TASK_PRIORITY_INTERVAL ) ///< Filtered conductivity moving average sample count. +#define FILTER_SIZE_MULTIPLIER ( 7 ) ///< Conductivity filter size multiplier. #define SIZE_OF_COND_TEMP_ROLLING_AVG ( CONDUCTIVITY_TEMP_SAMPLE_FILTER_MS / TASK_PRIORITY_INTERVAL ) ///< Filtered conductivity temprature moving average sample count. #define RO_RR_MOVING_AVG_NUM_OF_SAMPLES 30 ///< RO rejection ratio moving average number of samples. #define FRACTION_TO_PERCENT_CONVERSION_FACTOR 100.0F ///< RO rejection ratio factor to percentage conversion factor value @@ -49,7 +51,7 @@ /// Filter conductivity readings record. typedef struct { - F32 conductivityReadings[ SIZE_OF_COND_ROLLING_AVG ]; ///< Holds conductivity sample rolling average. + F32 conductivityReadings[ CONDUCTIVITY_MAX_FILTER_SIZE_MULTIPLIER ]; ///< Holds conductivity sample rolling average. U32 conductivityReadingsIdx; ///< Index for next sample in rolling average array. F32 conductivityReadingsTotal; ///< Rolling total - used to calc average. U32 conductivityReadingsCount; ///< Number of samples in rolling average buffer @@ -89,6 +91,7 @@ static U32 roRRCount; ///< RO rejection ratio Number of samples in average buffer. static F32 roRRTankFillAvg; ///< Average RO rejection ratio during permeate tank fill state. static U32 roRRSampleIntervalCounter; ///< RO rejection ratio sample collection timer counter. +static U32 conductivityFilterSize; ///< Active conductivity filter sample count. // ********** private function prototypes ********** @@ -98,6 +101,9 @@ static void filterConductivitySensorTemperatureReadings( void ); static void calcRORejectionRatio( void ); static void filterRORejectionRatioReadings( void ); +static void broadcastResistanceData( void ); +static U32 getConductivityFilterSize( void ); +static void resetConductivityFilterReadings( void ); /*********************************************************************//** * @brief @@ -127,6 +133,7 @@ roRRAvg.ovInitData = 0.0F; roRRAvg.override = OVERRIDE_RESET; roRRSampleIntervalCounter = 0; + conductivityFilterSize = FILTER_SIZE_MULTIPLIER; memset( &roRRSamples, 0, sizeof( roRRSamples ) ); @@ -289,9 +296,16 @@ { CONDUCTIVITY_SENSORS_T sensor; F32 calculatedConductivity = 0.0F; + U32 activeFilterSize = getConductivityFilterSize(); F32 uncompenstatedConductivity = 0.0F; BOOL freshData = FALSE; + if ( conductivityFilterSize != activeFilterSize ) + { + conductivityFilterSize = activeFilterSize; + resetConductivityFilterReadings(); + } + for ( sensor = FIRST_DD_COND_SENSOR; sensor < NUM_OF_CONDUCTIVITY_SENSORS; sensor++ ) { if ( getTestConfigStatus( TEST_CONFIG_DD_FP_ENABLE_BETA_1_9_HW ) == TRUE ) @@ -324,24 +338,24 @@ { freshData = FALSE; // TODO - calibrate - if ( filteredConductivityReadings[ sensor ].conductivityReadingsCount >= SIZE_OF_COND_ROLLING_AVG ) + if ( filteredConductivityReadings[ sensor ].conductivityReadingsCount >= conductivityFilterSize ) { filteredConductivityReadings[ sensor ].conductivityReadingsTotal -= filteredConductivityReadings[ sensor ].conductivityReadings[ filteredConductivityReadings[ sensor ].conductivityReadingsIdx ]; } filteredConductivityReadings[ sensor ].conductivityReadings[ filteredConductivityReadings[ sensor ].conductivityReadingsIdx ] = calculatedConductivity; filteredConductivityReadings[ sensor ].conductivityReadingsTotal += calculatedConductivity; - filteredConductivityReadings[ sensor ].conductivityReadingsIdx = INC_WRAP( filteredConductivityReadings[ sensor ].conductivityReadingsIdx, 0, SIZE_OF_COND_ROLLING_AVG - 1 ); - filteredConductivityReadings[ sensor ].conductivityReadingsCount = INC_CAP( filteredConductivityReadings[ sensor ].conductivityReadingsCount, SIZE_OF_COND_ROLLING_AVG ); + filteredConductivityReadings[ sensor ].conductivityReadingsIdx = INC_WRAP( filteredConductivityReadings[ sensor ].conductivityReadingsIdx, 0, conductivityFilterSize - 1 ); + filteredConductivityReadings[ sensor ].conductivityReadingsCount = INC_CAP( filteredConductivityReadings[ sensor ].conductivityReadingsCount, conductivityFilterSize ); filteredcurrentConductivityReadings[ sensor ].data = filteredConductivityReadings[ sensor ].conductivityReadingsTotal / (F32)filteredConductivityReadings[ sensor ].conductivityReadingsCount; - if ( filteredUConductivityReadings[ sensor ].conductivityReadingsCount >= SIZE_OF_COND_ROLLING_AVG ) + if ( filteredUConductivityReadings[ sensor ].conductivityReadingsCount >= conductivityFilterSize ) { filteredUConductivityReadings[ sensor ].conductivityReadingsTotal -= filteredUConductivityReadings[ sensor ].conductivityReadings[ filteredUConductivityReadings[ sensor ].conductivityReadingsIdx ]; } filteredUConductivityReadings[ sensor ].conductivityReadings[ filteredUConductivityReadings[ sensor ].conductivityReadingsIdx ] = uncompenstatedConductivity; filteredUConductivityReadings[ sensor ].conductivityReadingsTotal += uncompenstatedConductivity; - filteredUConductivityReadings[ sensor ].conductivityReadingsIdx = INC_WRAP( filteredUConductivityReadings[ sensor ].conductivityReadingsIdx, 0, SIZE_OF_COND_ROLLING_AVG - 1 ); - filteredUConductivityReadings[ sensor ].conductivityReadingsCount = INC_CAP( filteredUConductivityReadings[ sensor ].conductivityReadingsCount, SIZE_OF_COND_ROLLING_AVG ); + filteredUConductivityReadings[ sensor ].conductivityReadingsIdx = INC_WRAP( filteredUConductivityReadings[ sensor ].conductivityReadingsIdx, 0, conductivityFilterSize - 1 ); + filteredUConductivityReadings[ sensor ].conductivityReadingsCount = INC_CAP( filteredUConductivityReadings[ sensor ].conductivityReadingsCount, conductivityFilterSize ); filteredcurrentUConductivityReadings[ sensor ].data = filteredUConductivityReadings[ sensor ].conductivityReadingsTotal / (F32)filteredUConductivityReadings[ sensor ].conductivityReadingsCount; } @@ -350,6 +364,75 @@ /*********************************************************************//** * @brief + * The getConductivityFilterSize function gets the active conductivity filter + * sample count based on the Qd balancing chamber switching period. + * @details \b Inputs: TD dialysate flow rate + * @details \b Outputs: none + * @return active conductivity filter sample count. + *************************************************************************/ +static U32 getConductivityFilterSize( void ) +{ + F32 tdDialysateFlowRate = getTDDialysateFlowrate(); + U32 result = FILTER_SIZE_MULTIPLIER; + + if ( tdDialysateFlowRate > NEARLY_ZERO ) + { + F32 balChamberSwitchingFreq = tdDialysateFlowRate / BAL_CHAMBER_FILL_VOLUME_ML; + F32 balChamberSwitchingPeriod = (F32)SEC_PER_MIN / balChamberSwitchingFreq; + + result = (U32)( (F32)FILTER_SIZE_MULTIPLIER * balChamberSwitchingPeriod ); + } + + return result; +} + +/*********************************************************************//** + * @brief + * The resetConductivityFilterReadings function clears conductivity rolling + * average data when the active filter window changes. + * @details \b Inputs: none + * @details \b Outputs: filteredConductivityReadings + * @return none + *************************************************************************/ +static void resetConductivityFilterReadings( void ) +{ + CONDUCTIVITY_SENSORS_T sensor; + + for ( sensor = FIRST_DD_COND_SENSOR; sensor < NUM_OF_CONDUCTIVITY_SENSORS; sensor++ ) + { + U32 readingIndex; + + F32 seedConductivity = filteredcurrentConductivityReadings[ sensor ].data; + BOOL hasPreviousSamples = ( filteredConductivityReadings[ sensor ].conductivityReadingsCount > 0 ); + + for ( readingIndex = 0; readingIndex < CONDUCTIVITY_MAX_FILTER_SIZE_MULTIPLIER; readingIndex++ ) + { + if ( ( TRUE == hasPreviousSamples ) && ( readingIndex < conductivityFilterSize ) ) + { + filteredConductivityReadings[ sensor ].conductivityReadings[ readingIndex ] = seedConductivity; + } + else + { + filteredConductivityReadings[ sensor ].conductivityReadings[ readingIndex ] = 0.0F; + } + } + + filteredConductivityReadings[ sensor ].conductivityReadingsIdx = 0; + if ( TRUE == hasPreviousSamples ) + { + filteredConductivityReadings[ sensor ].conductivityReadingsTotal = seedConductivity * (F32)conductivityFilterSize; + filteredConductivityReadings[ sensor ].conductivityReadingsCount = conductivityFilterSize; + } + else + { + filteredConductivityReadings[ sensor ].conductivityReadingsTotal = 0.0F; + filteredConductivityReadings[ sensor ].conductivityReadingsCount = 0; + } + } +} + +/*********************************************************************//** + * @brief * The getFilteredConductivitySensorTemperature function gets the filtered * temperature (in C) for a given conductivity sensor. * @details \b Alarm: ALARM_ID_DD_SOFTWARE_FAULT if given sensor is invalid.