Index: firmware/App/Controllers/DGInterface.c =================================================================== diff -u -rfee22801cab60be10f4e7c08a1a96645dfdcaf8b -r1017bbc5760a50e20357da1e4f705b3e6157375e --- firmware/App/Controllers/DGInterface.c (.../DGInterface.c) (revision fee22801cab60be10f4e7c08a1a96645dfdcaf8b) +++ firmware/App/Controllers/DGInterface.c (.../DGInterface.c) (revision 1017bbc5760a50e20357da1e4f705b3e6157375e) @@ -27,11 +27,11 @@ // ********** private definitions ********** -#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 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 DRAIN_RESERVOIR_TO_VOLUME_ML 100 ///< Drain reservoir to this volume (in mL) during treatment. -#define FILL_RESERVOIR_TO_VOLUME_ML 1500 ///< Fill reservoir to this volume (in mL) during treatment. +#define DRAIN_RESERVOIR_TO_VOLUME_ML 100 ///< Drain reservoir to this volume (in mL) during treatment. +#define FILL_RESERVOIR_TO_VOLUME_ML 1500 ///< Fill reservoir to this volume (in mL) during treatment. /// States of the treatment reservoir management state machine. typedef enum TreatmentReservoirMgmt_States @@ -48,35 +48,34 @@ // ********** private data ********** // DG status -static DG_OP_MODE_T dgCurrentOpMode = DG_MODE_INIT; -static U32 dgSubMode = 0; -static BOOL dgStarted = FALSE; -static BOOL dgStartetSet = FALSE; -static BOOL dgWaterSampled = FALSE; -static BOOL dgWaterSampledSet = FALSE; +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. // DG sensor data -static F32 dgPressures[ NUM_OF_DG_PRESSURE_SENSORS ]; -static F32 dgPrimaryTempSet = 0.0; -static F32 dgPrimaryTemp = 0.0; -static F32 dgTrimmerTempSet = 0.0; -static F32 dgTrimmerTemp = 0.0; +static F32 dgPressures[ NUM_OF_DG_PRESSURE_SENSORS ]; ///< Latest pressures 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 pumps data -static F32 dgROPumpFlowRateMlMin = 0.0; -static U32 dgROPumpPressureSetPtPSI = 0; -static U32 dgDrainPumpSpeedSetPtRPM = 0; +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; -static DG_RESERVOIR_ID_T dgActiveReservoirSet = DG_RESERVOIR_2; -static U32 dgReservoirFillVolumeTarget = 0; -static U32 dgReservoirFillVolumeTargetSet = 0; -static U32 dgReservoirDrainVolumeTarget = 0; -static U32 dgReservoirDrainVolumeTargetSet = 0; +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. // ********** private function prototypes ********** @@ -210,6 +209,19 @@ /*********************************************************************//** * @brief + * The getDGActiveReservoir function gets the current active reservoir. + * @details + * Inputs : dgActiveReservoirSet + * Outputs : none + * @return Currently commanded active reservoir. + *************************************************************************/ +DG_RESERVOIR_ID_T getDGActiveReservoir( void ) +{ + return dgActiveReservoirSet; +} + +/*********************************************************************//** + * @brief * The getDGPressure function gets the latest pressure reported by the DG \n * for a given pressure sensor. * @details @@ -439,6 +451,18 @@ sendDGStartStopCommand( STOP_DG_CMD ); } +void cmdStartDGTrimmerHeater( void ) +{ + dgTrimmerHeaterOn = TRUE; + sendDGStartStopTrimmerHeaterCommand( START_DG_CMD ); +} + +void cmdStopDGTrimmerHeater( void ) +{ + dgTrimmerHeaterOn = FALSE; + sendDGStartStopTrimmerHeaterCommand( STOP_DG_CMD ); +} + /*********************************************************************//** * @brief * The cmdSetDGActiveReservoir function sends a set active reservoir command \n Index: firmware/App/Controllers/DGInterface.h =================================================================== diff -u -r0b87f7e6142dc3710db5c32a0c7c6694343dd717 -r1017bbc5760a50e20357da1e4f705b3e6157375e --- firmware/App/Controllers/DGInterface.h (.../DGInterface.h) (revision 0b87f7e6142dc3710db5c32a0c7c6694343dd717) +++ firmware/App/Controllers/DGInterface.h (.../DGInterface.h) (revision 1017bbc5760a50e20357da1e4f705b3e6157375e) @@ -75,6 +75,8 @@ void cmdSetDGActiveReservoir( DG_RESERVOIR_ID_T resID ); void cmdStartDGFill( U32 fillToVolMl ); void cmdStartDGDrain( U32 drainToVolMl ); +void cmdStartDGTrimmerHeater( void ); +void cmdStopDGTrimmerHeater( void ); void cmdDGSampleWater( void ); /**@}*/ Index: firmware/App/Modes/Dialysis.c =================================================================== diff -u -rd954cab1e721ac955f98feb260d7b978ec14ccab -r1017bbc5760a50e20357da1e4f705b3e6157375e --- firmware/App/Modes/Dialysis.c (.../Dialysis.c) (revision d954cab1e721ac955f98feb260d7b978ec14ccab) +++ firmware/App/Modes/Dialysis.c (.../Dialysis.c) (revision 1017bbc5760a50e20357da1e4f705b3e6157375e) @@ -16,6 +16,7 @@ #include "BloodFlow.h" #include "Buttons.h" +#include "DGInterface.h" #include "Dialysis.h" #include "DialInFlow.h" #include "DialOutFlow.h" @@ -42,7 +43,8 @@ static F32 refUFVolume; ///< Current reference volume for ultrafiltration (Where should we be w/r/t ultrafiltration). static F32 measUFVolume; ///< Current total measured volume for ultrafiltration (Where are we w/r/t ultrafiltration). -static F32 resStartVolume; ///< Reservoir start volume for ultrafiltration (i.e. where did we start with current reservoir). +static F32 resStartVolume[ NUM_OF_DG_RESERVOIRS ]; ///< Reservoir start volume for ultrafiltration (i.e. where did we start with each reservoir). +static F32 resFinalVolume[ NUM_OF_DG_RESERVOIRS ]; ///< Reservoir final volume for ultrafiltration (i.e. where did we end after switch with each reservoir). static F32 measUFVolumeFromPriorReservoirs; ///< Current total ultrafiltration volume from previous reservoirs in current treatment. static U32 uFTimeMS; ///< Current elapsed ultrafiltration time (in ms). Used for calculating UF reference volume. @@ -87,7 +89,10 @@ refUFVolume = 0.0; measUFVolume = 0.0; - resStartVolume = 0.0; + resStartVolume[ DG_RESERVOIR_1 ] = 0.0; + resStartVolume[ DG_RESERVOIR_2 ] = 0.0; + resFinalVolume[ DG_RESERVOIR_1 ] = 0.0; + resFinalVolume[ DG_RESERVOIR_2 ] = 0.0; measUFVolumeFromPriorReservoirs = 0.0; uFTimeMS = 0; @@ -307,7 +312,7 @@ switch ( currentDialysisState ) { case DIALYSIS_START_STATE: - resStartVolume = getLoadCellWeightInGrams( LOAD_CELL_RESERVOIR_1_PRIMARY ); // always start dialysis w/ reservoir 1 +// resStartVolume = getLoadCellWeightInGrams( LOAD_CELL_RESERVOIR_1_PRIMARY ); // should be set by reservoir mgmg state machine now currentDialysisState = DIALYSIS_UF_STATE; break; @@ -563,14 +568,120 @@ *************************************************************************/ static void updateUFVolumes( void ) { - F32 latestResVolume = getLoadCellWeightInGrams( LOAD_CELL_RESERVOIR_1_PRIMARY ); // TODO - just res 1 for now - add reservoir switching, mgmt later. + DG_RESERVOIR_ID_T activeRes = getDGActiveReservoir(); + F32 latestResVolume; + // 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 refUFVolume = ( ( (F32)uFTimeMS / MS_PER_SECOND ) / SEC_PER_MIN ) * setUFRate; - measUFVolume = measUFVolumeFromPriorReservoirs + ( latestResVolume - resStartVolume ); + measUFVolume = measUFVolumeFromPriorReservoirs + ( latestResVolume - resStartVolume[ activeRes ] ); + resFinalVolume[ activeRes ] = latestResVolume; setDialOutUFVolumes( refUFVolume, measUFVolume ); } +/*********************************************************************//** + * @brief + * The setStartReservoirVolume function updates the baseline volume of the \n + * next reservoir to be drawn from before it is switched to (i.e. while it \n + * is the inactive reservoir) in order to get a more stable volume. + * @details + * Inputs : active reservoir, load cell reading from inactive reservoir + * Outputs : resStartVolume[] + * @return none + *************************************************************************/ +void setStartReservoirVolume( void ) +{ + DG_RESERVOIR_ID_T activeRes = getDGActiveReservoir(); + DG_RESERVOIR_ID_T inactiveRes; + F32 resVolume; + + // 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; +} + +/*********************************************************************//** + * @brief + * The signalReservoirsSwitched function informs this module that the \n + * reservoirs have been switched. The UF volume from prior reservoirs is \n + * tentatively added to with a load cell reading of the inactive reservoir. + * @details + * Inputs : resFinalVolume[], resStartVolume[] + * Outputs : measUFVolumeFromPriorReservoirs + * @return none + *************************************************************************/ +void signalReservoirsSwitched( void ) +{ + DG_RESERVOIR_ID_T activeRes = getDGActiveReservoir(); + DG_RESERVOIR_ID_T inactiveRes; + + // get volume of inactive reservoir + if ( DG_RESERVOIR_2 == activeRes ) + { + inactiveRes = DG_RESERVOIR_1; + } + else + { + inactiveRes = DG_RESERVOIR_2; + } + // update UF volume from prior reservoirs per tentative res volume for last reservoir + measUFVolumeFromPriorReservoirs += ( resFinalVolume[ inactiveRes ] - resStartVolume[ inactiveRes ] ); +} + +/*********************************************************************//** + * @brief + * The setFinalReservoirVolume function updates the UF volume from prior reservoirs \n + * with a more stable final reservoir volume of the prior reservoir after it's \n + * had a moment to settle. + * @details + * Inputs : active reservoir, load cell reading from inactive reservoir + * Outputs : measUFVolumeFromPriorReservoirs, resFinalVolume[], resStartVolume[] + * @return none + *************************************************************************/ +void setFinalReservoirVolume( void ) +{ + DG_RESERVOIR_ID_T activeRes = getDGActiveReservoir(); + DG_RESERVOIR_ID_T inactiveRes; + F32 resVolume; + + // 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 + measUFVolumeFromPriorReservoirs -= ( resFinalVolume[ inactiveRes ] - resStartVolume[ inactiveRes ] ); + resFinalVolume[ inactiveRes ] = resVolume; + measUFVolumeFromPriorReservoirs += ( resFinalVolume[ inactiveRes ] - resStartVolume[ inactiveRes ] ); +} + /**@}*/ Index: firmware/App/Modes/Dialysis.h =================================================================== diff -u -rd954cab1e721ac955f98feb260d7b978ec14ccab -r1017bbc5760a50e20357da1e4f705b3e6157375e --- firmware/App/Modes/Dialysis.h (.../Dialysis.h) (revision d954cab1e721ac955f98feb260d7b978ec14ccab) +++ firmware/App/Modes/Dialysis.h (.../Dialysis.h) (revision 1017bbc5760a50e20357da1e4f705b3e6157375e) @@ -82,6 +82,10 @@ BOOL pauseUF( void ); BOOL resumeUF( void ); +void setStartReservoirVolume( void ); +void signalReservoirsSwitched( void ); +void setFinalReservoirVolume( void ); + /**@}*/ #endif Index: firmware/App/Services/SystemCommMessages.c =================================================================== diff -u -r0b87f7e6142dc3710db5c32a0c7c6694343dd717 -r1017bbc5760a50e20357da1e4f705b3e6157375e --- firmware/App/Services/SystemCommMessages.c (.../SystemCommMessages.c) (revision 0b87f7e6142dc3710db5c32a0c7c6694343dd717) +++ firmware/App/Services/SystemCommMessages.c (.../SystemCommMessages.c) (revision 1017bbc5760a50e20357da1e4f705b3e6157375e) @@ -641,6 +641,36 @@ /************************************************************************* * @brief + * The sendDGStartStopTrimmerHeaterCommand function constructs a DG start/stop \n + * trimmer heater command message and queues the msg for transmit on the \n + * appropriate CAN channel. + * @details + * Inputs : none + * Outputs : DG start/stop trimmer heater command msg constructed and queued. + * @param start : TRUE indicates start heater, FALSE indicates stop heater. + * @return TRUE if msg successfully queued for transmit, FALSE if not + *************************************************************************/ +BOOL sendDGStartStopTrimmerHeaterCommand( BOOL start ) +{ + BOOL result; + MESSAGE_T msg; + U08 *payloadPtr = msg.payload; + + // create a message record + blankMessage( &msg ); + msg.hdr.msgID = MSG_ID_DG_START_STOP_TRIMMER_HEATER_CMD; + msg.hdr.payloadLen = sizeof( BOOL ); + + memcpy( payloadPtr, &start, sizeof( BOOL ) ); + + // serialize the message (w/ sync, CRC, and appropriate CAN padding) and add serialized message data to appropriate comm buffer + result = serializeMessage( msg, COMM_BUFFER_OUT_CAN_HD_2_DG, ACK_REQUIRED ); + + return result; +} + +/************************************************************************* + * @brief * The sendDGSampleWaterCommand function constructs a DG sample water command \n * message and queues the msg for transmit on the appropriate CAN channel. * @details @@ -1430,18 +1460,21 @@ MESSAGE_T msg; U08 major = (U08)HD_VERSION_MAJOR; U08 minor = (U08)HD_VERSION_MINOR; + U08 micro = (U08)HD_VERSION_MICRO; U16 build = (U16)HD_VERSION_BUILD; U08 *payloadPtr = msg.payload; // create a message record blankMessage( &msg ); msg.hdr.msgID = MSG_ID_HD_VERSION; - msg.hdr.payloadLen = sizeof( U08 ) + sizeof( U08 ) + sizeof( U16 ); + msg.hdr.payloadLen = sizeof( U08 ) + sizeof( U08 ) + sizeof( U08 ) + sizeof( U16 ); memcpy( payloadPtr, &major, sizeof( U08 ) ); payloadPtr += sizeof( U08 ); memcpy( payloadPtr, &minor, sizeof( U08 ) ); payloadPtr += sizeof( U08 ); + memcpy( payloadPtr, µ, sizeof( U08 ) ); + payloadPtr += sizeof( U08 ); memcpy( payloadPtr, &build, sizeof( U16 ) ); // serialize the message (w/ sync, CRC, and appropriate CAN padding) and add serialized message data to appropriate comm buffer Index: firmware/App/Services/SystemCommMessages.h =================================================================== diff -u -ra19a676d1e67bb3e1aca9e9bba49727f9d5f8b38 -r1017bbc5760a50e20357da1e4f705b3e6157375e --- firmware/App/Services/SystemCommMessages.h (.../SystemCommMessages.h) (revision a19a676d1e67bb3e1aca9e9bba49727f9d5f8b38) +++ firmware/App/Services/SystemCommMessages.h (.../SystemCommMessages.h) (revision 1017bbc5760a50e20357da1e4f705b3e6157375e) @@ -96,6 +96,9 @@ // MSG_ID_DG_SAMPLE_WATER_CMD BOOL sendDGSampleWaterCommand( void ); +// MSG_ID_DG_START_STOP_TRIMMER_HEATER_CMD +BOOL sendDGStartStopTrimmerHeaterCommand( BOOL start ); + // MSG_ID_DG_OP_MODE: void handleDGOpMode( MESSAGE_T *message );