Index: firmware/App/Controllers/Heaters.c =================================================================== diff -u -r2468e56fbecd26da713bc78535bd727f4b105fe1 -rab7dfc361e5ee347141842b317f1fc2f16e4e3f3 --- firmware/App/Controllers/Heaters.c (.../Heaters.c) (revision 2468e56fbecd26da713bc78535bd727f4b105fe1) +++ firmware/App/Controllers/Heaters.c (.../Heaters.c) (revision ab7dfc361e5ee347141842b317f1fc2f16e4e3f3) @@ -183,6 +183,7 @@ { if( heater < NUM_OF_DG_HEATERS ) { +#ifndef DISABLE_HEATERS_AND_TEMPS // Assume the target temperature has not changed heatersStatus[ heater ].hasTargetTempChanged = FALSE; @@ -199,6 +200,7 @@ // TODO alarm if temperature if out of range or just reject? } } +#endif } else { @@ -230,13 +232,16 @@ { BOOL status = FALSE; + if( heater < NUM_OF_DG_HEATERS ) { +#ifndef DISABLE_HEATERS_AND_TEMPS if ( TRUE == heatersStatus[ heater ].hasTargetTempChanged ) { status = TRUE; heatersStatus[ heater ].startHeaterSignal = TRUE; } +#endif } else { @@ -321,6 +326,7 @@ if ( ( MINIMUM_TARGET_TEMPERATURE <= heaterCmdPtr->targetTemp ) && ( heaterCmdPtr->targetTemp <= MAXIMUM_TARGET_TEMPERATURE ) ) { cmdResponse.rejected = FALSE; + #ifndef DISABLE_HEATERS_AND_TEMPS heatersStatus[ DG_TRIMMER_HEATER ].targetTemp = heaterCmdPtr->targetTemp; heatersStatus[ DG_TRIMMER_HEATER ].startHeaterSignal = TRUE; @@ -352,7 +358,7 @@ *************************************************************************/ void execHeatersMonitor( void ) { - /*DG_HEATERS_T heater; + DG_HEATERS_T heater; #ifndef IGNORE_HEATERS_MONITOR checkPrimaryHeaterTempSensors(); @@ -395,7 +401,7 @@ heatersStatus[ heater ].heaterOnWithNoFlowTimer = getMSTimerCount(); } } - }*/ + } // TODO un-comment the heaters voltage //monitorHeatersVoltage(); Index: firmware/App/Controllers/ROPump.c =================================================================== diff -u -r2468e56fbecd26da713bc78535bd727f4b105fe1 -rab7dfc361e5ee347141842b317f1fc2f16e4e3f3 --- firmware/App/Controllers/ROPump.c (.../ROPump.c) (revision 2468e56fbecd26da713bc78535bd727f4b105fe1) +++ firmware/App/Controllers/ROPump.c (.../ROPump.c) (revision ab7dfc361e5ee347141842b317f1fc2f16e4e3f3) @@ -324,12 +324,16 @@ roControlTimerCounter = 0; isROPumpOn = FALSE; targetROPumpMaxPressure = 0; + pendingROPumpCmdMaxPressure = 0.0; + pendingROPumpCmdTargetFlow = 0.0; + pendingROPumpCmdCountDown = 0; resetPIController( PI_CONTROLLER_ID_RO_PUMP_FLOW, MIN_RO_PUMP_DUTY_CYCLE ); } /*********************************************************************//** * @brief - * The execROPumpMonitor function executes the RO pump monitor. + * The execROPumpMonitor function executes the RO pump monitor. The RO flow + * sensor is read, filtered, converted to L/min and calibrated. * @details Inputs: measuredFlowReadingsSum, flowFilterCounter, * measuredROFlowRateLPM, measuredROFlowRateLPM, roPumpState, * flowOutOfRangeCounter, roPumpControlMode @@ -365,20 +369,20 @@ // Read flow at the control set if ( ++flowFilterCounter >= FLOW_SAMPLES_TO_AVERAGE ) { - F32 flow = RO_FLOW_ADC_TO_LPM_FACTOR / ( (F32)measuredFlowReadingsSum * FLOW_AVERAGE_MULTIPLIER ); + F32 flow = RO_FLOW_ADC_TO_LPM_FACTOR / ( (F32)measuredFlowReadingsSum * FLOW_AVERAGE_MULTIPLIER ); // Convert flow sensor period to L/min + // Apply calibration to flow sensor reading measuredROFlowRateLPM.data = pow(flow, 4) * flowSensorsCalRecord.flowSensors[ CAL_DATA_RO_PUMP_FLOW_SENSOR ].fourthOrderCoeff + pow(flow, 3) * flowSensorsCalRecord.flowSensors[ CAL_DATA_RO_PUMP_FLOW_SENSOR ].thirdOrderCoeff + pow(flow, 2) * flowSensorsCalRecord.flowSensors[ CAL_DATA_RO_PUMP_FLOW_SENSOR ].secondOrderCoeff + - flow * flowSensorsCalRecord.flowSensors[ CAL_DATA_RO_PUMP_FLOW_SENSOR ].gain + + flow * flowSensorsCalRecord.flowSensors[ CAL_DATA_RO_PUMP_FLOW_SENSOR ].gain + flowSensorsCalRecord.flowSensors[ CAL_DATA_RO_PUMP_FLOW_SENSOR ].offset; - // 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 ) - { - measuredROFlowRateLPM.data = 0.0; - } + // 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 ) + { + measuredROFlowRateLPM.data = 0.0; + } measuredFlowReadingsSum = 0; flowFilterCounter = 0; Index: firmware/App/DGCommon.h =================================================================== diff -u -r2468e56fbecd26da713bc78535bd727f4b105fe1 -rab7dfc361e5ee347141842b317f1fc2f16e4e3f3 --- firmware/App/DGCommon.h (.../DGCommon.h) (revision 2468e56fbecd26da713bc78535bd727f4b105fe1) +++ firmware/App/DGCommon.h (.../DGCommon.h) (revision ab7dfc361e5ee347141842b317f1fc2f16e4e3f3) @@ -25,7 +25,7 @@ #define DG_VERSION_MAJOR 0 #define DG_VERSION_MINOR 6 #define DG_VERSION_MICRO 0 -#define DG_VERSION_BUILD 14 +#define DG_VERSION_BUILD 57 // ********** build switches ********** @@ -48,10 +48,12 @@ #define IGNORE_RO_PUMP_MONITOR 1 #define DISABLE_RO_RATIO_CHECK 1 // #define DISABLE_COND_SENSOR_CHECK 1 -// #define DISABLE_WATER_QUALITY_CHECK 1 + #define DISABLE_WATER_QUALITY_CHECK 1 #define DISABLE_RTC_CONFIG 1 #define THD_USING_TRO_CONNECTOR 1 + #define DISABLE_FLOW_CHECK_IN_FILL 1 #define IGNORE_CONC_PUMP_IN_HEAT_DISINFECT 1 +// #define NEW_FMD_FLOW_SENSOR 1 // Turn these flags on to disable dialysate mixing #define DISABLE_DIALYSATE_CHECK 1 Index: firmware/App/Modes/ModeDrain.c =================================================================== diff -u -r2468e56fbecd26da713bc78535bd727f4b105fe1 -rab7dfc361e5ee347141842b317f1fc2f16e4e3f3 --- firmware/App/Modes/ModeDrain.c (.../ModeDrain.c) (revision 2468e56fbecd26da713bc78535bd727f4b105fe1) +++ firmware/App/Modes/ModeDrain.c (.../ModeDrain.c) (revision ab7dfc361e5ee347141842b317f1fc2f16e4e3f3) @@ -15,6 +15,7 @@ * ***************************************************************************/ +#include "ConcentratePumps.h" #include "ConductivitySensors.h" #include "DrainPump.h" #include "Heaters.h" @@ -46,15 +47,23 @@ #define DELAY_RES_DRAIN_VALVE_MS 1000 ///< Delay reservoir drain valve open by 1 second. #define DELAY_DRAIN_PUMP_MS 2000 ///< Delay drain pump on by 2 seconds. +/// Time period to wait for concentrate lines to rinse. +#define RINSE_CONCENTRATE_LINES_WAIT ( 25 * MS_PER_SECOND / TASK_GENERAL_INTERVAL ) +/// Reserver the concentrate speed to rinse out concentrate lines. +#define RINSE_SPEED ( ( CONCENTRATE_PUMP_MAX_SPEED - 3.0 ) * -1.0 ) + // ********** private data ********** static DG_DRAIN_STATE_T drainState; ///< Currently active drain state. static U32 drainEmptyTareTimerCtr; ///< Timer counter for delay between drain complete and load cell tare. +static BOOL rinseConcentrateLines; ///< Flag indicates to rinse concentrate lines. +static U32 rinseConcentrateLinesTimerCtr; ///< Timer counter for rinsing concentrate lines. // ********** private function prototypes ********** static DG_DRAIN_STATE_T handleDrainState( void ); static DG_DRAIN_STATE_T handleTareState( void ); +static DG_DRAIN_STATE_T handleRinseState( void ); /*********************************************************************//** * @brief @@ -67,6 +76,8 @@ { drainState = DG_DRAIN_STATE_START; drainEmptyTareTimerCtr = 0; + rinseConcentrateLines = FALSE; + rinseConcentrateLinesTimerCtr = 0; } /*********************************************************************//** @@ -125,6 +136,7 @@ case DG_DRAIN_STATE_START: if ( TRUE == isDrainPumpOn() ) { + resetReservoirsLowestWeight(); drainState = DG_DRAIN_STATE_DRAIN; } break; @@ -137,6 +149,10 @@ drainState = handleTareState(); break; + case DG_DRAIN_STATE_RINSE: + drainState = handleRinseState(); + break; + default: SET_ALARM_WITH_2_U32_DATA( ALARM_ID_DG_SOFTWARE_FAULT, SW_FAULT_ID_DRAIN_MODE_INVALID_EXEC_STATE, drainState ) drainState = DG_DRAIN_STATE_START; @@ -148,6 +164,31 @@ /*********************************************************************//** * @brief + * The getCurrentDrainState function returns the current state of the drain mode. + * @details Inputs: drainState + * @details Outputs: none + * @return the current state of drain mode. + *************************************************************************/ +DG_DRAIN_STATE_T getCurrentDrainState( void ) +{ + return drainState; +} + +/*********************************************************************//** + * @brief + * The signalDrainModeRinseConcentrateLines function sets the flag for drain + * mode to rinse concentrate lines. + * @details Inputs: none + * @details Outputs: rinseConcentrateLines + * @return none + *************************************************************************/ +void signalDrainModeRinseConcentrateLines( BOOL rinse ) +{ + rinseConcentrateLines = rinse; +} + +/*********************************************************************//** + * @brief * The handleDrainState function handles the drain state of the drain mode * state machine. * @details Inputs: none @@ -162,7 +203,7 @@ // if we have reached our target drain to volume (by weight) or cannot drain anymore, we are done draining - go back to generation idle mode if ( TRUE == hasTargetDrainVolumeBeenReached( inactiveReservoir, DRAIN_WEIGHT_UNCHANGE_TIMEOUT ) ) { - setDrainPumpTargetRPM( 0 ); + signalDrainPumpHardStop(); if ( DG_RESERVOIR_1 == inactiveReservoir ) { @@ -203,25 +244,52 @@ { drainEmptyTareTimerCtr = 0; tareLoadCellsAtEmpty( inactiveReservoir ); - requestNewOperationMode( DG_MODE_GENE ); setValveState( VRD1, VALVE_STATE_CLOSED ); setValveState( VRD2, VALVE_STATE_CLOSED ); + + if ( TRUE == rinseConcentrateLines ) + { + setConcentratePumpTargetSpeed( CONCENTRATEPUMPS_CP1_ACID, RINSE_SPEED ); + setConcentratePumpTargetSpeed( CONCENTRATEPUMPS_CP2_BICARB, RINSE_SPEED ); + requestConcentratePumpOn( CONCENTRATEPUMPS_CP1_ACID ); + requestConcentratePumpOn( CONCENTRATEPUMPS_CP2_BICARB ); + } + rinseConcentrateLinesTimerCtr = 0; + result = DG_DRAIN_STATE_RINSE; } return result; } /*********************************************************************//** * @brief - * The getCurrentDrainState function returns the current state of the drain mode. - * @details Inputs: drainState - * @details Outputs: none - * @return the current state of drain mode. + * The handleRinseState function handles the tare state of the drain mode + * state machine. + * @details Inputs: drainEmptyTareTimerCtr + * @details Outputs: drainEmptyTareTimerCtr + * @return the next state *************************************************************************/ -DG_DRAIN_STATE_T getCurrentDrainState( void ) +static DG_DRAIN_STATE_T handleRinseState( void ) { - return drainState; + DG_DRAIN_STATE_T result = DG_DRAIN_STATE_RINSE; + + if ( TRUE == rinseConcentrateLines ) + { + if ( ++rinseConcentrateLinesTimerCtr > RINSE_CONCENTRATE_LINES_WAIT ) + { + rinseConcentrateLinesTimerCtr = 0; + requestConcentratePumpOff( CONCENTRATEPUMPS_CP1_ACID ); + requestConcentratePumpOff( CONCENTRATEPUMPS_CP2_BICARB ); + requestNewOperationMode( DG_MODE_GENE ); + } + } + else + { + requestNewOperationMode( DG_MODE_GENE ); + } + + return result; } /**@}*/ Index: firmware/App/Modes/ModeFill.c =================================================================== diff -u -r2468e56fbecd26da713bc78535bd727f4b105fe1 -rab7dfc361e5ee347141842b317f1fc2f16e4e3f3 --- firmware/App/Modes/ModeFill.c (.../ModeFill.c) (revision 2468e56fbecd26da713bc78535bd727f4b105fe1) +++ firmware/App/Modes/ModeFill.c (.../ModeFill.c) (revision ab7dfc361e5ee347141842b317f1fc2f16e4e3f3) @@ -316,15 +316,16 @@ DG_FILL_MODE_STATE_T result = DG_FILL_MODE_STATE_BICARB_PUMP_CHECK; DG_BICARB_CONCENTRATES_RECORD_T bicarb = getBicarbConcentrateCalRecord(); F32 const measuredROFlowRate_mL_min = getMeasuredROFlowRate() * ML_PER_LITER; - F32 const bicarbPumpFlowRate_mL_min = measuredROFlowRate_mL_min * bicarb.bicarbConcentrate[ CAL_DATA_BICARB_CONCENTRATE_1 ].bicarbConcMixRatio + + F32 bicarbPumpFlowRate_mL_min = measuredROFlowRate_mL_min * bicarb.bicarbConcentrate[ CAL_DATA_BICARB_CONCENTRATE_1 ].bicarbConcMixRatio + CONCENTRATE_PUMP_PRIME_EXTRA_SPEED_ML_MIN; - #ifndef DISABLE_DIALYSATE_CHECK F32 const bicarbConductivity = getConductivityValue( CONDUCTIVITYSENSORS_CD2_SENSOR ); #else - F32 const bicarbConductivity = MIN_BICARB_CONCENTRATE_CONDUCTIVITY; + F32 const bicarbConductivity = MAX_BICARB_CONCENTRATE_CONDUCTIVITY; #endif + bicarbPumpFlowRate_mL_min = MIN( bicarbPumpFlowRate_mL_min, CONCENTRATE_PUMP_MAX_SPEED ); + if ( MIN_BICARB_CONCENTRATE_CONDUCTIVITY <= bicarbConductivity ) { // Reduce acid pump speed after reaching minimum conductivity @@ -377,9 +378,11 @@ #ifndef DISABLE_DIALYSATE_CHECK F32 const acidConductivity = getConductivityValue( CONDUCTIVITYSENSORS_CD1_SENSOR ); #else - F32 const acidConductivity = MIN_ACID_CONCENTRATE_CONDUCTIVITY; + F32 const acidConductivity = MAX_ACID_CONCENTRATE_CONDUCTIVITY; #endif + acidPumpFlowRate_mL_min = MIN( acidPumpFlowRate_mL_min, CONCENTRATE_PUMP_MAX_SPEED ); + if ( MIN_ACID_CONCENTRATE_CONDUCTIVITY <= acidConductivity ) { // Reduce acid pump speed after reaching minimum conductivity @@ -429,10 +432,12 @@ { // Prime mixing before deliver result to reservoir handleDialysateMixing( measuredROFlowRate_mL_min ); +#ifndef DISABLE_MIXING requestConcentratePumpOn( CONCENTRATEPUMPS_CP1_ACID ); requestConcentratePumpOn( CONCENTRATEPUMPS_CP2_BICARB ); if ( concentratePumpPrimeCount++ > CONCENTRATE_PUMP_PRIME_INTERVAL ) +#endif { setValveState( VPO, VALVE_STATE_FILL_C_TO_NC ); result = DG_FILL_MODE_STATE_DELIVER_DIALYSATE; @@ -512,7 +517,7 @@ result = DG_FILL_MODE_STATE_PAUSED; } #endif - +#ifndef DISABLE_MIXING if ( ( ACID_CONCENTRATION_BOTTLE_VOLUME_ML - getF32OverrideValue( &usedAcidVolume_mL ) ) <= CONCENTRATION_BOTTLE_LOW_VOLUME_ML ) { activateAlarmNoData( ALARM_ID_DG_ACID_BOTTLE_LOW_VOLUME ); @@ -522,18 +527,18 @@ { activateAlarmNoData( ALARM_ID_DG_BICARB_BOTTLE_LOW_VOLUME ); } - +#endif // 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 +#ifndef DISABLE_FLOW_CHECK_IN_FILL SET_ALARM_WITH_2_F32_DATA( ALARM_ID_DG_FLOW_METER_CHECK_FAILURE, filledVolume_mL, integratedVolume_mL ); #endif } Index: firmware/App/Modes/ModeGenIdle.c =================================================================== diff -u -r2468e56fbecd26da713bc78535bd727f4b105fe1 -rab7dfc361e5ee347141842b317f1fc2f16e4e3f3 --- firmware/App/Modes/ModeGenIdle.c (.../ModeGenIdle.c) (revision 2468e56fbecd26da713bc78535bd727f4b105fe1) +++ firmware/App/Modes/ModeGenIdle.c (.../ModeGenIdle.c) (revision ab7dfc361e5ee347141842b317f1fc2f16e4e3f3) @@ -139,7 +139,7 @@ { if ( TRUE == didTimeout( hdLostCommStartTime_ms, HD_LOST_COMM_TIMEOUT_MS ) ) { - //requestNewOperationMode( DG_MODE_STAN ); TODO uncomment there is no HD in unit 2 + requestNewOperationMode( DG_MODE_STAN ); } } Index: firmware/App/Modes/ModeInitPOST.c =================================================================== diff -u -r2468e56fbecd26da713bc78535bd727f4b105fe1 -rab7dfc361e5ee347141842b317f1fc2f16e4e3f3 --- firmware/App/Modes/ModeInitPOST.c (.../ModeInitPOST.c) (revision 2468e56fbecd26da713bc78535bd727f4b105fe1) +++ firmware/App/Modes/ModeInitPOST.c (.../ModeInitPOST.c) (revision ab7dfc361e5ee347141842b317f1fc2f16e4e3f3) @@ -284,15 +284,15 @@ { DG_POST_STATE_T result = postState; - if ( ( SELF_TEST_STATUS_PASSED == testStatus ) || ( SELF_TEST_STATUS_FAILED == testStatus ) ) + if ( ( testStatus == SELF_TEST_STATUS_PASSED ) || ( testStatus == SELF_TEST_STATUS_FAILED ) ) { - BOOL passed = ( SELF_TEST_STATUS_PASSED == testStatus ? TRUE : FALSE ); + BOOL passed = ( testStatus == SELF_TEST_STATUS_PASSED ? TRUE : FALSE ); // Broadcast passed POST result sendPOSTTestResult( (DG_POST_STATE_T)((int)postState), passed ); // Move on to next POST test result = (DG_POST_STATE_T)((int)postState + 1); - if ( SELF_TEST_STATUS_FAILED == testStatus ) + if ( testStatus == SELF_TEST_STATUS_FAILED ) { tempPOSTPassed = FALSE; } Index: firmware/App/Services/FPGA.c =================================================================== diff -u -re6f3a632890f96a5aa282922d11df148bdd06587 -rab7dfc361e5ee347141842b317f1fc2f16e4e3f3 --- firmware/App/Services/FPGA.c (.../FPGA.c) (revision e6f3a632890f96a5aa282922d11df148bdd06587) +++ firmware/App/Services/FPGA.c (.../FPGA.c) (revision ab7dfc361e5ee347141842b317f1fc2f16e4e3f3) @@ -185,7 +185,17 @@ U16 fpgaFanOut2Pulse; ///< Reg 398. Fan outlet 2 pulse time in 2.5 resolution U16 fpgaFanIn3Pulse; ///< Reg 400. Fan inlet 3 pulse time in 2.5 resolution U16 fpgaFanOut3Pulse; ///< Reg 402. Fan outlet 3 pulse time in 2.5 resolution - U16 fpgaTimerCount_ms; ///< Reg 404. Internal FPGA timer count in ms. + U16 fpgaTimerCount_ms; ///< Reg 404. Internal FPGA timer count in ms. + + U16 fpgaADCVccInt; ///< Reg 406. Internal FPGA Vcc Voltage. + U16 fpgaADCVccAux; ///< Reg 408. Internal FPGA Vcc auxiliary voltage. + U16 fpgaADCVPVN; ///< Reg 410. Internal FPGA VPVN voltage. + + U16 fpgaROPumpFeedback; ///< Reg 412. RO pump duty cycle feedback. + U16 fpgaDrainPumpSpeedFeedback; ///< Reg 414. Drain pump speed feedback. + U16 fpgaDrainPumpCurrentFeedback; ///< Reg 416. Drain pump current feedback. + + U16 fpgaFMPROFlowTemporary; ///< Reg 418. FMP flow sensor temporary register. } DG_FPGA_SENSORS_T; typedef struct @@ -1926,4 +1936,9 @@ return ( fpgaSensorReadings.fpgaGPIO & CONCENTRATE_CAP_SWITCH_MASK ); } +U16 getFPGAFMPTemporaryFlow( void ) +{ + return fpgaSensorReadings.fpgaFMPROFlowTemporary; +} + /**@}*/