Index: firmware/App/Controllers/ROPump.c =================================================================== diff -u -rd3819286869611f9c02add72a0f8e321598fdf42 -r012ee7b4f72e47aa351eb723abca0e3104ea677b --- firmware/App/Controllers/ROPump.c (.../ROPump.c) (revision d3819286869611f9c02add72a0f8e321598fdf42) +++ firmware/App/Controllers/ROPump.c (.../ROPump.c) (revision 012ee7b4f72e47aa351eb723abca0e3104ea677b) @@ -324,8 +324,12 @@ { U16 roFlowReading = getFPGAROPumpFlowRate(); - // Update sum for flow average calculation - measuredFlowReadingsSum += (S32)roFlowReading; + // If the flow is less than a certain value, FPGA will return 0xFFFF meaning that the flow is 0. + if ( FLOW_SENSOR_ZERO_READING != roFlowReading ) + { + // Update sum for flow average calculation + measuredFlowReadingsSum += (S32)roFlowReading; + } // Read the pressure at the sensor. The pump cannot be more that the maximum allowed pressure // to make sure the hardware (especially the ROF) is not damaged. If it is the case, we need to stop immediately @@ -347,25 +351,16 @@ F32 flow = RO_FLOW_ADC_TO_LPM_FACTOR / ( (F32)measuredFlowReadingsSum * FLOW_AVERAGE_MULTIPLIER ); - // If the flow is less than a certain value, FPGA will return 0xFFFF meaning that - // the flow is 0. Otherwise, convert the count to flow rate in mL/min - if ( ( FLOW_SENSOR_ZERO_READING == roFlowReading ) || ( 0 == roFlowReading ) ) + // Right now there is only one flow sensor but a for loop is used here to be able to automatically accommodate + // any future flow sensors TODO - this loop works with the flowSensorsCalRecord, but not with the measuredROFlowRateLPM structure. + for( sensor = 0; sensor < NUM_OF_CAL_DATA_FLOW_SENSORS; sensor++ ) { - measuredROFlowRateLPM.data = 0.0; + measuredROFlowRateLPM.data = pow(flow, 4) * flowSensorsCalRecord.flowSensors[ sensor ].fourthOrderCoeff + + pow(flow, 3) * flowSensorsCalRecord.flowSensors[ sensor ].thirdOrderCoeff + + pow(flow, 2) * flowSensorsCalRecord.flowSensors[ sensor ].secondOrderCoeff + + flow * flowSensorsCalRecord.flowSensors[ sensor ].gain + + flowSensorsCalRecord.flowSensors[ sensor ].offset; } - else - { - // Right now there is only one flow sensor but a for loop is used here to be able to automatically accommodate - // the future flow sensors - for( sensor = 0; sensor < NUM_OF_CAL_DATA_FLOW_SENSORS; sensor++ ) - { - measuredROFlowRateLPM.data = pow(flow, 4) * flowSensorsCalRecord.flowSensors[ sensor ].fourthOrderCoeff + - pow(flow, 3) * flowSensorsCalRecord.flowSensors[ sensor ].thirdOrderCoeff + - pow(flow, 2) * flowSensorsCalRecord.flowSensors[ sensor ].secondOrderCoeff + - flow * flowSensorsCalRecord.flowSensors[ sensor ].gain + - flowSensorsCalRecord.flowSensors[ sensor ].offset; - } - } measuredFlowReadingsSum = 0; flowFilterCounter = 0; Index: firmware/App/Modes/ModeDrain.c =================================================================== diff -u -r9df373d768695a399a141d5224bff88bea4efff5 -r012ee7b4f72e47aa351eb723abca0e3104ea677b --- firmware/App/Modes/ModeDrain.c (.../ModeDrain.c) (revision 9df373d768695a399a141d5224bff88bea4efff5) +++ firmware/App/Modes/ModeDrain.c (.../ModeDrain.c) (revision 012ee7b4f72e47aa351eb723abca0e3104ea677b) @@ -134,6 +134,7 @@ case DG_DRAIN_STATE_START: if ( TRUE == isDrainPumpOn() ) { + resetReservoirsLowestWeight(); drainState = DG_DRAIN_STATE_DRAIN; } break; Index: firmware/App/Modes/ModeFill.c =================================================================== diff -u -r9df373d768695a399a141d5224bff88bea4efff5 -r012ee7b4f72e47aa351eb723abca0e3104ea677b --- firmware/App/Modes/ModeFill.c (.../ModeFill.c) (revision 9df373d768695a399a141d5224bff88bea4efff5) +++ firmware/App/Modes/ModeFill.c (.../ModeFill.c) (revision 012ee7b4f72e47aa351eb723abca0e3104ea677b) @@ -463,18 +463,16 @@ } // If we've reached our target fill to volume (by weight), we're done filling - go back to generation idle mode - if ( ( TRUE == hasTargetFillVolumeBeenReached( inactiveReservoir ) ) || ( ( integratedVolume_mL - reservoirBaseWeight ) >= MAX_RESERVOIR_VOLUME_ML ) ) + if ( TRUE == hasTargetFillVolumeBeenReached( inactiveReservoir ) ) { F32 const filledVolume_mL = getReservoirWeight( inactiveReservoir ) - reservoirBaseWeight; F32 const integratedVolumeToLoadCellReadingPercent = fabs( 1 - ( filledVolume_mL / integratedVolume_mL ) ); - F32 const avgAcidConductivity = acidConductivityTotal / conductivitySampleCount; + F32 const avgAcidConductivity = acidConductivityTotal / conductivitySampleCount; // TODO - should we be checking this below? F32 const avgDialysateConductivity = dialysateConductivityTotal / conductivitySampleCount; if ( integratedVolumeToLoadCellReadingPercent > FLOW_INTEGRATED_VOLUME_CHECK_TOLERANCE ) { -#ifndef DISABLE_MIXING SET_ALARM_WITH_2_F32_DATA( ALARM_ID_DG_FLOW_METER_CHECK_FAILURE, filledVolume_mL, integratedVolume_mL ); -#endif } #ifndef DISABLE_DIALYSATE_CHECK Index: firmware/App/Services/Reservoirs.c =================================================================== diff -u -r9c523a8628bb75b601c048f67d3ef7250f45f547 -r012ee7b4f72e47aa351eb723abca0e3104ea677b --- firmware/App/Services/Reservoirs.c (.../Reservoirs.c) (revision 9c523a8628bb75b601c048f67d3ef7250f45f547) +++ firmware/App/Services/Reservoirs.c (.../Reservoirs.c) (revision 012ee7b4f72e47aa351eb723abca0e3104ea677b) @@ -45,8 +45,10 @@ #define MIN_DRAIN_INLET_PSI_EMPTY -3.0 ///< Minimum drain inlet pressure (in PSI) to indicate reservoir is empty while drain pump on. -#define RESERVOIR_DATA_PUB_INTERVAL ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ) ///< interval (ms/task time) at which the reservoir data is published on the CAN bus. +#define RESERVOIR_DATA_PUB_INTERVAL ( MS_PER_SECOND / TASK_GENERAL_INTERVAL ) ///< interval (ms/task time) at which the reservoir data is published on the CAN bus. +#define MAX_REDUNDANT_LOAD_CELL_DIFF 50.0 ///< Maximum difference in redundant load cells when determing if fill completed. + // ********** private data ********** static U32 reservoirDataPublicationTimerCounter = 0; ///< used to schedule reservoir data publication to CAN bus. @@ -461,10 +463,17 @@ *************************************************************************/ BOOL hasTargetFillVolumeBeenReached( DG_RESERVOIR_ID_T reservoirId ) { - F32 const loadcellWeight = getLoadCellSmallFilteredWeight( associatedLoadCell[ reservoirId ] ); + F32 const loadcellWeight1 = getLoadCellSmallFilteredWeight( associatedLoadCell[ reservoirId ] ); + F32 const loadcellWeight2 = getLoadCellSmallFilteredWeight( redundantLoadCell[ reservoirId ] ); U32 const targetFillVolume = getU32OverrideValue( &fillVolumeTargetMl ); - BOOL const hasTargetReached = ( loadcellWeight >= targetFillVolume ); + BOOL const hasTargetReached = ( ( loadcellWeight1 >= targetFillVolume || loadcellWeight2 > ( targetFillVolume + MAX_REDUNDANT_LOAD_CELL_DIFF ) ) ? TRUE : FALSE ); + // if redundant load cells too far apart at end of fill, alarm + if ( loadcellWeight1 < targetFillVolume ) + { + // TODO - alarm + } + return hasTargetReached; }