Index: firmware/App/Controllers/SyringePump.c =================================================================== diff -u -r8cda0962f1683f3bbf63dba88fa1b9161ca89733 -r7c03cfb8116f1e29ef3dbc60f84f2e6f26481f5c --- firmware/App/Controllers/SyringePump.c (.../SyringePump.c) (revision 8cda0962f1683f3bbf63dba88fa1b9161ca89733) +++ firmware/App/Controllers/SyringePump.c (.../SyringePump.c) (revision 7c03cfb8116f1e29ef3dbc60f84f2e6f26481f5c) @@ -45,7 +45,8 @@ #define SYRINGE_STEPS_PER_REV 200.0 ///< Number of steps per revolution. #define MICRO_SECONDS_PER_SECOND 1000000.0 ///< Microseconds per second conversion. #define SYRINGE_TOGGLES_PER_STEP 2.0 ///< Stepper motor driver toggles per step or microstep. -#define SYRINGE_MICRO_STEPS_PER_STEP 32.0 ///< Micro-steps per step. +#define SYRINGE_MICRO_STEPS_PER_STEP 32.0 ///< Number of micro-steps per step. + /// Number of micro steps per revolution. #define SYRINGE_MICRO_STEPS_PER_REV ( SYRINGE_STEPS_PER_REV * SYRINGE_MICRO_STEPS_PER_STEP ) /// Number of encoder counts per mm. @@ -81,6 +82,8 @@ #define SYRINGE_PUMP_PRIME_VOLUME_ML 0.353 ///< Target syringe prime volume (in mL). #define SYRINGE_PUMP_MAX_VOL_ERROR_ML 0.1 ///< Maximum Heparin volume error (in mL). #define SYRINGE_PUMP_MAX_RATE_ERROR_ML_HR 0.1 ///< Maximum Heparin delivery rate error (in mL/hr). +#define TEN_PCT_OVER_ALLOWANCE 1.1 ///< Allow ten percent over target before alarming on over travel. +#define FIVE_PCT_OVER_ALLOWANCE 1.05 ///< Allow five percent over target before alarming on over travel. /// Expected position of empty in relation to home postion. #define SYRINGE_PUMP_EMPTY_POS ( SYRINGE_ENCODER_COUNTS_PER_ML * 11.0 ) @@ -143,7 +146,7 @@ NUM_OF_SYRINGE_PUMP_STATES ///< Number of syringe pump control states } SYRINGE_PUMP_STATE_T; -/// Defined states for the pressure and occlusion self-test state machine. +/// Defined states for the syringe pump self-test state machine. typedef enum Syringe_Pump_Self_Test_States { SYRINGE_PUMP_SELF_TEST_STATE_START = 0, ///< Self test start state. @@ -176,6 +179,7 @@ static S32 syringePumpVolumeStartPosition; ///< Start position for the current volume calculation. static S32 syringePumpHomePositionOffset; ///< FPGA reported position when at home postion. static S32 syringePumpPosition1SecAgo; ///< Position recorded at last 1 Hz speed check. +static MOTOR_DIR_T syringePumpMeasuredDirection; ///< Measured direction of syringe pump. static BOOL syringePumpRetractRequested; ///< Flag indicates a retract operation is requested. static BOOL syringePumpSeekRequested; ///< Flag indicates a plunger seek operation is requested. @@ -244,6 +248,7 @@ syringePumpVolumeStartPosition = 0; syringePumpHomePositionOffset = 0; syringePumpPosition1SecAgo = 0; + syringePumpMeasuredDirection = MOTOR_DIR_FORWARD; syringePumpDataPublicationTimerCounter = 0; syringePumpSelfTestTimerCount = 0; @@ -282,7 +287,7 @@ * The userHeparinRequest function handles a command request from the user * to pause or resume Heparin delivery. * @details Inputs: none - * @details Outputs: + * @details Outputs: heparinDeliveryState, syringePumpState, syringePumpContinuousRequested * @param cmd command from user * @return TRUE if request accepted, FALSE if not *************************************************************************/ @@ -806,6 +811,8 @@ calcSafetyVolumeDelivered(); // Calculate measured rate (mL/hr) calcMeasRate(); + // Get measured direction + syringePumpMeasuredDirection = ( ( encStatus & 0x80 ) != 0 ? MOTOR_DIR_REVERSE : MOTOR_DIR_FORWARD ); if ( syringePumpDACVrefWriteInProgress != TRUE ) { @@ -815,6 +822,18 @@ // activateAlarmNoData( ALARM_ID_HD_SYRINGE_PUMP_ADC_ERROR ); // TODO - restore when issue with read counter resolved } lastSyringePumpADCReadCtr = adcReadCtr; + + // Check encoder direction error. // TODO check direction in states + if ( ( encStatus & 0x3F ) != 0) + { + // TODO - alarm? + } + + // Check pump status + if ( pmpStatus != 0 ) + { + // TODO - pump failure fault + } } } @@ -975,8 +994,8 @@ * @brief * The handleSyringePumpRetractState function handles the retract state * of the syringe pump control state machine. - * @details Inputs: TBD - * @details Outputs: TBD + * @details Inputs: syringePumpMeasHome.data + * @details Outputs: Syringe pump ramped up to retract rate, alarm conditions checked * @return next state *************************************************************************/ static SYRINGE_PUMP_STATE_T handleSyringePumpRetractState( void ) @@ -990,16 +1009,24 @@ if ( TRUE == isSyringePumpHome() ) { stopSyringePump(); + // Set position to zero after retract reaches home position syringePumpHomePositionOffset = getFPGASyringePumpEncoderPosition(); syringePumpPosition.data = 0; syringePumpVolumeStartPosition = 0; syringePumpPositionKnown = TRUE; + // Zero volumes after retract syringePumpVolumeDelivered.data = 0.0; syringePumpSafetyVolumeDelivered = 0.0; + // Reset flags syringePumpPlungerFound = FALSE; syringePumpPrimeCompleted = FALSE; result = SYRINGE_PUMP_OFF_STATE; } + else if ( syringePumpMeasuredDirection != MOTOR_DIR_REVERSE ) + { + // TODO - alarm w/ some persistence + } + // TODO - if position know from prior retract, ensure we don't go lower than -TBD position return result; } @@ -1008,8 +1035,8 @@ * @brief * The handleSyringePumpSeekState function handles the seek plunger state * of the syringe pump control state machine. - * @details Inputs: TBD - * @details Outputs: TBD + * @details Inputs: syringePumpMeasForce.data + * @details Outputs: Syringe pump ramped up to seek rate, alarm conditions checked * @return next state *************************************************************************/ static SYRINGE_PUMP_STATE_T handleSyringePumpSeekState( void ) @@ -1036,6 +1063,10 @@ // Check for occlusion stopPump = checkOcclusionOrEmpty( stopPump ); + // TODO - check max position > TBD + + // TODO - calc estimate syringe volume - if insufficient for treatment needs, alarm + // If anything found that would require stopping the pump, stop pump and go to off state if ( TRUE == stopPump ) { @@ -1050,8 +1081,8 @@ * @brief * The handleSyringePumpPrimeState function handles the prime state * of the syringe pump control state machine. - * @details Inputs: TBD - * @details Outputs: TBD + * @details Inputs: syringePumpVolumeDelivered.data + * @details Outputs: Syringe pump ramped up to prime rate, alarm conditions checked * @return next state *************************************************************************/ static SYRINGE_PUMP_STATE_T handleSyringePumpPrimeState( void ) @@ -1079,7 +1110,7 @@ stopPump = checkOcclusionOrEmpty( stopPump ); // Check position > max travel - stopPump = checkMaxTravel( stopPump, syringePumpVolumeStartPosition * ( SYRINGE_PUMP_PRIME_VOLUME_ML * SYRINGE_ENCODER_COUNTS_PER_ML ) ); + stopPump = checkMaxTravel( stopPump, syringePumpVolumeStartPosition + ( SYRINGE_PUMP_PRIME_VOLUME_ML * TEN_PCT_OVER_ALLOWANCE * SYRINGE_ENCODER_COUNTS_PER_ML ) ); // If anything found that would require stopping the pump, stop pump and go to off state if ( TRUE == stopPump ) @@ -1094,8 +1125,8 @@ * @brief * The handleSyringePumpBolusState function handles the bolus delivery state * of the syringe pump control state machine. - * @details Inputs: TBD - * @details Outputs: TBD + * @details Inputs: set bolus volume, syringePumpVolumeDelivered.data + * @details Outputs: Syringe pump ramped up to set bolus rate, alarm conditions checked * @return next state *************************************************************************/ static SYRINGE_PUMP_STATE_T handleSyringePumpBolusState( void ) @@ -1126,7 +1157,7 @@ stopPump = checkMaxMeasRate( stopPump, SYRINGE_PUMP_RATE_CHECK_MARGIN ); // Check position > max travel - stopPump = checkMaxTravel( stopPump, syringePumpVolumeStartPosition * ( SYRINGE_PUMP_PRIME_VOLUME_ML * SYRINGE_ENCODER_COUNTS_PER_ML ) ); + stopPump = checkMaxTravel( stopPump, syringePumpVolumeStartPosition + ( bolusVol * FIVE_PCT_OVER_ALLOWANCE * SYRINGE_ENCODER_COUNTS_PER_ML ) ); // If anything found that would require stopping the pump, stop pump and go to off state if ( TRUE == stopPump ) @@ -1142,8 +1173,8 @@ * @brief * The handleSyringePumpContinuousState function handles the continuous state * of the syringe pump control state machine. - * @details Inputs: TBD - * @details Outputs: TBD + * @details Inputs: none + * @details Outputs: Syringe pump ramped up to set rate, alarm conditions checked * @return next state *************************************************************************/ static SYRINGE_PUMP_STATE_T handleSyringePumpContinuousState( void ) @@ -1201,16 +1232,22 @@ // Back to off state result = SYRINGE_PUMP_OFF_STATE; } + // Check DAC write error + else if ( ( adcDACStatus & 0x40 ) != 0 ) + { + // TODO - alarm + } + return result; } /*********************************************************************//** * @brief * The checkOcclusionOrEmpty function checks the force sensor for excessive * pressure. Would indicate occlusion or jam or empty syringe. - * @details Inputs: TBD - * @details Outputs: TBD + * @details Inputs: syringePumpMeasForce.data, syringePumpPosition.data + * @details Outputs: alarm triggered if max force detected * @param stopPump flag passed in by caller indicating whether pump should be stopped * @return TRUE if pump should be stopped, FALSE if not *************************************************************************/ @@ -1243,8 +1280,8 @@ * The checkSyringeRemoved function checks whether the syringe has been removed. * This function should only be called from states that require the syringe to * be installed. - * @details Inputs: TBD - * @details Outputs: TBD + * @details Inputs: syringePumpMeasSyringeDetectionSwitch.data + * @details Outputs: alarm triggered if syringe not detected * @param stopPump flag passed in by caller indicating whether pump should be stopped * @return TRUE if pump should be stopped, FALSE if not *************************************************************************/ @@ -1266,8 +1303,8 @@ * The checkMaxTravel function checks whether a maximum travel (position) * has been exceeded. This threshold is state dependent so the calling function * must provide the maximum position to apply. - * @details Inputs: TBD - * @details Outputs: TBD + * @details Inputs: syringePumpPosition.data + * @details Outputs: alarm triggered if beyond given max position * @param stopPump flag passed in by caller indicating whether pump should be stopped * @param maxPos maximum position allowed in current state * @return TRUE if pump should be stopped, FALSE if not @@ -1296,8 +1333,8 @@ * The checkMaxMeasRate function checks whether the measured rate is exceeding * a maximum rate (in mL/hr). This threshold is state dependent so the calling * function must provide the maximum rate to apply. - * @details Inputs: TBD - * @details Outputs: TBD + * @details Inputs: syringePumpMeasRate.data, syringePumpSetRate + * @details Outputs: alarm triggered if measured and set rates deviate too much * @param stopPump flag passed in by caller indicating whether pump should be stopped * @param pctMargin percent tolerance allowed between set and measured rate * @return TRUE if pump should be stopped, FALSE if not @@ -1328,8 +1365,8 @@ * and the safety volume delivered have diverged too much. The threshold * is state dependent so the calling function must provide the tolerance (in +/- %) * to apply. - * @details Inputs: TBD - * @details Outputs: TBD + * @details Inputs: syringePumpVolumeDelivered.data, syringePumpSafetyVolumeDelivered + * @details Outputs: alarm triggered if measured and expected volume deviate too much * @param stopPump flag passed in by caller indicating whether pump should be stopped * @param pctMargin percent tolerance allowed between volume and safety volume * @return TRUE if pump should be stopped, FALSE if not Index: firmware/App/Modes/Dialysis.c =================================================================== diff -u -rbcebe62009f076731c0e2ad77c4d5dd8eb67fc34 -r7c03cfb8116f1e29ef3dbc60f84f2e6f26481f5c --- firmware/App/Modes/Dialysis.c (.../Dialysis.c) (revision bcebe62009f076731c0e2ad77c4d5dd8eb67fc34) +++ firmware/App/Modes/Dialysis.c (.../Dialysis.c) (revision 7c03cfb8116f1e29ef3dbc60f84f2e6f26481f5c) @@ -231,7 +231,7 @@ F32 hepRate = getTreatmentParameterF32( TREATMENT_PARAM_HEPARIN_DISPENSE_RATE ); // Do not run syringe pump if no Heparin included in prescription or it was paused or if Heparin should be stopped at this stage of treatment - if ( ( minRem > preStop ) && ( ( HEPARIN_STATE_STOPPED == currentHeparinState ) || ( HEPARIN_STATE_PAUSED == currentHeparinState ) ) ) + if ( ( minRem > preStop ) && ( HEPARIN_STATE_STOPPED == currentHeparinState ) ) { // If not done with bolus, start/resume bolus if ( ( bolusVol > 0.0 ) && ( getSyringePumpVolumeDelivered() < bolusVol ) ) Index: firmware/App/Services/FPGA.c =================================================================== diff -u -re22cea17af706bcdaed705302094b096818147b0 -r7c03cfb8116f1e29ef3dbc60f84f2e6f26481f5c --- firmware/App/Services/FPGA.c (.../FPGA.c) (revision e22cea17af706bcdaed705302094b096818147b0) +++ firmware/App/Services/FPGA.c (.../FPGA.c) (revision 7c03cfb8116f1e29ef3dbc60f84f2e6f26481f5c) @@ -1395,7 +1395,7 @@ /*********************************************************************//** * @brief * The getFPGASyringePumpStatus function gets the latest syringe pump status - * register reading. + * register reading. Bit 0 indicates a fault. * @details Inputs: fpgaSensorReadings * @details Outputs: none * @return last syringe pump status reading @@ -1408,7 +1408,7 @@ /*********************************************************************//** * @brief * The getFPGASyringePumpADCReadCounter function gets the latest syringe pump - * ADC read counter. + * ADC read counter. Counter is 8-bit and rolls over when exceeding 255. * @details Inputs: fpgaSensorReadings * @details Outputs: none * @return last syringe pump ADC read counter @@ -1422,6 +1422,9 @@ * @brief * The getFPGASyringePumpADCandDACStatus function gets the latest syringe pump * ADC/DAC status register reading. + * Bit 7 = DAC write and read-back done + * Bit 6 = I2C error on DAC data transfer + * Bit 0..5 = count of I2C errors, rolls over after 63 * @details Inputs: fpgaSensorReadings * @details Outputs: none * @return last syringe pump ADC/DAC status reading @@ -1435,6 +1438,8 @@ * @brief * The getFPGASyringePumpEncoderStatus function gets the latest syringe pump * encoder status register reading. + * Bit 7 = direction (0=fwd, 1=rev) + * Bit 0..5 = direction error count (# of errors after power up, rolls over after 63) * @details Inputs: fpgaSensorReadings * @details Outputs: none * @return last syringe pump encoder status reading Index: firmware/App/Services/FPGA.h =================================================================== diff -u -r88fd90befbce61886ae47ad7d20ec863319cfa34 -r7c03cfb8116f1e29ef3dbc60f84f2e6f26481f5c --- firmware/App/Services/FPGA.h (.../FPGA.h) (revision 88fd90befbce61886ae47ad7d20ec863319cfa34) +++ firmware/App/Services/FPGA.h (.../FPGA.h) (revision 7c03cfb8116f1e29ef3dbc60f84f2e6f26481f5c) @@ -21,11 +21,18 @@ #include "HDCommon.h" #include "Interrupts.h" + /** * @defgroup FPGA FPGA * @brief FPGA service module. - * Maintains latest sensor readings at priority task interval. Updates actuator - * states at priority task interval. + * The FPGA module manages communication between the HD and the FPGA via UART. + * This module is driven by the Priority Task via calls to two FPGA executive functions: + * 1) an incoming executive manages the states of the state machine that deal with responses and data received from the FPGA + * 2) an outgoing executive manages transmission of write and read commands to the FPGA. + * This module first reads the header record that includes the FPGA ID and revision and + * verifies the FPGA ID to check FPGA communication. It then initializes and configures the ADCs and + * various other sensors that are interfaced via the FPGA. Then, it essentially enters an infinite loop + * where a bulk write command updates actuator set points and a bulk read command retrieves the latest sensor readings. * * @addtogroup FPGA * @{