Index: firmware/App/Controllers/DGInterface.c =================================================================== diff -u -r1a685471524555a374854c0c9ec8e208e71fe2df -raeb1dea9ea10fcc70ae66023a87b565f29924c07 --- firmware/App/Controllers/DGInterface.c (.../DGInterface.c) (revision 1a685471524555a374854c0c9ec8e208e71fe2df) +++ firmware/App/Controllers/DGInterface.c (.../DGInterface.c) (revision aeb1dea9ea10fcc70ae66023a87b565f29924c07) @@ -32,7 +32,10 @@ #define START_DG_CMD TRUE ///< Parameter for DG start/stop command function. True = start. #define STOP_DG_CMD FALSE ///< Parameter for DG start/stop command function. False = stop. -#define RESERVOIR_SETTLE_TIME_MS 5000 ///< Time (in ms) allotted for reservoir to settle (after fill, before drain). +#define RESERVOIR_SETTLE_TIME_MS 5000 ///< Time (in ms) allotted for reservoir to settle (after fill, before drain). + +#define SIZE_OF_SMALL_LOAD_CELL_AVG 8 ///< Small load cell moving average has 8 samples. +#define SIZE_OF_LARGE_LOAD_CELL_AVG 32 ///< Large load cell moving average has 32 samples. /// States of the treatment reservoir management state machine. typedef enum TreatmentReservoirMgmt_States @@ -51,39 +54,56 @@ // ********** private data ********** // DG status -static DG_OP_MODE_T dgCurrentOpMode = DG_MODE_INIT; ///< Current DG operation mode. -static U32 dgSubMode = 0; ///< Current state (sub-mode) of current DG operation mode. -static BOOL dgStarted = FALSE; ///< Flag indicates whether we've commanded the DG to start or stop. -static BOOL dgTrimmerHeaterOn = FALSE; ///< Flag indicates whether we've commanded the DG to start or stop the trimmer heater. -static BOOL dgWaterSampled = FALSE; ///< Flag indicates whether we've commanded the DG to sample water. +static DG_OP_MODE_T dgCurrentOpMode = DG_MODE_INIT; ///< Current DG operation mode. +static U32 dgSubMode = 0; ///< Current state (sub-mode) of current DG operation mode. +static BOOL dgStarted = FALSE; ///< Flag indicates whether we've commanded the DG to start or stop. +static BOOL dgTrimmerHeaterOn = FALSE; ///< Flag indicates whether we've commanded the DG to start or stop the trimmer heater. +static BOOL dgWaterSampled = FALSE; ///< Flag indicates whether we've commanded the DG to sample water. -// state machine states -static TREATMENT_RESERVOIR_MGMT_STATE_T currentTrtResMgmtState = TREATMENT_RESERVOIR_MGMT_START_STATE; ///< Current state of treatment mode reservoir management. -static U32 resMgmtTimer = 0; ///< used for keeping state time. +// state machine states +/// Current state of treatment mode reservoir management. +static TREATMENT_RESERVOIR_MGMT_STATE_T currentTrtResMgmtState = TREATMENT_RESERVOIR_MGMT_START_STATE; +static U32 resMgmtTimer = 0; ///< used for keeping state time. -// DG sensor data -static F32 dgPressures[ NUM_OF_DG_PRESSURE_SENSORS ]; ///< Latest pressures reported by the DG. -static F32 dgDialysateTemp = 0.0; ///< Dialysate temperature reported by the DG. -static F32 dgRedundantDialysateTemp = 0.0; ///< Redundant dialysate temperature reported by the DG. -static F32 dgPrimaryTempSet = 0.0; ///< Primary heater target temperature commanded. -static F32 dgPrimaryTemp = 0.0; ///< Latest RO water temperature reported by the DG. -static F32 dgTrimmerTempSet = 0.0; ///< Trimmer heater target temperature commanded. -static F32 dgTrimmerTemp = 0.0; ///< Latest dialysate temperature reported by the DG. +// DG sensor data +static F32 dgPressures[ NUM_OF_DG_PRESSURE_SENSORS ]; ///< Latest pressures reported by the DG. +static F32 dgDialysateTemp = 0.0; ///< Dialysate temperature reported by the DG. +static F32 dgRedundantDialysateTemp = 0.0; ///< Redundant dialysate temperature reported by the DG. +static F32 dgPrimaryTempSet = 0.0; ///< Primary heater target temperature commanded. +static F32 dgPrimaryTemp = 0.0; ///< Latest RO water temperature reported by the DG. +static F32 dgTrimmerTempSet = 0.0; ///< Trimmer heater target temperature commanded. +static F32 dgTrimmerTemp = 0.0; ///< Latest dialysate temperature reported by the DG. +/// Measured weight from load cells. +static OVERRIDE_F32_T loadCellWeightInGrams[ NUM_OF_LOAD_CELLS ]; +/// Filtered (8 sample) weight of reservoirs. +static F32 smFilteredReservoirWeightInGrams[ NUM_OF_DG_RESERVOIRS ]; +/// Filtered (32 sample) weight of reservoirs. +static F32 lgFilteredReservoirWeightInGrams[ NUM_OF_DG_RESERVOIRS ]; +// load cell filtering data +/// holds load cell samples for small load cell moving average +static F32 smLoadCellReadings[ NUM_OF_DG_RESERVOIRS ][ SIZE_OF_SMALL_LOAD_CELL_AVG ]; +static U32 smLoadCellReadingsIdx = 0; ///< index for next sample in small load cell rolling average sample array +static F32 smLoadCellReadingsTotal[ NUM_OF_DG_RESERVOIRS ]; ///< rolling total - used to calc small load cell moving average +/// holds load cell samples for large load cell moving average +static F32 lgLoadCellReadings[ NUM_OF_DG_RESERVOIRS ][ SIZE_OF_LARGE_LOAD_CELL_AVG ]; +static U32 lgLoadCellReadingsIdx = 0; ///< index for next sample in large load cell rolling average sample array +static F32 lgLoadCellReadingsTotal[ NUM_OF_DG_RESERVOIRS ]; ///< rolling total - used to calc large load cell moving average + // DG pumps data -static F32 dgROPumpFlowRateMlMin = 0.0; ///< Latest RO water flow rate reported by the DG. -static U32 dgROPumpPressureSetPtPSI = 0; ///< Latest RO pump target pressure reported by the DG. -static U32 dgDrainPumpSpeedSetPtRPM = 0; ///< Latest Drain pump target speed reported by the DG. +static F32 dgROPumpFlowRateMlMin = 0.0; ///< Latest RO water flow rate reported by the DG. +static U32 dgROPumpPressureSetPtPSI = 0; ///< Latest RO pump target pressure reported by the DG. +static U32 dgDrainPumpSpeedSetPtRPM = 0; ///< Latest Drain pump target speed reported by the DG. // reservoir data -static DG_RESERVOIR_ID_T dgActiveReservoir = DG_RESERVOIR_2; ///< Latest active reservoir reported by the DG. -static DG_RESERVOIR_ID_T dgActiveReservoirSet = DG_RESERVOIR_2; ///< Active reservoir commanded. -static U32 dgReservoirFillVolumeTarget = 0; ///< Latest fill-to volume reported by the DG. -static U32 dgReservoirFillVolumeTargetSet = 0; ///< Fill-to volume commanded. -static U32 dgReservoirDrainVolumeTarget = 0; ///< Latest drain-to volume reported by the DG. -static U32 dgReservoirDrainVolumeTargetSet = 0; ///< Drain-to volume commanded. -static U32 resUseTimer = 0; ///< used to track time pumping from active reservoir (for volume used calculation). -static F32 resUseVolumeMl = 0.0; ///< Accumulated volume used from active reservoir. +static DG_RESERVOIR_ID_T dgActiveReservoir = DG_RESERVOIR_2; ///< Latest active reservoir reported by the DG. +static DG_RESERVOIR_ID_T dgActiveReservoirSet = DG_RESERVOIR_2; ///< Active reservoir commanded. +static U32 dgReservoirFillVolumeTarget = 0; ///< Latest fill-to volume reported by the DG. +static U32 dgReservoirFillVolumeTargetSet = 0; ///< Fill-to volume commanded. +static U32 dgReservoirDrainVolumeTarget = 0; ///< Latest drain-to volume reported by the DG. +static U32 dgReservoirDrainVolumeTargetSet = 0; ///< Drain-to volume commanded. +static U32 resUseTimer = 0; ///< used to track time pumping from active reservoir (for volume used calculation). +static F32 resUseVolumeMl = 0.0; ///< Accumulated volume used from active reservoir. // ********** private function prototypes ********** @@ -97,6 +117,8 @@ *************************************************************************/ void initDGInterface( void ) { + U32 i, j; + dgStarted = FALSE; dgTrimmerHeaterOn = FALSE; dgWaterSampled = FALSE; @@ -105,8 +127,50 @@ dgActiveReservoirSet = DG_RESERVOIR_2; dgReservoirFillVolumeTargetSet = 0; dgReservoirDrainVolumeTargetSet = 0; -} + + // initialize load cell weights + for ( i = 0; i < NUM_OF_LOAD_CELLS; i++ ) + { + loadCellWeightInGrams[ i ].data = 0.0; + loadCellWeightInGrams[ i ].ovInitData = 0.0; + loadCellWeightInGrams[ i ].ovData = 0.0; + loadCellWeightInGrams[ i ].override = 0; + } + // initialize reservoirs weights + for ( i = 0; i < NUM_OF_DG_RESERVOIRS; i++ ) + { + smFilteredReservoirWeightInGrams[ i ] = 0.0; + lgFilteredReservoirWeightInGrams[ i ] = 0.0; + for ( j = 0; j < SIZE_OF_SMALL_LOAD_CELL_AVG; j++ ) + { + smLoadCellReadings[ i ][ j ] = 0.0; + } + for ( j = 0; j < SIZE_OF_LARGE_LOAD_CELL_AVG; j++ ) + { + lgLoadCellReadings[ i ][ j ] = 0.0; + } + } + smLoadCellReadingsIdx = 0; + smLoadCellReadingsTotal[ DG_RESERVOIR_1 ] = 0.0; + smLoadCellReadingsTotal[ DG_RESERVOIR_2 ] = 0.0; + lgLoadCellReadingsIdx = 0; + lgLoadCellReadingsTotal[ DG_RESERVOIR_1 ] = 0.0; + lgLoadCellReadingsTotal[ DG_RESERVOIR_2 ] = 0.0; +} +/*********************************************************************//** + * @brief + * The execDGInterfaceMonitor function executes the DG Interface monitoring + * function. Ensures DG is sending fresh data in a timely manner. + * @details Inputs: TBD + * @details Outputs: TBD + * @return none + *************************************************************************/ +void execDGInterfaceMonitor( void ) +{ + // TODO - make sure DG sensor/state data is coming in timely manner (e.g. load cells s/b every 100 ms) +} + /*********************************************************************//** * @brief * The initTreatmentReservoirMgmt function initializes the treatment reservoir @@ -287,6 +351,20 @@ DG_RESERVOIR_ID_T getDGActiveReservoir( void ) { return dgActiveReservoirSet; +} + +/*********************************************************************//** + * @brief + * The getDGInactiveReservoir function gets the currently inactive reservoir. + * @details Inputs: dgActiveReservoirSet + * @details Outputs: none + * @return Currently commanded inactive reservoir. + *************************************************************************/ +DG_RESERVOIR_ID_T getDGInactiveReservoir( void ) +{ + DG_RESERVOIR_ID_T inactiveRes = ( DG_RESERVOIR_2 == dgActiveReservoirSet ? DG_RESERVOIR_1 : DG_RESERVOIR_2 ); + + return inactiveRes; } /*********************************************************************//** @@ -359,6 +437,79 @@ return result; } +/*********************************************************************//** + * @brief + * The getLoadCellWeightInGrams function gets the load cell weight. + * @details Inputs: loadCellWeightInGrams + * @details Outputs: none + * @param loadCellID ID of load cell to get + * @return the current load cell weight in grams + *************************************************************************/ +F32 getLoadCellWeightInGrams( LOAD_CELL_T loadCellID ) +{ + F32 result = 0.0; + + if ( loadCellID < NUM_OF_LOAD_CELLS ) + { + if ( OVERRIDE_KEY == loadCellWeightInGrams[ loadCellID ].override ) + { + result = loadCellWeightInGrams[ loadCellID ].ovData; + } + else + { + result = loadCellWeightInGrams[ loadCellID ].data; + } + } + else + { + activateAlarmNoData( ALARM_ID_HD_SOFTWARE_FAULT ); + } + + return result; +} + +/*********************************************************************//** + * @brief + * The getReservoirWeightSmallFilter function gets the load cell weight + * of the given reservoir after large (8 sample) filter applied. + * @details Inputs: lgFilteredReservoirWeightInGrams[] + * @details Outputs: none + * @param resID ID of reservoir to get filtered weight for + * @return the current filtered weight of the given reservoir in grams + *************************************************************************/ +F32 getReservoirWeightSmallFilter( DG_RESERVOIR_ID_T resID ) +{ + F32 result = 0.0; + + if ( resID < NUM_OF_DG_RESERVOIRS ) + { + result = smFilteredReservoirWeightInGrams[ resID ]; + } + + return result; +} + +/*********************************************************************//** + * @brief + * The getReservoirWeightLargeFilter function gets the load cell weight + * of the given reservoir after large (32 sample) filter applied. + * @details Inputs: lgFilteredReservoirWeightInGrams[] + * @details Outputs: none + * @param resID ID of reservoir to get filtered weight for + * @return the current filtered weight of the given reservoir in grams + *************************************************************************/ +F32 getReservoirWeightLargeFilter( DG_RESERVOIR_ID_T resID ) +{ + F32 result = 0.0; + + if ( resID < NUM_OF_DG_RESERVOIRS ) + { + result = lgFilteredReservoirWeightInGrams[ resID ]; + } + + return result; +} + /*********************************************************************//** * @brief * The setDGOpMode function sets the latest DG operating mode reported by @@ -486,6 +637,48 @@ dgDrainPumpSpeedSetPtRPM = rpmSetPt; } +/*********************************************************************//** + * @brief + * The setNewLoadCellReadings function sets the latest DG reservoir load cell + * readings sent by the DG (in g or mL). New readings are expected once + * every 100 ms. + * @details Inputs: none + * @details Outputs: loadCellWeightInGrams[], smFilteredReservoirWeightInGrams[], + * lgFilteredReservoirWeightInGrams[] + * @param res1Primary New weight from primary load cell of reservoir 1 + * @param res1Backup New weight from backup load cell of reservoir 1 + * @param res2Primary New weight from primary load cell of reservoir 2 + * @param res2Backup New weight from backup load cell of reservoir 2 + * @return none + *************************************************************************/ +void setNewLoadCellReadings( F32 res1Primary, F32 res1Backup, F32 res2Primary, F32 res2Backup ) +{ + loadCellWeightInGrams[ LOAD_CELL_RESERVOIR_1_PRIMARY ].data = res1Primary; + loadCellWeightInGrams[ LOAD_CELL_RESERVOIR_1_BACKUP ].data = res1Backup; + loadCellWeightInGrams[ LOAD_CELL_RESERVOIR_2_PRIMARY ].data = res2Primary; + loadCellWeightInGrams[ LOAD_CELL_RESERVOIR_2_BACKUP ].data = res2Backup; + + // feed new weight samples into filters and update moving averages + smLoadCellReadingsTotal[ DG_RESERVOIR_1 ] -= smLoadCellReadings[ DG_RESERVOIR_1 ][ smLoadCellReadingsIdx ]; + lgLoadCellReadingsTotal[ DG_RESERVOIR_1 ] -= lgLoadCellReadings[ DG_RESERVOIR_1 ][ lgLoadCellReadingsIdx ]; + smLoadCellReadingsTotal[ DG_RESERVOIR_2 ] -= smLoadCellReadings[ DG_RESERVOIR_2 ][ smLoadCellReadingsIdx ]; + lgLoadCellReadingsTotal[ DG_RESERVOIR_2 ] -= lgLoadCellReadings[ DG_RESERVOIR_2 ][ lgLoadCellReadingsIdx ]; + smLoadCellReadings[ DG_RESERVOIR_1 ][ smLoadCellReadingsIdx ] = res1Primary; + lgLoadCellReadings[ DG_RESERVOIR_1 ][ lgLoadCellReadingsIdx ] = res1Primary; + smLoadCellReadings[ DG_RESERVOIR_2 ][ smLoadCellReadingsIdx ] = res2Primary; + lgLoadCellReadings[ DG_RESERVOIR_2 ][ lgLoadCellReadingsIdx ] = res2Primary; + smLoadCellReadingsTotal[ DG_RESERVOIR_1 ] += res1Primary; + lgLoadCellReadingsTotal[ DG_RESERVOIR_1 ] += res1Primary; + smLoadCellReadingsTotal[ DG_RESERVOIR_2 ] += res2Primary; + lgLoadCellReadingsTotal[ DG_RESERVOIR_2 ] += res2Primary; + smFilteredReservoirWeightInGrams[ DG_RESERVOIR_1 ] = smLoadCellReadingsTotal[ DG_RESERVOIR_1 ] / (F32)SIZE_OF_SMALL_LOAD_CELL_AVG; + lgFilteredReservoirWeightInGrams[ DG_RESERVOIR_1 ] = lgLoadCellReadingsTotal[ DG_RESERVOIR_1 ] / (F32)SIZE_OF_LARGE_LOAD_CELL_AVG; + smFilteredReservoirWeightInGrams[ DG_RESERVOIR_2 ] = smLoadCellReadingsTotal[ DG_RESERVOIR_2 ] / (F32)SIZE_OF_SMALL_LOAD_CELL_AVG; + lgFilteredReservoirWeightInGrams[ DG_RESERVOIR_2 ] = lgLoadCellReadingsTotal[ DG_RESERVOIR_2 ] / (F32)SIZE_OF_LARGE_LOAD_CELL_AVG; + smLoadCellReadingsIdx = INC_WRAP( smLoadCellReadingsIdx, 0, SIZE_OF_SMALL_LOAD_CELL_AVG - 1 ); + lgLoadCellReadingsIdx = INC_WRAP( lgLoadCellReadingsIdx, 0, SIZE_OF_LARGE_LOAD_CELL_AVG - 1 ); +} + /*********************************************************************//** * @brief * The cmdSetDGDialysateTargetTemps function sends a target dialysate @@ -621,5 +814,64 @@ dgWaterSampled = TRUE; sendDGSampleWaterCommand(); } - + + +/************************************************************************* + * TEST SUPPORT FUNCTIONS + *************************************************************************/ + + +/*********************************************************************//** + * @brief + * The testSetDialOutLoadCellWeightOverride function overrides the value of the + * load cell sensor with a given weight (in grams). + * @details Inputs: loadCellWeightInGrams[] + * @details Outputs: loadCellWeightInGrams[] + * @param sensor ID of load cell sensor to override weight for + * @param value override weight (in grams) for the given sensor + * @return TRUE if override successful, FALSE if not + *************************************************************************/ +BOOL testSetDialOutLoadCellWeightOverride( U32 sensor, F32 value ) +{ + BOOL result = FALSE; + + if ( sensor < NUM_OF_LOAD_CELLS ) + { + if ( TRUE == isTestingActivated() ) + { + result = TRUE; + loadCellWeightInGrams[ sensor ].ovData = value; + loadCellWeightInGrams[ sensor ].override = OVERRIDE_KEY; + } + } + + return result; +} + +/*********************************************************************//** + * @brief + * The testResetDialOutLoadCellWeightOverride function resets the override of the + * load cell sensor. + * @details Inputs: loadCellWeightInGrams[] + * @details Outputs: loadCellWeightInGrams[] + * @param sensor ID of load cell sensor to override weight for + * @return TRUE if reset successful, FALSE if not + *************************************************************************/ +BOOL testResetDialOutLoadCellWeightOverride( U32 sensor ) +{ + BOOL result = FALSE; + + if ( sensor < NUM_OF_LOAD_CELLS ) + { + if ( TRUE == isTestingActivated() ) + { + result = TRUE; + loadCellWeightInGrams[ sensor ].override = OVERRIDE_RESET; + loadCellWeightInGrams[ sensor ].ovData = loadCellWeightInGrams[ sensor ].ovInitData; + } + } + + return result; +} + /**@}*/ Index: firmware/App/Controllers/DGInterface.h =================================================================== diff -u -rb01542f8e4ef5a29e9b08fc0d465478de516bf02 -raeb1dea9ea10fcc70ae66023a87b565f29924c07 --- firmware/App/Controllers/DGInterface.h (.../DGInterface.h) (revision b01542f8e4ef5a29e9b08fc0d465478de516bf02) +++ firmware/App/Controllers/DGInterface.h (.../DGInterface.h) (revision aeb1dea9ea10fcc70ae66023a87b565f29924c07) @@ -32,29 +32,39 @@ // ********** public definitions ********** -#define DRAIN_RESERVOIR_TO_VOLUME_ML 200 ///< Drain reservoir to this volume (in mL) during treatment. +#define DRAIN_RESERVOIR_TO_VOLUME_ML 200 ///< Drain reservoir to this volume (in mL) during treatment. #ifndef V1_5_SYSTEM -#define FILL_RESERVOIR_TO_VOLUME_ML 1700 ///< Fill reservoir to this volume (in mL) during treatment. +#define FILL_RESERVOIR_TO_VOLUME_ML 1700 ///< Fill reservoir to this volume (in mL) during treatment. #else -#define FILL_RESERVOIR_TO_VOLUME_ML 1300 ///< Fill reservoir to this volume (in mL) during treatment. +#define FILL_RESERVOIR_TO_VOLUME_ML 1300 ///< Fill reservoir to this volume (in mL) during treatment. #endif +/// Enumeration of load cell sensors. +typedef enum Load_Cells +{ + LOAD_CELL_RESERVOIR_1_PRIMARY = 0, ///< Primary load cell for reservoir 1. + LOAD_CELL_RESERVOIR_1_BACKUP, ///< Backup load cell for reservoir 1. + LOAD_CELL_RESERVOIR_2_PRIMARY, ///< Primary load cell for reservoir 2. + LOAD_CELL_RESERVOIR_2_BACKUP, ///< Backup load cell for reservoir 2. + NUM_OF_LOAD_CELLS ///< Number of load cell sensors. +} LOAD_CELL_T; + /// Enumeration of DG reservoirs. typedef enum DG_Reservoirs { - DG_RESERVOIR_1 = 0, ///< Reservoir #1. - DG_RESERVOIR_2, ///< Reservoir #2. - NUM_OF_DG_RESERVOIRS ///< Number of reservoirs. + DG_RESERVOIR_1 = 0, ///< Reservoir #1. + DG_RESERVOIR_2, ///< Reservoir #2. + NUM_OF_DG_RESERVOIRS ///< Number of reservoirs. } DG_RESERVOIR_ID_T; /// Enumeration of DG pressure sensors. typedef enum DG_PressureSensors { - DG_PRESSURE_SENSOR_RO_PUMP_INLET = 0, ///< RO pump pressure sensor. - DG_PRESSURE_SENSOR_RO_PUMP_OUTLET, ///< RO pump pressure sensor. - DG_PRESSURE_SENSOR_DRAIN_PUMP_INLET, ///< drain pump inlet pressure. - DG_PRESSURE_SENSOR_DRAIN_PUMP_OUTLET, ///< drain pump outlet pressure. - NUM_OF_DG_PRESSURE_SENSORS ///< Number of pressure sensors. + DG_PRESSURE_SENSOR_RO_PUMP_INLET = 0, ///< RO pump pressure sensor. + DG_PRESSURE_SENSOR_RO_PUMP_OUTLET, ///< RO pump pressure sensor. + DG_PRESSURE_SENSOR_DRAIN_PUMP_INLET, ///< drain pump inlet pressure. + DG_PRESSURE_SENSOR_DRAIN_PUMP_OUTLET, ///< drain pump outlet pressure. + NUM_OF_DG_PRESSURE_SENSORS ///< Number of pressure sensors. } DG_PRESSURE_SENSORS_T; /// Payload record structure for an RO pump data message. @@ -108,17 +118,24 @@ // ********** public function prototypes ********** -void initDGInterface( void ); +void initDGInterface( void ); + +void execDGInterfaceMonitor( void ); + void initTreatmentReservoirMgmt( void ); void execTreatmentReservoirMgmt( void ); DG_OP_MODE_T getDGOpMode( void ); U32 getDGSubMode( void ); DG_RESERVOIR_ID_T getDGActiveReservoir( void ); +DG_RESERVOIR_ID_T getDGInactiveReservoir( void ); F32 getDGPressure( DG_PRESSURE_SENSORS_T sensorID ); U32 getDGROPumpPressureSetPt( void ); F32 getDGROPumpFlowRateMlMin( void ); U32 getDGDrainPumpRPMSetPt( void ); +F32 getLoadCellWeightInGrams( LOAD_CELL_T loadCellID ); +F32 getReservoirWeightSmallFilter( DG_RESERVOIR_ID_T resID ); +F32 getReservoirWeightLargeFilter( DG_RESERVOIR_ID_T resID ); void setDGOpMode( U32 opMode, U32 subMode ); void setDialysateTemperatureReadings( F32 temp1, F32 temp2 ); @@ -127,6 +144,7 @@ void setDGPressures( F32 roIn, F32 roOut, F32 drainIn, F32 drainOut ); void setDGROPumpData( U32 presSetPt, F32 flowRate ); void setDGDrainPumpData( U32 rpmSetPt ); +void setNewLoadCellReadings( F32 res1Primary, F32 res1Backup, F32 res2Primary, F32 res2Backup ); void cmdSetDGDialysateTargetTemps( F32 primaryHtrTemp, F32 trimmerHtrTemp ); void cmdStartDG( void ); @@ -138,6 +156,9 @@ void cmdStopDGTrimmerHeater( void ); void cmdDGSampleWater( void ); +BOOL testSetDialOutLoadCellWeightOverride( U32 sensor, F32 value ); +BOOL testResetDialOutLoadCellWeightOverride( U32 sensor ); + /**@}*/ #endif Index: firmware/App/Controllers/DialOutFlow.c =================================================================== diff -u -rb01542f8e4ef5a29e9b08fc0d465478de516bf02 -raeb1dea9ea10fcc70ae66023a87b565f29924c07 --- firmware/App/Controllers/DialOutFlow.c (.../DialOutFlow.c) (revision b01542f8e4ef5a29e9b08fc0d465478de516bf02) +++ firmware/App/Controllers/DialOutFlow.c (.../DialOutFlow.c) (revision aeb1dea9ea10fcc70ae66023a87b565f29924c07) @@ -137,7 +137,6 @@ static PUMP_CONTROL_MODE_T dialOutPumpControlMode = PUMP_CONTROL_MODE_CLOSED_LOOP; ///< Requested control mode for dialysate outlet pump (open or closed loop). static PUMP_CONTROL_MODE_T dialOutPumpControlModeSet = PUMP_CONTROL_MODE_CLOSED_LOOP; ///< Currently set control mode for dialysate outlet pump. -static OVERRIDE_F32_T loadCellWeightInGrams[ NUM_OF_LOAD_CELLS ]; ///< Measured weight from load cells. static OVERRIDE_U32_T dialOutDataPublishInterval = { DIAL_OUT_DATA_PUB_INTERVAL, DIAL_OUT_DATA_PUB_INTERVAL, DIAL_OUT_DATA_PUB_INTERVAL, 0 }; ///< Interval (in ms) at which to publish dialysate outlet data to CAN bus. static OVERRIDE_F32_T referenceUFVolumeInMl = { 0.0, 0.0, 0.0, 0 }; ///< Target ultrafiltration volume (in mL). static OVERRIDE_F32_T totalMeasuredUFVolumeInMl = { 0.0, 0.0, 0.0, 0 }; ///< Total measured ultrafiltration volume (in mL). @@ -208,12 +207,6 @@ dopLastMotorHallSensorCounts[ i ] = 0; } - // initialize load cell weights - for ( i = 0; i < NUM_OF_LOAD_CELLS; i++ ) - { - loadCellWeightInGrams[ i ].data = 0.0; - } - // initialize dialysate outlet flow PI controller initializePIController( PI_CONTROLLER_ID_ULTRAFILTRATION, MIN_DIAL_OUT_PUMP_PWM_DUTY_CYCLE, DOP_P_COEFFICIENT, DOP_I_COEFFICIENT, @@ -388,30 +381,6 @@ /*********************************************************************//** * @brief - * The setDialOutUFVolumes function sets the ultrafiltration reference and - * measured total volumes (in mL). - * @details Inputs: none - * @details Outputs: loadCellWeightInGrams[] - * @param res1Primary New weight from primary load cell of reservoir 1 - * @param res1Backup New weight from backup load cell of reservoir 1 - * @param res2Primary New weight from primary load cell of reservoir 2 - * @param res2Backup New weight from backup load cell of reservoir 2 - * @return TRUE if successful, FALSE if not - *************************************************************************/ -BOOL setNewLoadCellReadings( F32 res1Primary, F32 res1Backup, F32 res2Primary, F32 res2Backup ) -{ - BOOL result = TRUE; - - loadCellWeightInGrams[ LOAD_CELL_RESERVOIR_1_PRIMARY ].data = res1Primary; - loadCellWeightInGrams[ LOAD_CELL_RESERVOIR_1_BACKUP ].data = res1Backup; - loadCellWeightInGrams[ LOAD_CELL_RESERVOIR_2_PRIMARY ].data = res2Primary; - loadCellWeightInGrams[ LOAD_CELL_RESERVOIR_2_BACKUP ].data = res2Backup; - - return result; -} - -/*********************************************************************//** - * @brief * The execDialOutFlowMonitor function executes the dialysate outlet pump * and load cell sensor monitor. Checks are performed. Data is published * at appropriate interval. @@ -1015,37 +984,6 @@ /*********************************************************************//** * @brief - * The getLoadCellWeightInGrams function gets the load cell weight. - * @details Inputs: loadCellWeightInGrams - * @details Outputs: none - * @param loadCellID ID of load cell to get - * @return the current load cell weight in grams - *************************************************************************/ -F32 getLoadCellWeightInGrams( U32 loadCellID ) -{ - F32 result = 0.0; - - if ( loadCellID < NUM_OF_LOAD_CELLS ) - { - if ( OVERRIDE_KEY == loadCellWeightInGrams[ loadCellID ].override ) - { - result = loadCellWeightInGrams[ loadCellID ].ovData; - } - else - { - result = loadCellWeightInGrams[ loadCellID ].data; - } - } - else - { - activateAlarmNoData( ALARM_ID_HD_SOFTWARE_FAULT ); - } - - return result; -} - -/*********************************************************************//** - * @brief * The getTotalTargetDialOutUFVolumeInMl function gets the target UF volume. * @details Inputs: referenceUFVolumeInMl * @details Outputs: none @@ -1520,57 +1458,4 @@ return result; } -/*********************************************************************//** - * @brief - * The testSetDialOutLoadCellWeightOverride function overrides the value of the - * load cell sensor with a given weight (in grams). - * @details Inputs: loadCellWeightInGrams[] - * @details Outputs: loadCellWeightInGrams[] - * @param sensor ID of load cell sensor to override weight for - * @param value override weight (in grams) for the given sensor - * @return TRUE if override successful, FALSE if not - *************************************************************************/ -BOOL testSetDialOutLoadCellWeightOverride( U32 sensor, F32 value ) -{ - BOOL result = FALSE; - - if ( sensor < NUM_OF_LOAD_CELLS ) - { - if ( TRUE == isTestingActivated() ) - { - result = TRUE; - loadCellWeightInGrams[ sensor ].ovData = value; - loadCellWeightInGrams[ sensor ].override = OVERRIDE_KEY; - } - } - - return result; -} - -/*********************************************************************//** - * @brief - * The testResetDialOutLoadCellWeightOverride function resets the override of the - * load cell sensor. - * @details Inputs: loadCellWeightInGrams[] - * @details Outputs: loadCellWeightInGrams[] - * @param sensor ID of load cell sensor to override weight for - * @return TRUE if reset successful, FALSE if not - *************************************************************************/ -BOOL testResetDialOutLoadCellWeightOverride( U32 sensor ) -{ - BOOL result = FALSE; - - if ( sensor < NUM_OF_LOAD_CELLS ) - { - if ( TRUE == isTestingActivated() ) - { - result = TRUE; - loadCellWeightInGrams[ sensor ].override = OVERRIDE_RESET; - loadCellWeightInGrams[ sensor ].ovData = loadCellWeightInGrams[ sensor ].ovInitData; - } - } - - return result; -} - /**@}*/ Index: firmware/App/Controllers/DialOutFlow.h =================================================================== diff -u -r933a18d740285e70be9d00696ed0f5a5381bc8e4 -raeb1dea9ea10fcc70ae66023a87b565f29924c07 --- firmware/App/Controllers/DialOutFlow.h (.../DialOutFlow.h) (revision 933a18d740285e70be9d00696ed0f5a5381bc8e4) +++ firmware/App/Controllers/DialOutFlow.h (.../DialOutFlow.h) (revision aeb1dea9ea10fcc70ae66023a87b565f29924c07) @@ -32,16 +32,6 @@ // ********** public definitions ********** -/// Enumeration of load cell sensors. -typedef enum Load_Cells -{ - LOAD_CELL_RESERVOIR_1_PRIMARY = 0, ///< Primary load cell for reservoir 1. - LOAD_CELL_RESERVOIR_1_BACKUP, ///< Backup load cell for reservoir 1. - LOAD_CELL_RESERVOIR_2_PRIMARY, ///< Primary load cell for reservoir 2. - LOAD_CELL_RESERVOIR_2_BACKUP, ///< Backup load cell for reservoir 2. - NUM_OF_LOAD_CELLS ///< Number of load cell sensors. -} LOAD_CELL_T; - #pragma pack(push, 1) /// Dialysate outlet pump broadcast record @@ -81,15 +71,12 @@ BOOL homeDialOutPump( void ); BOOL isDialOutPumpRunning( void ); -BOOL setNewLoadCellReadings( F32 res1Primary, F32 res1Backup, F32 res2Primary, F32 res2Backup ); - // SELF_TEST_STATUS_T execDialOutFlowTest( void ); // TODO - implement later F32 getTotalTargetDialOutUFVolumeInMl( void ); F32 getTotalMeasuredUFVolumeInMl( void ); F32 getMeasuredDialOutPumpMCSpeed( void ); F32 getMeasuredDialOutPumpMCCurrent( void ); -F32 getLoadCellWeightInGrams( U32 loadCellID ); F32 getMeasuredDialOutPumpRotorSpeed( void ); F32 getMeasuredDialOutPumpSpeed( void ); @@ -108,8 +95,6 @@ BOOL testResetMeasuredDialOutPumpMCSpeedOverride( void ); BOOL testSetMeasuredDialOutPumpMCCurrentOverride( F32 value ); BOOL testResetMeasuredDialOutPumpMCCurrentOverride( void ); -BOOL testSetDialOutLoadCellWeightOverride( U32 sensor, F32 value ); -BOOL testResetDialOutLoadCellWeightOverride( U32 sensor ); /**@}*/ Index: firmware/App/Modes/Dialysis.c =================================================================== diff -u -r1a685471524555a374854c0c9ec8e208e71fe2df -raeb1dea9ea10fcc70ae66023a87b565f29924c07 --- firmware/App/Modes/Dialysis.c (.../Dialysis.c) (revision 1a685471524555a374854c0c9ec8e208e71fe2df) +++ firmware/App/Modes/Dialysis.c (.../Dialysis.c) (revision aeb1dea9ea10fcc70ae66023a87b565f29924c07) @@ -1126,18 +1126,8 @@ static void updateUFVolumes( void ) { DG_RESERVOIR_ID_T activeRes = getDGActiveReservoir(); - F32 latestResVolume; + F32 latestResVolume = getReservoirWeightSmallFilter( activeRes ); - // get volume of active reservoir - if ( DG_RESERVOIR_1 == activeRes ) - { - latestResVolume = getLoadCellWeightInGrams( LOAD_CELL_RESERVOIR_1_PRIMARY ); - } - else - { - latestResVolume = getLoadCellWeightInGrams( LOAD_CELL_RESERVOIR_2_PRIMARY ); - } - // calculate UF volumes and provide to dialysate outlet pump controller measUFVolume = measUFVolumeFromPriorReservoirs + ( latestResVolume - resStartVolume[ activeRes ] ); resFinalVolume[ activeRes ] = latestResVolume; @@ -1155,22 +1145,9 @@ *************************************************************************/ void setStartReservoirVolume( void ) { - DG_RESERVOIR_ID_T activeRes = getDGActiveReservoir(); - DG_RESERVOIR_ID_T inactiveRes; - F32 resVolume; + DG_RESERVOIR_ID_T inactiveRes = getDGInactiveReservoir(); + F32 resVolume = getReservoirWeightLargeFilter( inactiveRes ); - // get volume of inactive reservoir - if ( DG_RESERVOIR_2 == activeRes ) - { - inactiveRes = DG_RESERVOIR_1; - resVolume = getLoadCellWeightInGrams( LOAD_CELL_RESERVOIR_1_PRIMARY ); - } - else - { - inactiveRes = DG_RESERVOIR_2; - resVolume = getLoadCellWeightInGrams( LOAD_CELL_RESERVOIR_2_PRIMARY ); - } - // set starting baseline volume for next reservoir before we switch to it resStartVolume[ inactiveRes ] = resVolume; } @@ -1204,22 +1181,9 @@ *************************************************************************/ void setFinalReservoirVolume( void ) { - DG_RESERVOIR_ID_T activeRes = getDGActiveReservoir(); - DG_RESERVOIR_ID_T inactiveRes; - F32 resVolume; + DG_RESERVOIR_ID_T inactiveRes = getDGInactiveReservoir(); + F32 resVolume = getReservoirWeightLargeFilter( inactiveRes ); - // get volume of inactive reservoir - if ( DG_RESERVOIR_2 == activeRes ) - { - inactiveRes = DG_RESERVOIR_1; - resVolume = getLoadCellWeightInGrams( LOAD_CELL_RESERVOIR_1_PRIMARY ); - } - else - { - inactiveRes = DG_RESERVOIR_2; - resVolume = getLoadCellWeightInGrams( LOAD_CELL_RESERVOIR_2_PRIMARY ); - } - // update UF volume from prior reservoirs per final res volume for last reservoir a bit after we've switched and reservoir has settled measUFVolumeFromPriorReservoirs -= ( resFinalVolume[ inactiveRes ] - resStartVolume[ inactiveRes ] ); resFinalVolume[ inactiveRes ] = resVolume; Index: firmware/App/Services/SystemCommMessages.c =================================================================== diff -u -rb01542f8e4ef5a29e9b08fc0d465478de516bf02 -raeb1dea9ea10fcc70ae66023a87b565f29924c07 --- firmware/App/Services/SystemCommMessages.c (.../SystemCommMessages.c) (revision b01542f8e4ef5a29e9b08fc0d465478de516bf02) +++ firmware/App/Services/SystemCommMessages.c (.../SystemCommMessages.c) (revision aeb1dea9ea10fcc70ae66023a87b565f29924c07) @@ -1313,14 +1313,12 @@ *************************************************************************/ void handleLoadCellReadingsFromDG( MESSAGE_T *message ) { - BOOL result = FALSE; - if ( message->hdr.payloadLen == sizeof(LOAD_CELL_READINGS_PAYLOAD_T) ) { LOAD_CELL_READINGS_PAYLOAD_T payload; memcpy( &payload, message->payload, sizeof(LOAD_CELL_READINGS_PAYLOAD_T) ); - result = setNewLoadCellReadings( payload.res1PrimaryLoadCell, payload.res1BackupLoadCell, payload.res2PrimaryLoadCell, payload.res2BackupLoadCell ); + setNewLoadCellReadings( payload.res1PrimaryLoadCell, payload.res1BackupLoadCell, payload.res2PrimaryLoadCell, payload.res2BackupLoadCell ); } // TODO - what to do if invalid payload length? // TODO - how to know if DG stops sending these? @@ -1921,10 +1919,6 @@ setDGOpMode( mode, subMode ); checkInFromDG(); // TODO - here until we implement DG check-in w/ HD broadcast } - else - { - sendAckResponseMsg( (MSG_ID_T)message->hdr.msgID, COMM_BUFFER_OUT_CAN_HD_2_DG, FALSE ); - } } /*********************************************************************//** Index: firmware/App/Tasks/TaskGeneral.c =================================================================== diff -u -rc67def50892f9a7c2f1f22985b5351465a8f6773 -raeb1dea9ea10fcc70ae66023a87b565f29924c07 --- firmware/App/Tasks/TaskGeneral.c (.../TaskGeneral.c) (revision c67def50892f9a7c2f1f22985b5351465a8f6773) +++ firmware/App/Tasks/TaskGeneral.c (.../TaskGeneral.c) (revision aeb1dea9ea10fcc70ae66023a87b565f29924c07) @@ -18,7 +18,8 @@ #include "AirTrap.h" #include "AlarmLamp.h" #include "BloodFlow.h" -#include "CPLD.h" +#include "CPLD.h" +#include "DGInterface.h" #include "DialInFlow.h" #include "DialOutFlow.h" #include "OperationModes.h" @@ -68,7 +69,10 @@ #ifndef SIMULATE_UI if ( TRUE == uiCommunicated() ) #endif - { + { + // monitor DG interface + execDGInterfaceMonitor(); + // monitor pressure/occlusion sensors execPresOccl();