Index: firmware/App/Controllers/BloodFlow.c =================================================================== diff -u -r6a6c064bdab77b9b42d25910d94da55812d00ffa -rd4850547b287cc1f94ea3617a1902c5278ea86b4 --- firmware/App/Controllers/BloodFlow.c (.../BloodFlow.c) (revision 6a6c064bdab77b9b42d25910d94da55812d00ffa) +++ firmware/App/Controllers/BloodFlow.c (.../BloodFlow.c) (revision d4850547b287cc1f94ea3617a1902c5278ea86b4) @@ -44,7 +44,7 @@ #define MAX_BLOOD_PUMP_PWM_DUTY_CYCLE 0.88 ///< controller will error if PWM duty cycle > 90%, so set max to 88% #define MIN_BLOOD_PUMP_PWM_DUTY_CYCLE 0.12 ///< controller will error if PWM duty cycle < 10%, so set min to 12% -#define BP_CONTROL_INTERVAL ( 1000 / TASK_GENERAL_INTERVAL ) ///< interval (ms/task time) at which the blood pump is controlled +#define BP_CONTROL_INTERVAL ( 10000 / TASK_GENERAL_INTERVAL ) ///< interval (ms/task time) at which the blood pump is controlled #define BP_P_COEFFICIENT 0.00005 ///< P term for blood pump control #define BP_I_COEFFICIENT 0.00015 ///< I term for blood pump control @@ -82,9 +82,7 @@ #define BLOODPUMP_ADC_ZERO 1998 ///< Blood pump ADC channel zero offset. #define SIGN_FROM_12_BIT_VALUE(v) ( (S16)(v) - (S16)BLOODPUMP_ADC_ZERO ) ///< macro converts 12 bit ADC value to signed 16-bit value. -#define BLOOD_FLOW_SAMPLE_FREQ ( MS_PER_SECOND / TASK_PRIORITY_INTERVAL ) ///< Blood flow sample frequency (in task intervals). -#define SIZE_OF_ROLLING_AVG ( BLOOD_FLOW_SAMPLE_FREQ * 2 ) ///< measured blood flow is filtered w/ moving average -#define MAX_FLOW_FILTER_INTERVAL 5 ///< slowest sample interval for filter is every 5th sample +#define SIZE_OF_ROLLING_AVG ( ( MS_PER_SECOND / TASK_PRIORITY_INTERVAL ) * 10 ) ///< measured blood flow is filtered w/ moving average /// Enumeration of blood pump controller states. typedef enum BloodPump_States @@ -158,7 +156,6 @@ static U32 flowReadingsIdx = 0; ///< index for next sample in rolling average array static F32 flowReadingsTotal = 0.0; ///< rolling total - used to calc average static U32 flowReadingsCount = 0; ///< number of samples in flow rolling average buffer -static U32 flowReadingsTmrCtr = 0; ///< determines when to add samples to filter static U32 bpCurrErrorDurationCtr = 0; ///< used for tracking persistence of bp current errors @@ -819,8 +816,11 @@ // TODO - temporary debug code - remove later char debugFlowStr[ 256 ]; -// sprintf( debugFlowStr, "Tgt:%5d, Flow:%5d, Speed:%5d RPM, Rotor:%5d RPM, Curr:%5d mA, PWM:%5d \n", flowStPt, (S32)measFlow, (S32)measMCSpd, (S32)measRotSpd, (S32)measMCCurr, (S32)pumpPWMPctDutyCycle ); - sprintf( debugFlowStr, "Tgt:%5d, Flow:%5d \n", flowStPt, (S32)measFlow ); +// F32 measFlowRaw = getFPGABloodFlow(); +// F32 dialFlow = getMeasuredDialInFlowRate(); +// F32 dialFlowRaw = getFPGADialysateFlow(); + sprintf( debugFlowStr, "Tgt:%5d, Flow:%5d, Speed-MC:%5d RPM, Speed:%5d RPM, Rotor:%5d RPM, Curr:%5d mA, PWM:%5d \n", flowStPt, (S32)measFlow, (S32)measMCSpd, (S32)measSpd, (S32)measRotSpd, (S32)measMCCurr, (S32)pumpPWMPctDutyCycle ); +// sprintf( debugFlowStr, "Blood: %5d, %5d Dial: %5d, %5d\n", (S32)measFlowRaw, (S32)measFlow, (S32)dialFlowRaw, (S32)dialFlow ); sendDebugData( (U08*)debugFlowStr, strlen(debugFlowStr) ); #endif broadcastBloodFlowData( flowStPt, measFlow, measRotSpd, measSpd, measMCSpd, measMCCurr, pumpPWMPctDutyCycle ); @@ -835,16 +835,13 @@ * @details * Inputs : none * Outputs : flowReadingsTotal, flowReadingsIdx, flowReadingsCount all set to zero. - * @param initFlow : the new blood flow set pt. - * @param flowDir : the new set direction * @return none *************************************************************************/ static void resetBloodFlowMovingAverage( void ) { - flowReadingsTotal = 0.0; flowReadingsIdx = 0; flowReadingsCount = 0; - flowReadingsTmrCtr = 0; + flowReadingsTotal = 0.0; bpControlTimerCounter = 0; } @@ -860,65 +857,15 @@ *************************************************************************/ static void filterBloodFlowReadings( F32 flow ) { - BOOL addSampleToFilter = FALSE; - - if ( ( targetBloodFlowRate.data < MIN_BLOOD_FLOW_RATE ) || ( targetBloodFlowRate.data >= MAX_BLOOD_FLOW_RATE ) ) + if ( flowReadingsCount >= SIZE_OF_ROLLING_AVG ) { - addSampleToFilter = TRUE; + flowReadingsTotal -= flowReadings[ flowReadingsIdx ]; } - else - { - switch ( flowReadingsTmrCtr ) - { - case 0: - addSampleToFilter = TRUE; - break; - - case 1: - addSampleToFilter = FALSE; - break; - - case 2: - if ( targetBloodFlowRate.data >= 400 ) - { - addSampleToFilter = TRUE; - } - break; - - case 3: - if ( targetBloodFlowRate.data >= 200 ) - { - addSampleToFilter = TRUE; - } - break; - - case 4: - if ( targetBloodFlowRate.data >= 300 ) - { - addSampleToFilter = TRUE; - } - break; - - default: - SET_ALARM_WITH_2_U32_DATA( ALARM_ID_SOFTWARE_FAULT, SW_FAULT_ID_BLOOD_FLOW_INVALID_FILTER_STATE, flowReadingsTmrCtr ) - break; - } - } - - if ( TRUE == addSampleToFilter ) - { - if ( flowReadingsCount >= SIZE_OF_ROLLING_AVG ) - { - flowReadingsTotal -= flowReadings[ flowReadingsIdx ]; - } - flowReadings[ flowReadingsIdx ] = flow; - flowReadingsTotal += flow; - flowReadingsIdx = INC_WRAP( flowReadingsIdx, 0, SIZE_OF_ROLLING_AVG - 1 ); - flowReadingsCount = INC_CAP( flowReadingsCount, SIZE_OF_ROLLING_AVG ); - measuredBloodFlowRate.data = flowReadingsTotal / (F32)flowReadingsCount; - } - - flowReadingsTmrCtr = INC_WRAP( flowReadingsTmrCtr, 0, MAX_FLOW_FILTER_INTERVAL - 1 ); + flowReadings[ flowReadingsIdx ] = flow; + flowReadingsTotal += flow; + flowReadingsIdx = INC_WRAP( flowReadingsIdx, 0, SIZE_OF_ROLLING_AVG - 1 ); + flowReadingsCount = INC_CAP( flowReadingsCount, SIZE_OF_ROLLING_AVG ); + measuredBloodFlowRate.data = flowReadingsTotal / (F32)flowReadingsCount; } /*********************************************************************//** Index: firmware/App/Controllers/DialInFlow.c =================================================================== diff -u -r186d10f0644b9726f1a632197a0ccfba7b00bf48 -rd4850547b287cc1f94ea3617a1902c5278ea86b4 --- firmware/App/Controllers/DialInFlow.c (.../DialInFlow.c) (revision 186d10f0644b9726f1a632197a0ccfba7b00bf48) +++ firmware/App/Controllers/DialInFlow.c (.../DialInFlow.c) (revision d4850547b287cc1f94ea3617a1902c5278ea86b4) @@ -45,7 +45,7 @@ #define MAX_DIAL_IN_PUMP_PWM_DUTY_CYCLE 0.88 ///< controller will error if PWM duty cycle > 90%, so set max to 88% #define MIN_DIAL_IN_PUMP_PWM_DUTY_CYCLE 0.12 ///< controller will error if PWM duty cycle < 10%, so set min to 12% -#define DIP_CONTROL_INTERVAL ( 1000 / TASK_GENERAL_INTERVAL ) ///< interval (ms/task time) at which the dialIn pump is controlled +#define DIP_CONTROL_INTERVAL ( 10000 / TASK_GENERAL_INTERVAL ) ///< interval (ms/task time) at which the dialIn pump is controlled #define DIP_P_COEFFICIENT 0.00005 ///< P term for dialIn pump control #define DIP_I_COEFFICIENT 0.00015 ///< I term for dialIn pump control @@ -83,9 +83,7 @@ #define DIAL_IN_PUMP_ADC_ZERO 1998 ///< Mid-point (zero) for ADC readings. #define SIGN_FROM_12_BIT_VALUE(v) ( (S16)(v) - (S16)DIAL_IN_PUMP_ADC_ZERO ) ///< Macro converts a 12-bit ADC reading to a signed 16-bit value. -#define DIAL_IN_FLOW_SAMPLE_FREQ ( MS_PER_SECOND / TASK_PRIORITY_INTERVAL ) ///< -#define SIZE_OF_ROLLING_AVG ( DIAL_IN_FLOW_SAMPLE_FREQ * 2 ) ///< measured dialIn flow is filtered w/ moving average -#define MAX_FLOW_FILTER_INTERVAL 5 ///< slowest sample interval for filter is every 5th sample +#define SIZE_OF_ROLLING_AVG ( ( MS_PER_SECOND / TASK_PRIORITY_INTERVAL ) * 10 ) ///< measured dialIn flow is filtered w/ moving average /// Enumeration of dialysate inlet pump states. typedef enum DialInPump_States @@ -761,10 +759,9 @@ *************************************************************************/ static void resetDialInFlowMovingAverage( void ) { - flowReadingsTotal = 0.0; flowReadingsIdx = 0; flowReadingsCount = 0; - flowReadingsTmrCtr = 0; + flowReadingsTotal = 0.0; dipControlTimerCounter = 0; } @@ -775,70 +772,19 @@ * @details * Inputs : none * Outputs : flowReadings[], flowReadingsIdx, flowReadingsCount - * @param flow : newest dialIn flow sample * @return none *************************************************************************/ static void filterDialInFlowReadings( F32 flow ) { - BOOL addSampleToFilter = FALSE; - - if ( ( targetDialInFlowRate.data < MIN_DIAL_IN_FLOW_RATE ) || ( targetDialInFlowRate.data >= MAX_DIAL_IN_FLOW_RATE ) ) + if ( flowReadingsCount >= SIZE_OF_ROLLING_AVG ) { - addSampleToFilter = TRUE; + flowReadingsTotal -= flowReadings[ flowReadingsIdx ]; } - else - { - switch ( flowReadingsTmrCtr ) - { - case 0: - addSampleToFilter = TRUE; - break; - - case 1: - addSampleToFilter = FALSE; - break; - - case 2: - if ( targetDialInFlowRate.data >= 400 ) - { - addSampleToFilter = TRUE; - } - break; - - case 3: - if ( targetDialInFlowRate.data >= 200 ) - { - addSampleToFilter = TRUE; - } - break; - - case 4: - if ( targetDialInFlowRate.data >= 300 ) - { - addSampleToFilter = TRUE; - } - break; - - default: - SET_ALARM_WITH_2_U32_DATA( ALARM_ID_SOFTWARE_FAULT, SW_FAULT_ID_DIAL_IN_FLOW_INVALID_FILTER_STATE, flowReadingsTmrCtr ) - break; - } - } - - // if it's time to add sample to filter, add it. - if ( TRUE == addSampleToFilter ) - { - if ( flowReadingsCount >= SIZE_OF_ROLLING_AVG ) - { - flowReadingsTotal -= flowReadings[ flowReadingsIdx ]; - } - flowReadings[ flowReadingsIdx ] = flow; - flowReadingsTotal += flow; - flowReadingsIdx = INC_WRAP( flowReadingsIdx, 0, SIZE_OF_ROLLING_AVG - 1 ); - flowReadingsCount = INC_CAP( flowReadingsCount, SIZE_OF_ROLLING_AVG ); - measuredDialInFlowRate.data = flowReadingsTotal / (F32)flowReadingsCount; - } - flowReadingsTmrCtr = INC_WRAP( flowReadingsTmrCtr, 0, MAX_FLOW_FILTER_INTERVAL - 1 ); + flowReadings[ flowReadingsIdx ] = flow; + flowReadingsTotal += flow; + flowReadingsIdx = INC_WRAP( flowReadingsIdx, 0, SIZE_OF_ROLLING_AVG - 1 ); + flowReadingsCount = INC_CAP( flowReadingsCount, SIZE_OF_ROLLING_AVG ); + measuredDialInFlowRate.data = flowReadingsTotal / (F32)flowReadingsCount; } /*********************************************************************//** Index: firmware/App/Modes/ModeTreatment.c =================================================================== diff -u -r51147222d369a3023a11b2ee675178d058ffaf46 -rd4850547b287cc1f94ea3617a1902c5278ea86b4 --- firmware/App/Modes/ModeTreatment.c (.../ModeTreatment.c) (revision 51147222d369a3023a11b2ee675178d058ffaf46) +++ firmware/App/Modes/ModeTreatment.c (.../ModeTreatment.c) (revision d4850547b287cc1f94ea3617a1902c5278ea86b4) @@ -40,6 +40,7 @@ // ********** private definitions ********** #define MAX_TREATMENT_TIME_MINUTES ( 8 * MIN_PER_HOUR ) ///< Maximum treatment time (in minutes). +#define MIN_TREATMENT_TIME_MINUTES ( 1 * MIN_PER_HOUR ) ///< Minimum treatment time (in minutes). #define MAX_UF_RATE_ML_MIN ( (F32)2500 / (F32)MIN_PER_HOUR ) ///< Maximum ultrafiltration rate (in mL/min). #define MAX_UF_VOLUME_ML ( 8 * ML_PER_LITER ) ///< Maximum ultrafiltration volume (in mL). #define MAX_DIALYSATE_VOLUME_ML ( 180 * ML_PER_LITER ) ///< Maximum dialysate volume (in mL). @@ -370,7 +371,7 @@ // check if we are in an appropriate treatment state for settings adjustment if ( ( MODE_TREA == currMode ) && ( currentTreatmentState > TREATMENT_START_STATE ) && ( currentTreatmentState < TREATMENT_DIALYSIS_END_STATE ) && - ( CALC_ELAPSED_TREAT_TIME_IN_MIN() < treatmentTime ) ) + ( CALC_ELAPSED_TREAT_TIME_IN_MIN() < treatmentTime ) && ( treatmentTime >= MIN_TREATMENT_TIME_MINUTES ) ) { F32 uFVolume; U32 dialVolume = presDialysateFlowRate * treatmentTime; // in mL @@ -413,6 +414,10 @@ { rejectReason = REQUEST_REJECT_REASON_INVALID_TREATMENT_STATE; } + else if ( treatmentTime < MIN_TREATMENT_TIME_MINUTES ) + { + rejectReason = REQUEST_REJECT_REASON_TREATMENT_TIME_LESS_THAN_MINIMUM; + } else { rejectReason = REQUEST_REJECT_REASON_TREATMENT_TIME_LESS_THAN_CURRENT; @@ -478,8 +483,9 @@ pendingUFRateChange = uFRate; rateDiff = ( uFRate - presUFRate ); - // verify treatment duration change would be valid - if ( ( trtTime <= MAX_TREATMENT_TIME_MINUTES ) && ( dialVolume <= MAX_DIALYSATE_VOLUME_ML ) ) + // verify treatment duration change would be valid (leave zero if not valid - UI will disable option) + if ( ( trtTime <= MAX_TREATMENT_TIME_MINUTES ) && ( trtTime >= MIN_TREATMENT_TIME_MINUTES ) && + ( dialVolume <= MAX_DIALYSATE_VOLUME_ML ) ) { pendingTreatmentTimeChange = trtTime; timeDiff = trtTime - ( (U32)( (F32)presTreatmentTimeSecs / (F32)SEC_PER_MIN ) + 1 );