Index: firmware/App/Controllers/BalancingChamber.c =================================================================== diff -u -r0bcac6885c8461b05da276fd245b580b7339ddfd -rcd1161514dbaff9e5b222931fff99618e39fd7ec --- firmware/App/Controllers/BalancingChamber.c (.../BalancingChamber.c) (revision 0bcac6885c8461b05da276fd245b580b7339ddfd) +++ firmware/App/Controllers/BalancingChamber.c (.../BalancingChamber.c) (revision cd1161514dbaff9e5b222931fff99618e39fd7ec) @@ -23,6 +23,7 @@ #include "FpgaDD.h" #include "Heaters.h" #include "Level.h" +#include "MixingControl.h" #include "ModeGenDialysate.h" #include "ModeStandby.h" #include "Messaging.h" Index: firmware/App/Controllers/DryBiCart.c =================================================================== diff -u -rfc26356f5aae3e51f6267e41da0d74e76a9d5b6d -rcd1161514dbaff9e5b222931fff99618e39fd7ec --- firmware/App/Controllers/DryBiCart.c (.../DryBiCart.c) (revision fc26356f5aae3e51f6267e41da0d74e76a9d5b6d) +++ firmware/App/Controllers/DryBiCart.c (.../DryBiCart.c) (revision cd1161514dbaff9e5b222931fff99618e39fd7ec) @@ -24,6 +24,7 @@ #include "DryBiCart.h" #include "Level.h" #include "Messaging.h" +#include "MixingControl.h" #include "ModeGenDialysate.h" #include "OperationModes.h" #include "PIControllers.h" @@ -151,7 +152,7 @@ static BICARB_CHAMBER_FILL_EXEC_STATE_T handleBicarbChamberStartState( void ); static BICARB_CHAMBER_FILL_EXEC_STATE_T handleBicarbChamberCartridgeFillWaterStartState( void ); static BICARB_CHAMBER_FILL_EXEC_STATE_T handleBicarbChamberCartridgeFillWaterEndState( void ); -static BICARB_CHAMBER_FILL_EXEC_STATE_T handleBicarbChambeSupplyStart( void ); +static BICARB_CHAMBER_FILL_EXEC_STATE_T handleBicarbChamberSupplyStart( void ); 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); @@ -163,7 +164,6 @@ static F32 getDryBicartLowerCartPressure( void ); static F32 getDryBicartUpperCartPressure( void ); -static U32 getDryBicartMixControlInterval( void ); // publish the status static void publishDryBicartData( void ); @@ -260,19 +260,20 @@ * bicarbonate chamber fill and bicarbonate cartridge drain related state machines one at time * @details \b Inputs: dryBicartStartRequest * @details \b Outputs: none + * @details \b Alarm: ALARM_ID_DD_SOFTWARE_FAULT when wrong dry bicart state machine is + * invoked. * @return none. *************************************************************************/ void execDryBicart( void ) { - //( TRUE == getBicarbChamberFillRequested() ) - //supply dryBicartStartRequest = DRY_BICART_SUPPLY ; - //( TRUE == getBicartFillRequested() ) - //fill dryBicartStartRequest = DRY_BICART_INITIAL_FILL; - //( TRUE == getBicartDrainRequested() ) - //drain dryBicartStartRequest = DRY_BICART_DRAIN; - //else idle dryBicartStartRequest = DRY_BICART_IDLE; - updateDrybicartOperation(); + //DRY_BICART_SUPPLY ; + //DRY_BICART_INITIAL_FILL; + //DRY_BICART_DRAIN; + //default DRY_BICART_IDLE; + // the below function select any one of the above request + //updateDrybicartOperation(); + if( getCurrentBalancingChamberExecState() > BAL_CHAMBER_STATE_IDLE ) { // closed loop bicarb and acid mixing controller @@ -286,6 +287,12 @@ { case DRY_BICART_IDLE: // run as idle state + //DRY_BICART_SUPPLY ; + //DRY_BICART_INITIAL_FILL; + //DRY_BICART_DRAIN; + //default DRY_BICART_IDLE; + //the below function select any one of the above request + updateDrybicartOperation(); break; case DRY_BICART_INITIAL_FILL: @@ -396,7 +403,7 @@ break; case BICARB_CHAMBER_FILL_STATE: - bicarbChamberFillExecState = handleBicarbChamberFillState(); + bicarbChamberFillExecState = handleBicarbChamberSupplyStart(); break; case BICARB_CHAMBER_PRESSURE_CHECK_STATE: @@ -919,6 +926,7 @@ hydChamberWaterInletControl(); state = DRY_BICART_START_STATE; + dryBicartStartRequest = DRY_BICART_IDLE; } return state; @@ -1030,12 +1038,12 @@ /*********************************************************************//** * @brief - * The handleBicarbChambeSupplyStart function open the bicarb inlet valve (D80). + * The handleBicarbChamberSupplyStart function open the bicarb inlet valve (D80). * @details \b Inputs: none * @details \b Outputs: valve states, dryBiCarbSupplyStartTime * @return the next bicarb chamber fill state. *************************************************************************/ -static BICARB_CHAMBER_FILL_EXEC_STATE_T handleBicarbChambeSupplyStart( void ) +static BICARB_CHAMBER_FILL_EXEC_STATE_T handleBicarbChamberSupplyStart( void ) { BICARB_CHAMBER_FILL_EXEC_STATE_T state = BICARB_CHAMBER_PRESSURE_CHECK_STATE; @@ -1153,7 +1161,7 @@ setValveState( D64_VALV, VALVE_STATE_OPEN ); // D66 pressure drops to below 1.5 PSI or time out - if ( ( d66Pressure <= DRY_BICART_FILL_VENT_COMPLETE_PRESSURE ) ) + if ( ( d66Pressure <= DRY_BICART_FILL_VENT_COMPLETE_PRESSURE_PSI ) ) { // start the persistence timer once d66 reaches if it drops below 1.5 if ( 0 == dryBiCartPersistenceStartTime ) @@ -1202,6 +1210,8 @@ state = BICARB_CHAMBER_START_STATE; + dryBicartStartRequest = DRY_BICART_IDLE; + return state; } @@ -1379,6 +1389,7 @@ // for this request override also cleared dryBiCartDrainRequested.ovData = FALSE; state = DRY_BICART_DRAIN_START_STATE; + dryBicartStartRequest = DRY_BICART_IDLE; return state; } Index: firmware/App/Controllers/DryBiCart.h =================================================================== diff -u -rfc26356f5aae3e51f6267e41da0d74e76a9d5b6d -rcd1161514dbaff9e5b222931fff99618e39fd7ec --- firmware/App/Controllers/DryBiCart.h (.../DryBiCart.h) (revision fc26356f5aae3e51f6267e41da0d74e76a9d5b6d) +++ firmware/App/Controllers/DryBiCart.h (.../DryBiCart.h) (revision cd1161514dbaff9e5b222931fff99618e39fd7ec) @@ -74,6 +74,9 @@ BOOL testDryBiCartDrainRequestOverride( MESSAGE_T *message ); BOOL testDryBiCartTypeOverride( MESSAGE_T *message ); +BOOL testDryBiCartUpperCartPressureOverride( MESSAGE_T *message ); +BOOL testDryBiCartLowerCartPressureOverride( MESSAGE_T *message ); + /**@}*/ #endif Index: firmware/App/Controllers/MixingControl.c =================================================================== diff -u --- firmware/App/Controllers/MixingControl.c (revision 0) +++ firmware/App/Controllers/MixingControl.c (revision cd1161514dbaff9e5b222931fff99618e39fd7ec) @@ -0,0 +1,1136 @@ +/************************************************************************** +* +* Copyright (c) 2025-2026 Diality Inc. - All Rights Reserved. +* +* THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, IN PART OR IN +* WHOLE, WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. +* +* @file MixingControl.c +* +* @author (last) Sameer Kalliadan Poyil +* @date (last) 05-Jun-2026 +* +* @author (original) Sameer Kalliadan Poyil +* @date (original) 05-Jun-2026 +* +***************************************************************************/ + +#include "BalancingChamber.h" +#include "Common.h" +#include "ConcentratePumps.h" +#include "Conductivity.h" +#include "DialysatePumps.h" +#include "DDDefs.h" +#include "DryBiCart.h" +#include "Level.h" +#include "Messaging.h" +#include "MixingControl.h" +#include "ModeGenDialysate.h" +#include "OperationModes.h" +#include "PIControllers.h" +#include "PressureSensor.h" +#include "PersistentAlarm.h" +#include "Pressure.h" +#include "TaskGeneral.h" +#include "TDInterface.h" +#include "TemperatureSensors.h" +#include "Timers.h" +#include "Valves.h" + +/** + * @addtogroup MixingControl + * @{ + */ + +// ********** private definitions ********** + +#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 MIN_BICARB_VOLUME_ML 0.868686869 ///< Minimum bicarb volume in mL +#define MAX_BICARB_VOLUME_ML 1.8F ///< Maximum bicarb volume in mL + +#define ACID_VOL_CONTROL_P_COEFFICIENT ( 0.00000997F / 2 ) ///< Acid proportional gain (kp) +#define ACID_VOL_CONTROL_I_COEFFICIENT ( 0.00003988F / 5 ) ///< Acid integral gain. (ki) +#define MIN_ACID_VOLUME_ML 0.3F ///< Minimum acid volume in mL +#define MAX_ACID_VOLUME_ML 1.0F ///< Maximum acid volume in mL/min. + +#define BICARB_TARGET_CONDUCTIVITY 2714.0F ///< Target bicarb conductivity +#define BICARB_DELTA_CONDUCTIVITY 500.0F ///< Delta bicarb conductivity + +#define DIALYSATE_TARGET_CONDUCTIVITY 3734.87F ///< Target dialysate conductivity +#define DIALYSATE_DELTA_CONDUCTIVITY 700.0F ///< Delta dialysate conductivity + +// this is for reference only , it can be removed later +#define ACID_TYPE_1K_2_5_CA 11192.55F ///< standard acid conductivity for 1K +#define ACID_TYPE_2K_2_5_CA 11313.62F ///< standard acid conductivity for 2K +#define ACID_TYPE_3K_2_5_CA 11435.68F ///< standard acid conductivity for 3K + +#define MIX_NO_FEED_FORWARD 0.0F ///< Feed forward term for dialysate closed loop control + +#define BICARB_MIX_CONTROL_INTERVAL ( 15 * MS_PER_SECOND / TASK_GENERAL_INTERVAL ) ///< Interval (ms/task time) at which the bicarb mix is controlled. +#define ACID_MIX_CONTROL_INTERVAL ( 9 * 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 + +// Proportioning Ratios: 1 Part Acid : 1.72 Parts Bicarb : 42.28 Parts Water +// Total parts = 1 + 1.72 + 42.28 = 45.0 +#define STD_45X_CONC_MIX_ACID_PART 1.0F ///< Acid portion of 45X concentration mix +#define STD_45X_CONC_MIX_BICARB_PART 1.72F ///< Bicarb portion of 45X concentration mix +#define STD_45X_CONC_MIX_WATER_PART 42.28F ///< Water portion of 45X concentration mix + + +#define TOTAL_STD_45X_MIX_PART ( STD_45X_CONC_MIX_ACID_PART + STD_45X_CONC_MIX_BICARB_PART + \ + STD_45X_CONC_MIX_WATER_PART ) ///< Total 45X mix + +#define ACID_PCT_IN_DIALYSTATE ( ( STD_45X_CONC_MIX_ACID_PART / TOTAL_STD_45X_MIX_PART ) ) ///< Acid percent in Dialysate +#define BICARB_PCT_IN_DIALYSATE ( ( STD_45X_CONC_MIX_BICARB_PART / TOTAL_STD_45X_MIX_PART) ) ///< Bicarb Percent in Dialysate +#define WATER_PCT_IN_DIALYSATE ( ( STD_45X_CONC_MIX_WATER_PART / TOTAL_STD_45X_MIX_PART) ) ///< Water percent in Dialysate +#define RO_WATER_VOLUME_ML ( BAL_CHAMBER_FILL_VOLUME_ML * WATER_PCT_IN_DIALYSATE ) ///< Water volume +#define ACID_MIX_VOLUME_ML ( BAL_CHAMBER_FILL_VOLUME_ML * ACID_PCT_IN_DIALYSTATE ) ///< Acid volume +#define BICARB_MIX_VOLUME_ML ( BAL_CHAMBER_FILL_VOLUME_ML * BICARB_PCT_IN_DIALYSATE ) ///< Bicarb volume + +#define STD_DILUTION_ACID_POST_MIX_NA 100.0F ///< Acid post mix Sodium +#define STD_DILUTION_BICARB_POST_MIX_NA 37.0F ///< Bicarb post mix Sodium +#define STD_DILUTION_BICARB_POST_MIX_CHO3 33.0F ///< Post mix bicarbonate + +#define DIALYSATE_TARGET_STD_NA_SETTINGS 137.0F ///< Standard target sodium +#define DIALYSATE_TARGET_STD_BICARB_SETTING 33.0F ///< Standard bicarb +#define DIALYSATE_TARGET_USER_ADJ_SODIUM_SETTING getTDSodiumConcentration() ///< User Sodium +#define DIALYSATE_TARGET_USER_ADJ_BICARB_SETTING getTDBicarbonateConcentration() ///< User bicarb + +#define BICARB_PERCENT_CHANGE ( 1 + ( ( DIALYSATE_TARGET_USER_ADJ_BICARB_SETTING - DIALYSATE_TARGET_STD_BICARB_SETTING) /\ + DIALYSATE_TARGET_STD_BICARB_SETTING ) ) ///< Bicarb percentage change + +#define BICARB_PERCENT_CHANGE_NA ( STD_DILUTION_BICARB_POST_MIX_NA * BICARB_PERCENT_CHANGE ) ///< Percent change of sodium + +#define BICARB_PERCENT_CHANGE_NAHCO3 ( STD_DILUTION_BICARB_POST_MIX_CHO3 * BICARB_PERCENT_CHANGE ) ///< Percentage change of bicarbonate + +#define ACID_TARGET_CONCENTRATE_NA ( DIALYSATE_TARGET_USER_ADJ_SODIUM_SETTING - BICARB_PERCENT_CHANGE_NA ) ///< Acid Target concentrate sodium + +#define ACID_PERCENT_CHANGE ( ( 1 + ( ACID_TARGET_CONCENTRATE_NA - STD_DILUTION_ACID_POST_MIX_NA ) / STD_DILUTION_ACID_POST_MIX_NA ) ) ///< Acid percentage change + +#define FINAL_NA_ADJ_MIX ( ACID_TARGET_CONCENTRATE_NA + BICARB_PERCENT_CHANGE_NA ) ///< Final adjusted sodium + +#define FINAL_NAHCO3_ADJ_MIX ( BICARB_PERCENT_CHANGE_NAHCO3 ) + +#define FINAL_ACID_MIX ( ACID_MIX_VOLUME_ML * ACID_PERCENT_CHANGE ) ///< Final Acid Mix + +#define FINAL_BICARB_MIX ( BICARB_MIX_VOLUME_ML * BICARB_PERCENT_CHANGE ) ///< Final bicarb mix + +#define BICARB_CONDUCTIVITY_PRE ( STD_DILUTION_BICARB_POST_MIX_NA * BICARB_PERCENT_CHANGE * getTDBicarbConversionFactor() ) ///< Theoretical bicarb conductivity pre mix + +#define BICARB_CONDUCTIVITY_POST ( STD_DILUTION_BICARB_POST_MIX_CHO3 * BICARB_PERCENT_CHANGE * getTDBicarbConversionFactor() ) ///< Theoretical bicarb conductivity post mix + +#define ACID_CONDUCTIVITY_POST ( STD_DILUTION_ACID_POST_MIX_NA * ACID_PERCENT_CHANGE * getTDAcidConversionFactor() ) ///< Theoretical Acid conductivity post mix + +#define TOTAL_CONDUCTIVITY ( ACID_CONDUCTIVITY_POST + BICARB_CONDUCTIVITY_POST ) ///< Theoretical Dialysate conductivity + + +/// Enumeration of dialysate Mixing id. +typedef enum DialysateMixingID +{ + BICARB_MIX_ID = 0, ///< Bicarb mixing id + DIALYSATE_MIX_ID_FIRST = BICARB_MIX_ID, ///< First dialysate mixing in list + ACID_MIX_ID, ///< Acid mix id + NUM_OF_DIALYSATE_MIXING_ID ///< Number of dialysate mix ids +} DIALYSATE_MIXING_ID_T; + +/// Enumeration of dialysate Mixing states. +typedef enum DialysateMixing_States +{ + DIALYSATE_MIXING_OPEN_LOOP_STATE = 0, ///< Dialysate open loop state + DIALYSATE_MIXING_RAMP_UP_STATE, ///< Dialysate mixing ramp up state + DIALYSATE_MIXING_CONTROL_TO_TARGET_STATE, ///< Dialysate mixing control to target state + NUM_OF_DIALYSATE_MIXING_STATES ///< Number of dialysate mixing states +} DIALYSATE_MIXING_STATE_T; + +/// 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. +} DIALYSATE_MIXING_DATA_T; + +// ********** private data ********** + +// publish +static OVERRIDE_U32_T mixingControlDataPublishInterval; ///< Mixing Control data publish interval. +static U32 mixingControlDataPublicationTimerCounter; ///< Used to schedule mixingControl data publication to CAN bus. + +// mixing +static OVERRIDE_F32_T mixingControlAcidVolume; ///< Acid concentrate volume in ml ( overrideable). +static OVERRIDE_F32_T mixingControlBicarbVolume; ///< Bicarb concentrate volume in ml ( overrideable). + +static OVERRIDE_F32_T mixingControlAcidVolumeKpGain; ///< Acid kp gain. +static OVERRIDE_F32_T mixingControlAcidVolumeKiGain; ///< Acid ki gain. + +static OVERRIDE_F32_T mixingControlBicarbVolumeKpGain; ///< Bicarb kp gain +static OVERRIDE_F32_T mixingControlBicarbVolumeKiGain; ///< Acid ki gain. + +static DIALYSATE_MIXING_DATA_T dialysateMix[ NUM_OF_DIALYSATE_MIXING_ID ]; ///< Array of dialysate mixing data structure. + +static OVERRIDE_F32_T mixingControlBicarbTargetConductivity; ///< Target bicarb conductivity +static OVERRIDE_F32_T mixingControlBicarbDeltaConductivity; ///< Target delta conductivity + +static OVERRIDE_F32_T mixingControlDialysateTargetConductivity; ///< Dialysate mix conductivity +static OVERRIDE_F32_T mixingControlDialysateDeltaConductivity; ///< Dialysate delta conductivity + +static OVERRIDE_F32_T mixingControlStdMixingBCVolume; ///< Standard mixing balancing chamber volume +static OVERRIDE_F32_T mixingControlTargetAdjNaSettings; ///< Adjusted Sodium +static OVERRIDE_F32_T mixingControlTargetAdjBicarbSettings; ///< Adjusted bicarb + +static OVERRIDE_U32_T mixingControlBicarbControlInterval; ///< Bicarb mix control interval +static OVERRIDE_U32_T mixingControlAcidControlInterval; ///< Acid 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 + +// ********** private function prototypes ********** + +// 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 ); + +static void setBicarbMixVol( F32 targetValue ); +static void setAcidMixVol( F32 targetValue ); + +static F32 getBicarbDeltaConductivity( void ); +static F32 getBicarbTargetConductivity( void ); + +static F32 getDialysateDeltaConductivity( void ); +static F32 getDialysateTargetConductivity( void ); + +static F32 getTotalConductivity( void ); +static F32 getAcidConducivityPost( void ); +static F32 getBicarbConductivityPost( void ); +static F32 getBicarbConductivityPre( void ); + +static F32 getBicarbKpGainCoefficient( void ); +static F32 getBicarbKiGainCoefficient( void ); +static F32 getAcidKpGainCoefficient( void ); +static F32 getAcidKiGainCoefficient( void ); + +static U32 getMixingControlBicarbControlInterval( void ); +static U32 getMixingControlAcidControlInterval( void ); +// publish the status +static void publishMixingControlData( void ); +static U32 getMixingControlDataPublishInterval( void ); + +/*********************************************************************//** + * @brief + * The The initMixingControl function initializes the mixing controller + * module. + * @details \b Inputs: none + * @details \b Outputs: unit variables initialized + * @return none + *************************************************************************/ +void initMixingControl( void ) +{ + DIALYSATE_MIXING_ID_T mixId; + + for ( mixId = DIALYSATE_MIX_ID_FIRST; mixId < NUM_OF_DIALYSATE_MIXING_ID; mixId++ ) + { + dialysateMix[ mixId ].dialysateMixingState = DIALYSATE_MIXING_OPEN_LOOP_STATE; + dialysateMix[ mixId ].controlTimerCounter = 0; + } + + mixingControlDataPublishInterval.data = MIXING_CONTROL_DATA_PUBLISH_INTERVAL; + mixingControlDataPublishInterval.ovData = MIXING_CONTROL_DATA_PUBLISH_INTERVAL; + mixingControlDataPublishInterval.ovInitData = 0; + mixingControlDataPublishInterval.override = OVERRIDE_RESET; + + mixingControlAcidVolume.data = DEFAULT_ACID_VOLUME_ML; + mixingControlAcidVolume.ovData = DEFAULT_ACID_VOLUME_ML; + mixingControlAcidVolume.ovInitData = 0.0F; + mixingControlAcidVolume.override = OVERRIDE_RESET; + + mixingControlBicarbVolume.data = DEFAULT_BICARB_VOLUME_ML; + mixingControlBicarbVolume.ovData = DEFAULT_BICARB_VOLUME_ML; + mixingControlBicarbVolume.ovInitData = 0.0F; + mixingControlBicarbVolume.override = OVERRIDE_RESET; + + mixingControlAcidVolumeKpGain.data = ACID_VOL_CONTROL_P_COEFFICIENT; + mixingControlAcidVolumeKpGain.ovData = ACID_VOL_CONTROL_P_COEFFICIENT; + mixingControlAcidVolumeKpGain.ovInitData = 0.0F; + mixingControlAcidVolumeKpGain.override = OVERRIDE_RESET; + + mixingControlAcidVolumeKiGain.data = ACID_VOL_CONTROL_I_COEFFICIENT; + mixingControlAcidVolumeKiGain.ovData = ACID_VOL_CONTROL_I_COEFFICIENT; + mixingControlAcidVolumeKiGain.ovInitData = 0.0F; + mixingControlAcidVolumeKiGain.override = OVERRIDE_RESET; + + mixingControlBicarbVolumeKpGain.data = BICARB_VOL_CONTROL_P_COEFFICIENT; + mixingControlBicarbVolumeKpGain.ovData = BICARB_VOL_CONTROL_P_COEFFICIENT; + mixingControlBicarbVolumeKpGain.ovInitData = 0.0F; + mixingControlBicarbVolumeKpGain.override = OVERRIDE_RESET; + + mixingControlBicarbVolumeKiGain.data = BICARB_VOL_CONTROL_I_COEFFICIENT; + mixingControlBicarbVolumeKiGain.ovData = BICARB_VOL_CONTROL_I_COEFFICIENT; + mixingControlBicarbVolumeKiGain.ovInitData = 0.0F; + mixingControlBicarbVolumeKiGain.override = OVERRIDE_RESET; + + mixingControlBicarbTargetConductivity.data = BICARB_TARGET_CONDUCTIVITY; + mixingControlBicarbTargetConductivity.ovData = BICARB_TARGET_CONDUCTIVITY; + mixingControlBicarbTargetConductivity.ovInitData = 0.0F; + mixingControlBicarbTargetConductivity.override = OVERRIDE_RESET; + + mixingControlBicarbDeltaConductivity.data = BICARB_DELTA_CONDUCTIVITY; + mixingControlBicarbDeltaConductivity.ovData = BICARB_DELTA_CONDUCTIVITY; + mixingControlBicarbDeltaConductivity.ovInitData = 0.0F; + mixingControlBicarbDeltaConductivity.override = OVERRIDE_RESET; + + mixingControlDialysateTargetConductivity.data = DIALYSATE_TARGET_CONDUCTIVITY; + mixingControlDialysateTargetConductivity.ovData = DIALYSATE_TARGET_CONDUCTIVITY; + mixingControlDialysateTargetConductivity.ovInitData = 0.0F; + mixingControlDialysateTargetConductivity.override = OVERRIDE_RESET; + + mixingControlDialysateDeltaConductivity.data = DIALYSATE_DELTA_CONDUCTIVITY; + mixingControlDialysateDeltaConductivity.ovData = DIALYSATE_DELTA_CONDUCTIVITY; + mixingControlDialysateDeltaConductivity.ovInitData = 0.0F; + mixingControlDialysateDeltaConductivity.override = OVERRIDE_RESET; + + mixingControlStdMixingBCVolume.data = BAL_CHAMBER_FILL_VOLUME_ML; + mixingControlStdMixingBCVolume.ovData = BAL_CHAMBER_FILL_VOLUME_ML; + mixingControlStdMixingBCVolume.ovInitData = 0.0F; + mixingControlStdMixingBCVolume.override = OVERRIDE_RESET; + + mixingControlTargetAdjNaSettings.data = DIALYSATE_TARGET_USER_ADJ_SODIUM_SETTING; + mixingControlTargetAdjNaSettings.ovData = DIALYSATE_TARGET_USER_ADJ_SODIUM_SETTING; + mixingControlTargetAdjNaSettings.ovInitData = 0.0F; + mixingControlTargetAdjNaSettings.override = OVERRIDE_RESET; + + mixingControlTargetAdjBicarbSettings.data = DIALYSATE_TARGET_USER_ADJ_BICARB_SETTING; + mixingControlTargetAdjBicarbSettings.ovData = DIALYSATE_TARGET_USER_ADJ_BICARB_SETTING; + mixingControlTargetAdjBicarbSettings.ovInitData = 0.0F; + mixingControlTargetAdjBicarbSettings.override = OVERRIDE_RESET; + + mixingControlBicarbControlInterval.data = BICARB_MIX_CONTROL_INTERVAL; + mixingControlBicarbControlInterval.ovData = BICARB_MIX_CONTROL_INTERVAL; + mixingControlBicarbControlInterval.ovInitData = 0; + mixingControlBicarbControlInterval.override = OVERRIDE_RESET; + + mixingControlAcidControlInterval.data = ACID_MIX_CONTROL_INTERVAL; + mixingControlAcidControlInterval.ovData = ACID_MIX_CONTROL_INTERVAL; + mixingControlAcidControlInterval.ovInitData = 0; + mixingControlAcidControlInterval.override = OVERRIDE_RESET; + + mixingControlDataPublicationTimerCounter = 0; + +} + +/*********************************************************************//** + * @brief + * The transitionToMixingControl function prepares for transition to + * mixing in open loop/ closed loop operations. + * @details \b Inputs: none + * @details \b Outputs: none + * @return none + *************************************************************************/ +void transitionToMixingControl( void ) +{ + initMixingControl(); +} + +/*********************************************************************//** + * @brief + * The execDialysateCompositionMixingController function adjusts the volume of acid and bicarb based on the target + * conductivity of bicarb and dialysate solution + * @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 + *************************************************************************/ +void execDialysateCompositionMixingController( void ) +{ + DIALYSATE_MIXING_ID_T mixId; + + for ( mixId = DIALYSATE_MIX_ID_FIRST; mixId < NUM_OF_DIALYSATE_MIXING_ID; mixId++ ) + { + switch ( dialysateMix[ mixId ].dialysateMixingState ) + { + case DIALYSATE_MIXING_OPEN_LOOP_STATE: + dialysateMix[ mixId ].dialysateMixingState = handleDialysateMixOpenLoopState( mixId ); + break; + + case DIALYSATE_MIXING_RAMP_UP_STATE: + dialysateMix[ mixId ].dialysateMixingState = handleDialysateMixRampToTargetState( mixId ); + break; + + case DIALYSATE_MIXING_CONTROL_TO_TARGET_STATE: + dialysateMix[ mixId ].dialysateMixingState = handleDialysateMixControlToTargetState( mixId ); + break; + + default: + SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DD_SOFTWARE_FAULT, SW_FAULT_ID_DIALYSATE_MIX_EXEC_INVALID_STATE, mixId ) + dialysateMix[ mixId ].dialysateMixingState = DIALYSATE_MIXING_OPEN_LOOP_STATE; + break; + } + } +} + +/*********************************************************************//** + * @brief + * The execMixingControl function executes the dialysate and bicarb open loop /closed loop + * related state machines + * @details \b Inputs: none + * @details \b Outputs: none + * @return none. + *************************************************************************/ +void execMixingControl( void ) +{ + if( getCurrentBalancingChamberExecState() > BAL_CHAMBER_STATE_IDLE ) + { + // closed loop bicarb and acid mixing controller + execDialysateCompositionMixingController(); + } + + // Publish mixing control data + publishMixingControlData(); + +} + +/*********************************************************************//** + * @brief + * TThe getBicarbMixVol function gets the bicarb mix volume provided by the controller + * @details \b Inputs: mixingControlBicarbVolume + * @details \b Outputs: none + * @return TRUE if successful, FALSE if not. + *************************************************************************/ +F32 getBicarbMixVol( void ) +{ + F32 result = getF32OverrideValue( &mixingControlBicarbVolume ); + + return result; +} + +/*********************************************************************//** + * @brief + * The getAcidMixVol function gets acid mix volume provided by the controller + * @details \b Inputs: mixingControlAcidVolume + * @details \b Outputs: none + * @return TRUE if successful, FALSE if not. + *************************************************************************/ +F32 getAcidMixVol( void ) +{ + F32 result = getF32OverrideValue( &mixingControlAcidVolume ); + + return result; +} + +/*********************************************************************//** + * @brief + * The setAcidMixVol function sets acid mix volume provided by the controller + * flag value to be True. + * @details \b Inputs: none + * @details \b Outputs: mixingControlAcidMixVolume + * @param targetValue acid mix volume + * @return TRUE if successful, FALSE if not. + *************************************************************************/ +static void setAcidMixVol( F32 targetValue ) +{ + mixingControlAcidVolume.data = targetValue; +} + +/*********************************************************************//** + * @brief + * The setBicarbMixVol function sets 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 setBicarbMixVol( F32 targetValue ) +{ + mixingControlBicarbVolume.data = targetValue; +} + +/*********************************************************************//** + * @brief + * The getBicarbDeltaConductivity function gets the delta target conductivity + * @details \b Inputs: mixingControlBicarbDeltaConductivity + * @details \b Outputs: none + * @return TRUE if successful, FALSE if not. + *************************************************************************/ +static F32 getBicarbDeltaConductivity( void ) +{ + F32 result = getF32OverrideValue( &mixingControlBicarbDeltaConductivity ); + + return result; +} + +/*********************************************************************//** + * @brief + * The getBicarbTargetConductivity function gets the target conductivity + * @details \b Inputs: mixingControlBicarbTargetConductivity + * @details \b Outputs: none + * @return TRUE if successful, FALSE if not. + *************************************************************************/ +static F32 getBicarbTargetConductivity( void ) +{ + F32 result = getF32OverrideValue( &mixingControlBicarbTargetConductivity ); + + return result; +} + +/*********************************************************************//** + * @brief + * The getDialysateDeltaConductivity function gets the acid bicarb delta target conductivity + * @details \b Inputs: mixingControlDialysateDeltaConductivity + * @details \b Outputs: none + * @return TRUE if successful, FALSE if not. + *************************************************************************/ +static F32 getDialysateDeltaConductivity( void ) +{ + F32 result = getF32OverrideValue( &mixingControlDialysateDeltaConductivity ); + + return result; +} + +/*********************************************************************//** + * @brief + * The getDialysateTargetConductivity function gets the acid bicarb delta target conductivity + * @details \b Inputs: mixingControlDialysateTargetConductivity + * @details \b Outputs: none + * @return TRUE if successful, FALSE if not. + *************************************************************************/ +static F32 getDialysateTargetConductivity( void ) +{ + F32 result = getF32OverrideValue( &mixingControlDialysateTargetConductivity ); + + return result; +} + +/*********************************************************************//** + * @brief + * The getBicarbKpGainCoefficient function gets the Kp Gain for closed loop + * bicarb mix volume control + * @details \b Inputs: mixingControlBicarbMixVolumeKpGain + * @details \b Outputs: none + * @return TRUE if successful, FALSE if not. + *************************************************************************/ +static F32 getBicarbKpGainCoefficient( void ) +{ + F32 result = getF32OverrideValue( &mixingControlBicarbVolumeKpGain ); + + return result; +} + +/*********************************************************************//** + * @brief + * The getBicarbKiGainCoefficient function gets the Kp Gain for closed loop + * bicarb mix volume control + * @details \b Inputs: mixingControlBicarbMixVolumeKiGain + * @details \b Outputs: none + * @return TRUE if successful, FALSE if not. + *************************************************************************/ +static F32 getBicarbKiGainCoefficient( void ) +{ + F32 result = getF32OverrideValue( &mixingControlBicarbVolumeKiGain ); + + return result; +} + +/*********************************************************************//** + * @brief + * The getAcidKpGainCoefficient function gets the Kp Gain for closed loop + * acid mix volume control + * @details \b Inputs: mixingControlAcidMixVolumeKpGain + * @details \b Outputs: none + * @return TRUE if successful, FALSE if not. + *************************************************************************/ +static F32 getAcidKpGainCoefficient( void ) +{ + F32 result = getF32OverrideValue( &mixingControlAcidVolumeKpGain ); + + return result; +} + + +/*********************************************************************//** + * @brief + * The getAcidKiGainCoefficient function gets the Ki Gain for closed loop + * acid mix volume control + * @details \b Inputs: mixingControlAcidMixVolumeKiGain + * @details \b Outputs: none + * @return TRUE if successful, FALSE if not. + *************************************************************************/ +static F32 getAcidKiGainCoefficient( void ) +{ + F32 result = getF32OverrideValue( &mixingControlAcidVolumeKiGain ); + + return result; +} + +/*********************************************************************//** + * @brief + * The getmixingControlBicarbMixControlInterval function gets the bicart mix control interval + * @details \b Inputs: mixingControlBicarbMixControlInterval + * @details \b Outputs: none + * @return TRUE if successful, FALSE if not. + *************************************************************************/ +static U32 getMixingControlBicarbControlInterval( void ) +{ + U32 result = getU32OverrideValue( &mixingControlBicarbControlInterval ); + + return result; +} + +/*********************************************************************//** + * @brief + * The getMixingControlAcidControlInterval function gets the acid mix control interval + * @details \b Inputs: mixingControlAcidControlInterval + * @details \b Outputs: none + * @return TRUE if successful, FALSE if not. + *************************************************************************/ +static U32 getMixingControlAcidControlInterval( void ) +{ + U32 result = getU32OverrideValue( &mixingControlAcidControlInterval ); + + return result; +} + +static F32 getTotalConductivity( void ) +{ + return TOTAL_CONDUCTIVITY; +} + +static F32 getAcidConducivityPost( void ) +{ + return ACID_CONDUCTIVITY_POST; +} + +static F32 getBicarbConductivityPost( void ) +{ + return BICARB_CONDUCTIVITY_PRE; +} + +static F32 getBicarbConductivityPre( void ) +{ + return BICARB_CONDUCTIVITY_PRE; +} + + + +/*********************************************************************//** + * @brief + * The getmixingControlFillDataPublishInterval function gets the mix controller + * data publish interval. + * @details \b Inputs: mixingControlDataPublishInterval + * @details \b Outputs: none + * @return the interval at mixing control data being published. + *************************************************************************/ +static U32 getMixingControlDataPublishInterval( void ) +{ + U32 result = getU32OverrideValue( &mixingControlDataPublishInterval ); + + return result; +} + +/*********************************************************************//** + * @brief + * The handleDialysateOpenLoopState function handles the dialysate open loop state of + * the dialysate mix controller state machine. + * @details \b Inputs: D17_COND, D29_COND + * @details \b Outputs: none + * @param mixId dialysate mix id to run the dialysate mix + * @return next state for the controller state machine + *************************************************************************/ +static DIALYSATE_MIXING_STATE_T handleDialysateMixOpenLoopState( DIALYSATE_MIXING_ID_T mixId ) +{ + DIALYSATE_MIXING_STATE_T result; + + if ( BICARB_MIX_ID == mixId ) + { + F32 measuredBicarbConductivity = getFilteredConductivity( D17_COND ); + F32 bicarbConductivity = getBicarbTargetConductivity(); + F32 bicarbDeltaConductivity = getBicarbDeltaConductivity(); + + result = DIALYSATE_MIXING_OPEN_LOOP_STATE; + + if ( TRUE != getTestConfigStatus( TEST_CONFIG_DD_ENABLE_DOSING_OPEN_LOOP_CONTROL ) ) + { + // if measured conductivity crossed (targetConductivity- deltaConuctivity) , switch to closed loop + if ( measuredBicarbConductivity >= ( bicarbConductivity - bicarbDeltaConductivity ) ) + { + result = DIALYSATE_MIXING_RAMP_UP_STATE; + } + } + } + else if ( ACID_MIX_ID == mixId ) + { + F32 measuredAcidBicarbMixConductivity = getFilteredConductivity( D27_COND ); + F32 DialysateConductivity = getDialysateTargetConductivity(); + F32 DialysateDeltaConductivity = getDialysateTargetConductivity(); + + result = DIALYSATE_MIXING_OPEN_LOOP_STATE; + + if ( TRUE != getTestConfigStatus( TEST_CONFIG_DD_ENABLE_DOSING_OPEN_LOOP_CONTROL ) ) + { + // if measured conductivity crossed (targetConductivity- deltaConuctivity) , switch to closed loop + if ( measuredAcidBicarbMixConductivity >= ( DialysateConductivity - DialysateDeltaConductivity ) ) + { + result = DIALYSATE_MIXING_RAMP_UP_STATE; + } + } + } + + return result; +} + +/*********************************************************************//** + * @brief + * The handleDialysatePumpRampToTargetState function handles the dialysate ramp to target state of + * the dialysate mix controller state machine. + * @details \b Inputs: none + * @details \b Outputs: none + * @param mixId mix id to + * @return next state for the controller state machine + *************************************************************************/ +static DIALYSATE_MIXING_STATE_T handleDialysateMixRampToTargetState( DIALYSATE_MIXING_ID_T mixId ) +{ + DIALYSATE_MIXING_STATE_T state = DIALYSATE_MIXING_RAMP_UP_STATE; + + if ( BICARB_MIX_ID == mixId ) + { + resetPIController( PI_CONTROLLER_ID_BICARB_VOL, DEFAULT_BICARB_VOLUME_ML, MIX_NO_FEED_FORWARD ); + + state = DIALYSATE_MIXING_CONTROL_TO_TARGET_STATE; + } + else if ( ACID_MIX_ID == mixId ) + { + resetPIController( PI_CONTROLLER_ID_ACID_VOL, DEFAULT_ACID_VOLUME_ML, MIX_NO_FEED_FORWARD ); + + state = DIALYSATE_MIXING_CONTROL_TO_TARGET_STATE; + } + + return state; +} + +/*********************************************************************//** + * @brief + * The handleDialysatePumpControlToTargetState function handles the control to + * target state of the dialysate mix controller state machine.. + * @details \b Inputs: D17_COND, D29_COND, controlTimerCounter + * @details \b Outputs:none + * @return next state of the controller state machine + *************************************************************************/ +static DIALYSATE_MIXING_STATE_T handleDialysateMixControlToTargetState( DIALYSATE_MIXING_ID_T mixId ) +{ + DIALYSATE_MIXING_STATE_T state = DIALYSATE_MIXING_CONTROL_TO_TARGET_STATE; + + if ( BICARB_MIX_ID == mixId ) + { + // control interval for bicarb + if ( ( ++dialysateMix[ mixId ].controlTimerCounter >= getMixingControlBicarbControlInterval() ) ) + { + F32 bicarbMixVol; + + dialysateMix[ mixId ].controlTimerCounter = 0; + + // Control based on the measured and target conductivity + PI_CONTROLLER_SIGNALS_DATA debugBicarbControl; + F32 measuredBicarbConductivity = getFilteredConductivity( D17_COND ); + F32 bicarbConductivity = getBicarbConductivityPre();//getBicarbTargetConductivity(); + + if ( fabs ( bicarbConductivity - measuredBicarbConductivity ) > BICARB_DEADBAND_CONTROL ) + { + bicarbMixVol = runPIController( PI_CONTROLLER_ID_BICARB_VOL, getBicarbConductivityPre() /*getBicarbTargetConductivity()*/, measuredBicarbConductivity ); + //Set bicarb mix vol only if its above dead band threshold, else use the previous set vlaue + setBicarbMixVol( bicarbMixVol ); + } + else + { + //use the previous value + } + + debugBicarbControl = getDebugPIControllerSignals( PI_CONTROLLER_ID_BICARB_VOL ); + + memcpy( (void*)&bicarbControlSignals, (void*)&debugBicarbControl, sizeof(PI_CONTROLLER_SIGNALS_DATA) ); + } + } + + if ( ACID_MIX_ID == mixId ) + { + // control interval for acid + if ( ( ++dialysateMix[ mixId ].controlTimerCounter >= getMixingControlAcidControlInterval( ) ) ) + { + F32 acidMixVol; + + dialysateMix[ mixId ].controlTimerCounter = 0; + + F32 measuredDialysateConductivity = getFilteredConductivity( D27_COND ); + F32 DialysateConductivity = getTotalConductivity();//getDialysateTargetConductivity(); + PI_CONTROLLER_SIGNALS_DATA debugAcidControl; + + if ( fabs ( DialysateConductivity - measuredDialysateConductivity ) > ACID_DEADBAND_CONTROL ) + { + acidMixVol = runPIController( PI_CONTROLLER_ID_ACID_VOL, getTotalConductivity() /*DialysateConductivity*/, measuredDialysateConductivity ); + // set acid mix volume if its above dead band threshold , else use previous set value + setAcidMixVol( acidMixVol ); + } + else + { + // use the previous value + } + + debugAcidControl = getDebugPIControllerSignals( PI_CONTROLLER_ID_ACID_VOL ); + + memcpy( (void*)&acidControlSignals, (void*)&debugAcidControl, sizeof(PI_CONTROLLER_SIGNALS_DATA) ); + } + } + + return state; +} + + + + + +/*********************************************************************//** + * @brief + * The publishMixingControlData function broadcasts the Mixing Controller + * data at defined interval. + * @details \b Inputs: mixingControlDataPublicationTimerCounter + * @details \b Outputs: none + * @details \b Message \Sent: MSG_ID_DD_MIXING_CONTROL_DATA to publish the mixing control + * data. + * @return none + *************************************************************************/ +static void publishMixingControlData( void ) +{ + if ( ++mixingControlDataPublicationTimerCounter >= getMixingControlDataPublishInterval( ) ) + { + MIXING_CONTROL_DATA_T data; + + data.bicarbMixingState = (U32)dialysateMix[ BICARB_MIX_ID ].dialysateMixingState; + data.bicarbControlInterval = (U32)dialysateMix[ BICARB_MIX_ID ].controlTimerCounter; + data.acidMixingState = (U32)dialysateMix[ ACID_MIX_ID ].dialysateMixingState; + data.acidControlInterval = (U32)dialysateMix[ ACID_MIX_ID ].controlTimerCounter; + + data.bicarbVolume = getBicarbMixVol(); + data.acidVolume = getAcidMixVol(); + + // broadcast theretical pre and post conductivity + + // TODO: remove after feature testing + memcpy( &data.bicarbData, &bicarbControlSignals, sizeof( PI_CONTROLLER_SIGNALS_DATA ) ); + // TODO: remove after feature testing + memcpy( &data.acidData , &acidControlSignals , sizeof( PI_CONTROLLER_SIGNALS_DATA ) ); + + // TODO: remove after feature testing + data.bicarbKPgain = getBicarbKpGainCoefficient(); + // TODO: remove after feature testing + data.bicarbKIgain = getBicarbKiGainCoefficient(); + // TODO: remove after feature testing + data.acidKPgain = getAcidKpGainCoefficient(); + // TODO: remove after feature testing + data.aciKIgain = getAcidKiGainCoefficient(); + + broadcastData( MSG_ID_DD_MIXING_CONTROL_DATA, COMM_BUFFER_OUT_CAN_DD_BROADCAST, (U08*)&data, sizeof( MIXING_CONTROL_DATA_T ) ); + + mixingControlDataPublicationTimerCounter = 0; + } +} + + +/************************************************************************* + * TEST SUPPORT FUNCTIONS + *************************************************************************/ + + +/*********************************************************************//** + * @brief + * The testDDmixingControlDataPublishIntervalOverride function overrides the + * DD mixing control data publish interval. + * @details \b Inputs: mixingControlDataPublishInterval + * @details \b Outputs: mixingControlDataPublishInterval + * @param Override message from Dialin which includes the interval + * (in ms) to override the DD mixing control data publish interval to. + * @return TRUE if override successful, FALSE if not + *************************************************************************/ +BOOL testMixingControlDataPublishIntervalOverride( MESSAGE_T *message ) +{ + BOOL result = u32BroadcastIntervalOverride( message, &mixingControlDataPublishInterval, TASK_GENERAL_INTERVAL ); + + return result; +} + + +/*********************************************************************//** + * @brief + * The testmixingControlAcidMixVolumeOverride function sets the override value + * of the acid concentrate mixing volume. + * @details Inputs: mixingControlAcidMixVolume + * @details Outputs: mixingControlAcidMixVolume + * @param message Override message from Dialin which includes the override + * value to override the acid concentrate mixing volume. + * @return TRUE if override successful, FALSE if not + *************************************************************************/ +BOOL testMixingControlAcidMixVolumeOverride( MESSAGE_T *message ) +{ + BOOL result = f32Override( message, &mixingControlAcidVolume ); + + return result; +} + +/*********************************************************************//** + * @brief + * The testmixingControlBicarbMixVolumeOverride function sets the override value + * of the bicarb concentrate mixing volume. + * @details Inputs: mixingControlBicarbMixVolume + * @details Outputs: mixingControlBicarbMixVolume + * @param message Override message from Dialin which includes the override + * value to override the bicarb concentrate mixing volume. + * @return TRUE if override successful, FALSE if not + *************************************************************************/ +BOOL testMixingControlBicarbMixVolumeOverride( MESSAGE_T *message ) +{ + BOOL result = f32Override( message, &mixingControlBicarbVolume ); + + return result; +} + +/*********************************************************************//** + * @brief + * The testmixingControlBicarbMixVolControlKpGainOverride function sets the override value + * of the Kp gain coefficient for closed loop bicarb mixing volume control + * @details Inputs: mixingControlBicarbMixVolumeKpGain + * @details Outputs: mixingControlBicarbMixVolumeKpGain + * @param message Override message from Dialin which includes the override + * value to override the bicarb concentrate mixing volume kp gain. + * @return TRUE if override successful, FALSE if not + *************************************************************************/ +BOOL testMixingControlBicarbVolControlKpGainOverride( MESSAGE_T *message ) +{ + BOOL result = f32Override( message, &mixingControlBicarbVolumeKpGain ); + + initializePIController( PI_CONTROLLER_ID_BICARB_VOL, 0.0F,\ + getBicarbKpGainCoefficient(), getBicarbKiGainCoefficient(),\ + MIN_BICARB_VOLUME_ML, MAX_BICARB_VOLUME_ML, FALSE, MIX_NO_FEED_FORWARD ); + + return result; +} + +/*********************************************************************//** + * @brief + * The testmixingControlBicarbMixVolControlKiGainOverride function sets the override value + * of the Ki gain coefficient for closed loop bicarb concentrate mixing volume control + * @details Inputs: mixingControlBicarbMixVolumeKiGain + * @details Outputs: mixingControlBicarbMixVolumeKiGain + * @param message Override message from Dialin which includes the override + * value to override the bicarb concentrate mixing volume ki gain. + * @return TRUE if override successful, FALSE if not + *************************************************************************/ +BOOL testMixingControlBicarbVolControlKiGainOverride( MESSAGE_T *message ) +{ + BOOL result = f32Override( message, &mixingControlBicarbVolumeKiGain ); + + initializePIController( PI_CONTROLLER_ID_BICARB_VOL, 0.0F,\ + getBicarbKpGainCoefficient(), getBicarbKiGainCoefficient(),\ + MIN_BICARB_VOLUME_ML, MAX_BICARB_VOLUME_ML, FALSE, MIX_NO_FEED_FORWARD ); + + return result; +} + +/*********************************************************************//** + * @brief + * The testmixingControlAcidMoxVolControlKpGainOverride function sets the override value + * of the Kp gain coefficient for closed loop acid concentrate mixing volume control + * @details Inputs: mixingControlAcidMixVolumeKpGain + * @details Outputs: mixingControlAcidMixVolumeKpGain + * @param message Override message from Dialin which includes the override + * value to override the acid concentrate mixing volume kp gain. + * @return TRUE if override successful, FALSE if not + *************************************************************************/ +BOOL testMixingControlAcidVolControlKpGainOverride( MESSAGE_T *message ) +{ + BOOL result = f32Override( message, &mixingControlAcidVolumeKpGain ); + + initializePIController( PI_CONTROLLER_ID_ACID_VOL, 0.0F, \ + getAcidKpGainCoefficient(), getAcidKiGainCoefficient(),\ + MIN_ACID_VOLUME_ML, MAX_ACID_VOLUME_ML, FALSE, MIX_NO_FEED_FORWARD ); + + return result; +} + +/*********************************************************************//** + * @brief + * The testmixingControlAcidMixVolControlKiGainOverride function sets the override value + * of the Ki gain coefficient for closed loop acid concentrate mixing volume control + * @details Inputs: mixingControlAcidMixVolumeKiGain + * @details Outputs: mixingControlAcidMixVolumeKiGain + * @param message Override message from Dialin which includes the override + * value to override the bicarb concentrate mixing volume ki gain. + * @return TRUE if override successful, FALSE if not + *************************************************************************/ +BOOL testMixingControlAcidVolControlKiGainOverride( MESSAGE_T *message ) +{ + BOOL result = f32Override( message, &mixingControlAcidVolumeKiGain ); + + initializePIController( PI_CONTROLLER_ID_ACID_VOL, 0.0F, \ + getAcidKpGainCoefficient(), getAcidKiGainCoefficient(),\ + MIN_ACID_VOLUME_ML, MAX_ACID_VOLUME_ML, FALSE, MIX_NO_FEED_FORWARD ); + + return result; +} + +/*********************************************************************//** + * @brief + * The testMixingControlBicarbTargetConductivityOverride function sets the override value + * of target bicarb conductivity for closed loop control + * @details Inputs: mixingControlBicarbTargetConductivity + * @details Outputs: mixingControlBicarbTargetConductivity + * @param message Override message from Dialin which includes the override + * value to override the bicarb concentrate target conductivity. + * @return TRUE if override successful, FALSE if not + *************************************************************************/ +BOOL testMixingControlBicarbTargetConductivityOverride( MESSAGE_T *message ) +{ + BOOL result = f32Override( message, &mixingControlBicarbTargetConductivity ); + + return result; +} + +/*********************************************************************//** + * @brief + * The testMixingControlBicarbDeltaConductivityOverride function sets the override value + * of bicarb delta conductivity for closed loop control + * @details Inputs: mixingControlBicarbDeltaConductivity + * @details Outputs: mixingControlBicarbDeltaConductivity + * @param message Override message from Dialin which includes the override + * value to override the bicarb concentrate delta target conductivity. + * @return TRUE if override successful, FALSE if not + *************************************************************************/ +BOOL testMixingControlBicarbDeltaConductivityOverride( MESSAGE_T *message ) +{ + BOOL result = f32Override( message, &mixingControlBicarbDeltaConductivity ); + + return result; +} + +/*********************************************************************//** + * @brief + * The testmixingControlAcidBicarbTargetConductivityOverride function sets the override value + * of acid bicarb mix target conductivity for closed loop control + * @details Inputs: mixingControlAcidBicarbMixTargetConductivity + * @details Outputs: mixingControlAcidBicarbMixTargetConductivity + * @param message Override message from Dialin which includes the override + * value to override the acid bicarb mix target conductivity. + * @return TRUE if override successful, FALSE if not + *************************************************************************/ +BOOL testMixingControlDialysateTargetConductivityOverride( MESSAGE_T *message ) +{ + BOOL result = f32Override( message, &mixingControlDialysateTargetConductivity ); + + return result; +} + +/*********************************************************************//** + * @brief + * The testmixingControlAcidBicarbDeltaConductivityOverride function sets the override value + * of delta target conductivity for acid bicarb mix closed loop control + * @details Inputs: mixingControlDeltaConductivity + * + * @details Outputs: mixingControlDeltaConductivity + * @param message Override message from Dialin which includes the override + * value to override the acid bicarb mix target delta conductivity. + * @return TRUE if override successful, FALSE if not + *************************************************************************/ +BOOL testMixingControlDialysateDeltaConductivityOverride( MESSAGE_T *message ) +{ + BOOL result = f32Override( message, &mixingControlDialysateDeltaConductivity ); + + return result; +} + +/*********************************************************************//** + * @brief + * The testmixingControlBicarbMixControlIntervalOverride function sets the override value + * of bicarb mix control interval + * @details Inputs: mixingControlBicarbMixControlInterval + * @details Outputs: mixingControlBicarbMixControlInterval + * @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 testMixingControlBicarbControlIntervalOverride( MESSAGE_T *message ) +{ + BOOL result = u32Override( message, &mixingControlBicarbControlInterval, 0, BICARB_MIX_CONTROL_INTERVAL ); + + return result; +} + +/*********************************************************************//** + * @brief + * The testmixingControlAcidMixControlIntervalOverride function sets the override value + * of acid mix control interval + * @details Inputs: mixingControlAcidMixControlInterval + * @details Outputs: mixingControlAcidMixControlInterval + * @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 testMixingControlAcidControlIntervalOverride( MESSAGE_T *message ) +{ + BOOL result = u32Override( message, &mixingControlAcidControlInterval, 0, BICARB_MIX_CONTROL_INTERVAL ); + + return result; +} + +/*********************************************************************//** + * @brief + * The testmixingControlStdMixingBCVolumeOverride function sets the override value + * of acid mix control interval + * @details Inputs: mixingControlStdMixingBCVolume + * @details Outputs: mixingControlStdMixingBCVolume + * @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 testMixingControlStdMixingBCVolumeOverride( MESSAGE_T *message ) +{ + BOOL result = f32Override( message, &mixingControlStdMixingBCVolume ); + + return result; +} + +/*********************************************************************//** + * @brief + * The testmixingControlTargetAdjNASettingOverride function sets the override value + * of acid mix control interval + * @details Inputs: mixingControlTargetAdjNaSettings + * @details Outputs: mixingControlTargetAdjNaSettings + * @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 testMixingControlTargetAdjNASettingOverride( MESSAGE_T *message ) +{ + BOOL result = f32Override( message, &mixingControlTargetAdjNaSettings ); + + return result; +} + +/*********************************************************************//** + * @brief + * The testmixingControlAcidMixControlIntervalOverride function sets the override value + * of acid mix control interval + * @details Inputs: mixingControlTargetAdjBicarbSettings + * @details Outputs: mixingControlTargetAdjBicarbSettings + * @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 testMixingControlTargetAdjBicarbSettingOverride( MESSAGE_T *message ) +{ + BOOL result = f32Override( message, &mixingControlTargetAdjBicarbSettings ); + + return result; +} +/**@}*/ Index: firmware/App/Controllers/MixingControl.h =================================================================== diff -u --- firmware/App/Controllers/MixingControl.h (revision 0) +++ firmware/App/Controllers/MixingControl.h (revision cd1161514dbaff9e5b222931fff99618e39fd7ec) @@ -0,0 +1,96 @@ +/************************************************************************** +* +* Copyright (c) 2025-2026 Diality Inc. - All Rights Reserved. +* +* THIS CODE MAY NOT BE COPIED OR REPRODUCED IN ANY FORM, IN PART OR IN +* WHOLE, WITHOUT THE EXPLICIT PERMISSION OF THE COPYRIGHT OWNER. +* +* @file MixingControl.h +* +* @author (last) Sameer Kalliadan Poyil +* @date (last) 30-Apr-2026 +* +* @author (original) Vinayakam Mani +* @date (original) 19-Nov-2025 +* +***************************************************************************/ + +#ifndef __MIXING_CONTROL_H__ +#define __MIXING_CONTROL_H__ + +#include "PIControllers.h" +#include "DDCommon.h" +#include "DDDefs.h" + +/** + * @defgroup MixingControl MixingControl + * @brief MixingControl unit. Performs dry bicarbonate Dialysate Composition acid and bicarb mixing + * via a PI control state machine. + * + * @addtogroup MixingControl + * @{ + */ + +// ********** public definitions ********** + +#pragma pack(push, 1) +/// mixing control data structure +typedef struct +{ + U32 bicarbMixingState; + U32 bicarbControlInterval; + U32 acidMixingState; + U32 acidControlInterval; + F32 bicarbVolume; ///< Mixing control bicarb mix volume + F32 acidVolume; ///< Mixing control acid mix volume + // 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 + F32 bicarbKPgain; ///< Mixing control bicarb kp gain + F32 bicarbKIgain; ///< Mixing control bicarb ki gain + F32 acidKPgain; ///< Mixing control acid kp gain + F32 aciKIgain; ///< Mixing control acid ki gain + } MIXING_CONTROL_DATA_T; + +#pragma pack(pop) + +// ********** public function prototypes ********** + +#if 0 +void initDryMixingControl( void ); +void transitionToDryMixingControl( void ); +void execDryBicart( void ); +#endif +void execDialysateCompositionMixingController( void ); + +F32 getBicarbMixVol( void ); +F32 getAcidMixVol( void ); + +BOOL testMixingControlDataPublishIntervalOverride( MESSAGE_T *message ); + +BOOL testMixingControlAcidVolumeOverride( MESSAGE_T *message ); +BOOL testMixingControlBicarbVolumeOverride( MESSAGE_T *message ); + +BOOL testMixingControlBicarbVolControlKpGainOverride( MESSAGE_T *message ); +BOOL testMixingControlBicarbVolControlKiGainOverride( MESSAGE_T *message ); + + +BOOL testMixingControlAcidVolControlKpGainOverride( MESSAGE_T *message ); +BOOL testMixingControlAcidVolControlKiGainOverride( MESSAGE_T *message ); + +BOOL testMixingControlBicarbTargetConductivityOverride( MESSAGE_T *message ); +BOOL testMixingControlBicarbDeltaConductivityOverride( MESSAGE_T *message ); + +BOOL testMixingControlDialysateDeltaConductivityOverride( MESSAGE_T *message ); +BOOL testMixingControlDialysateTargetConductivityOverride( MESSAGE_T *message ); + +BOOL testMixingControlBicarbControlIntervalOverride( MESSAGE_T *message ); +BOOL testMixingControlAcidControlIntervalOverride( MESSAGE_T *message ); + +BOOL testMixingControlStdMixingBCVolumeOverride( MESSAGE_T *message ); +BOOL testMixingControlTargetAdjNASettingOverride( MESSAGE_T *message ); +BOOL testMixingControlTargetAdjBicarbSettingOverride( MESSAGE_T *message ); + +/**@}*/ + +#endif // __MIXING_CONTROL_H__ Index: firmware/App/Services/Messaging.c =================================================================== diff -u -r5f1b50a1d9a7bd6ea17bb666e28ccfeafe56432c -rcd1161514dbaff9e5b222931fff99618e39fd7ec --- firmware/App/Services/Messaging.c (.../Messaging.c) (revision 5f1b50a1d9a7bd6ea17bb666e28ccfeafe56432c) +++ firmware/App/Services/Messaging.c (.../Messaging.c) (revision cd1161514dbaff9e5b222931fff99618e39fd7ec) @@ -38,6 +38,7 @@ #include "Level.h" #include "Messaging.h" #include "MessagePayloads.h" +#include "MixingControl.h" #include "ModeGenDialysate.h" #include "ModeGenPermeate.h" #include "ModeGenPermeateDefeatured.h" @@ -277,10 +278,10 @@ { MSG_ID_FP_DEF_PRE_GEN_PUBLISH_INTERVAL_OVERRIDE_REQUEST, &testPreGenPermeateDefDataPublishIntervalOverride}, { MSG_ID_FP_DEF_GEN_PUBLISH_INTERVAL_OVERRIDE_REQUEST, &testGenPermeateDefDataPublishIntervalOverride}, { MSG_ID_FP_DEF_STATUS_REQUEST, &testGetFPDefeaturedStatus }, - { MSG_ID_DD_BICARB_MIX_VOL_CONTROL_KP_GAIN_COEFF_OVERRIDE_REQUEST, &testDryBiCartBicarbMixVolControlKiGainOverride }, - { MSG_ID_DD_BICARB_MIX_VOL_CONTROL_KI_GAIN_COEFF_OVERRIDE_REQUEST, &testDryBiCartAcidMixVolControlKpGainOverride }, - { MSG_ID_DD_ACID_MIX_VOL_CONTROL_KP_GAIN_COEFF_OVERRIDE_REQUEST, &testDryBiCartAcidMixVolControlKpGainOverride }, - { MSG_ID_DD_ACID_MIX_VOL_CONTROL_KI_GAIN_COEFF_OVERRIDE_REQUEST, &testDryBiCartAcidMixVolControlKiGainOverride }, + { MSG_ID_DD_BICARB_MIX_VOL_CONTROL_KP_GAIN_COEFF_OVERRIDE_REQUEST, &testMixingControlBicarbVolControlKiGainOverride }, + { MSG_ID_DD_BICARB_MIX_VOL_CONTROL_KI_GAIN_COEFF_OVERRIDE_REQUEST, &testMixingControlBicarbVolControlKpGainOverride }, + { MSG_ID_DD_ACID_MIX_VOL_CONTROL_KP_GAIN_COEFF_OVERRIDE_REQUEST, &testMixingControlAcidVolControlKpGainOverride }, + { MSG_ID_DD_ACID_MIX_VOL_CONTROL_KI_GAIN_COEFF_OVERRIDE_REQUEST, &testMixingControlAcidVolControlKiGainOverride }, { MSG_ID_DD_BICART_UPPER_PRESSURE_OVERRIDE_REQUEST, &testDryBiCartUpperCartPressureOverride }, { MSG_ID_DD_BICART_LOWER_PRESSURE_OVERRIDE_REQUEST, &testDryBiCartLowerCartPressureOverride } , { MSG_ID_FP_SET_OPERATION_SUB_MODE_REQUEST, &testSetFPOperationSubMode },