Index: firmware/App/Controllers/Valves.c =================================================================== diff -u -r306243570641956ce4e2303380c9c0a02801726d -rb1c2d54d3d029ab1340d91193a7a4c81db8ba29d --- firmware/App/Controllers/Valves.c (.../Valves.c) (revision 306243570641956ce4e2303380c9c0a02801726d) +++ firmware/App/Controllers/Valves.c (.../Valves.c) (revision b1c2d54d3d029ab1340d91193a7a4c81db8ba29d) @@ -67,7 +67,8 @@ #define AIR_TRAP_VALVE_GPIO_PIN 0x12 ///< Air trap valve GPIO pin number -#define STEP_CHANGE_IN_COUNTS 1000 ///< Step change in counts +#define HOMING_STEP_CHANGE_IN_COUNTS 1000 ///< Step change in counts during homing +#define TRANSITION_STEP_CHANGE_IN_COUNTS 13000 ///< Step change in counts during normal operations #define MAX_DEVIATION_FROM_TARGET_IN_COUNTS 150 ///< Maximum deviation from target in counts #define MAX_ALLOWED_FAILED_HOMINGS 3U ///< Maximum allowed failed homings @@ -80,12 +81,11 @@ // TODO changed the interval count to every 10 calls in priority task which is 100 ms #define VALVES_DATA_PUB_INTERVAL ( MS_PER_SECOND / ( 10 * TASK_PRIORITY_INTERVAL ) ) ///< Valve data publication time interval -#define VALVE_MAX_ALLOWED_PWM_PERCENT 90U ///< Valve maximum allowed PWM in percent -#define VALVE_MIN_ALLOWED_PWM_PERCENT 10U ///< Valve minimum allowed PWM in percent -#define VALVE_CW_PWM_TO_CNT_CONVERSION( pwm ) ( ( 22.222 * pwm ) + 2500 ) ///< Valve clockwise PWM to count conversion -#define VALVE_CW_CNT_TO_PWM_CONVERSION( cnt ) ( ( 0.045 * cnt ) - 112.5 ) ///< Valve clockwise count to PWM conversion -#define VALVE_CCW_PWM_TO_CNT_CONVERSION( pwm ) ( ( -22.222 * pwm ) + 2500 ) ///< Valve counter clockwise PWM to count conversion -#define VALVE_CCW_CNT_TO_PWM_CONVERSION( cnt ) ( ( -0.045 * cnt ) + 112.5 ) ///< Valve counter clockwise count to PWM conversion +#define VALVE_MAX_ALLOWED_PWM_PERCENT 100U ///< Valve maximum allowed PWM in percent +#define VALVE_CW_PWM_TO_CNT_CONVERSION( pwm ) ( ( 20 * pwm ) + 2500 ) ///< Valve clockwise PWM to count conversion +#define VALVE_CW_CNT_TO_PWM_CONVERSION( cnt ) ( ( 0.05 * cnt ) - 125 ) ///< Valve clockwise count to PWM conversion +#define VALVE_CCW_PWM_TO_CNT_CONVERSION( pwm ) ( ( -20 * pwm ) + 2500 ) ///< Valve counter clockwise PWM to count conversion +#define VALVE_CCW_CNT_TO_PWM_CONVERSION( cnt ) ( ( -0.05 * cnt ) + 125 ) ///< Valve counter clockwise count to PWM conversion // ********** private data ********** @@ -132,8 +132,8 @@ typedef enum valve_bypass_mode_direction { - CLOCKWISE = 0, ///< Clockwise direction in bypass mode - COUNTERCLOCKWISE, ///< Counter clockwise direction in bypass mode + VAVLE_DIR_CLOCKWISE = 0, ///< Clockwise direction in bypass mode + VALVE_DIR_COUNTERCLOCKWISE, ///< Counter clockwise direction in bypass mode NUM_OF_VALVE_DIRECTION ///< Number of valve directions } VALVE_DIRECTION_T; @@ -224,7 +224,7 @@ static void getAndMonitorValvesCurrentPosition( void ); static DATA_GET_PROTOTYPE( U32, getPublishValvesDataInterval ); static void publishValvesData( VALVE_T valve ); -static void setValveNextStep( VALVE_T valve ); +static void setValveNextStep( VALVE_T valve, U32 stepChange ); static void setFPGAValvePWM( VALVE_T valve ); static void getValvesCurrentPWM( void ); @@ -530,7 +530,7 @@ { // Get ready for the energized state valvesStatus[ valve ].homingEdgeDetectionCounter = 0; - valvesStatus[ valve ].targetPositionInCounts = valvesStatus[ valve ].currentPositionInCounts + STEP_CHANGE_IN_COUNTS; + valvesStatus[ valve ].targetPositionInCounts = valvesStatus[ valve ].currentPositionInCounts + HOMING_STEP_CHANGE_IN_COUNTS; valvesStatus[ valve ].hasValveBeenHomed = FALSE; valvesStatus[ valve ].currentPosition = VALVE_POSITION_NOT_IN_POSITION; setFPGAValveSetPoint( valve, valvesStatus[ valve ].targetPositionInCounts, FALSE ); @@ -567,7 +567,7 @@ // Current position (positive or negative) will be stored in the Position B of the current valve valvesStatus[ valve ].positions[ VALVE_POSITION_B_OPEN ] = currentPosition; valvesStatus[ valve ].homingEdgeDetectionCounter = 0; - valvesStatus[ valve ].targetPositionInCounts = currentPosition - STEP_CHANGE_IN_COUNTS; + valvesStatus[ valve ].targetPositionInCounts = currentPosition - HOMING_STEP_CHANGE_IN_COUNTS; setFPGAValveSetPoint( valve, valvesStatus[ valve ].targetPositionInCounts, FALSE ); state = VALVE_STATE_HOMING_FIND_DEENERGIZED_EDGE; @@ -577,7 +577,7 @@ if ( valvesStatus[ valve ].restCounter >= 0 )//TODO add a #define for the rest time. Do we need the rest? { valvesStatus[ valve ].homingEdgeDetectionCounter = 0; - valvesStatus[ valve ].targetPositionInCounts = currentPosition + STEP_CHANGE_IN_COUNTS; + valvesStatus[ valve ].targetPositionInCounts = currentPosition + HOMING_STEP_CHANGE_IN_COUNTS; setFPGAValveSetPoint( valve, valvesStatus[ valve ].targetPositionInCounts, FALSE ); } } @@ -621,7 +621,7 @@ valvesStatus[ valve ].positions[ VALVE_POSITION_A_INSERT_EJECT ] = ( valvesStatus[ valve ].positions[ VALVE_POSITION_B_OPEN ] - valvesStatus[ valve ].positions[ VALVE_POSITION_C_CLOSE ] ) / 2; - // Set the current position to Position C and the commanded position to Position A // Request a transition + // Set the current position to Position C and the commanded position to Position A valvesStatus[ valve ].hasValveBeenHomed = TRUE; valvesStatus[ valve ].currentPosition = VALVE_POSITION_C_CLOSE; valvesStatus[ valve ].commandedPosition = VALVE_POSITION_A_INSERT_EJECT; @@ -652,7 +652,7 @@ if ( valvesStatus[ valve ].restCounter >= 0 ) //TODO add a #define for the rest time. Do we need the rest? { valvesStatus[ valve ].homingEdgeDetectionCounter = 0; - valvesStatus[ valve ].targetPositionInCounts = currentPosition - STEP_CHANGE_IN_COUNTS; + valvesStatus[ valve ].targetPositionInCounts = currentPosition - HOMING_STEP_CHANGE_IN_COUNTS; setFPGAValveSetPoint( valve, valvesStatus[ valve ].targetPositionInCounts, FALSE ); } } @@ -685,12 +685,17 @@ { // Just set the valves to transition so it will not be in a known position for a while valvesStatus[ valve ].transitionStartTime = getMSTimerCount(); - setValveNextStep( valve ); + setValveNextStep( valve, TRANSITION_STEP_CHANGE_IN_COUNTS ); state = VALVE_STATE_IN_TRANSITION; } + else + { + valvesStatus[ valve ].hasTransitionBeenRequested = FALSE; + } } - // TODO add build switch here +// This option is only available in a debug build +#ifdef VALVES_PWM_CONTROL_ENABLED // Check if the valves have been homed and a bypass mode has been requested else if ( valvesStatus[ valve ].hasValveBeenHomed && valvesStatus[ valve ].bypassModeStatus.hasBypassModeBeenRequeseted ) @@ -703,6 +708,7 @@ state = VALVE_STATE_IN_BYPASS_MODE; } +#endif return state; } @@ -736,6 +742,7 @@ // Set the transition request to false as it has been serviced valvesStatus[ valve ].hasTransitionBeenRequested = FALSE; + // If we are in Pos B, enable current relaxation if ( commandedPositionEnum == VALVE_POSITION_B_OPEN ) { setFPGAValveSetPoint( valve, currentPosition, TRUE ); @@ -752,9 +759,9 @@ state = VALVE_STATE_IDLE; SET_ALARM_WITH_1_U32_DATA( ALARM_ID_HD_VALVE_TRANSITION_TIMEOUT, (U32)valve ); } - else if ( currentPosition - targetPosition < MAX_DEVIATION_FROM_TARGET_IN_COUNTS ) + else if ( currentPosition - targetPosition > MAX_DEVIATION_FROM_TARGET_IN_COUNTS ) { - setValveNextStep( valve ); + setValveNextStep( valve, TRANSITION_STEP_CHANGE_IN_COUNTS ); } return state; @@ -774,35 +781,27 @@ { VALVE_STATE_T state = VALVE_STATE_IN_BYPASS_MODE; - // Get the positions counts - S16 currentPos = valvesStatus[ valve ].currentPositionInCounts; - S16 posAInCounts = valvesStatus[ valve ].positions[ VALVE_POSITION_B_OPEN ]; - S16 posCInCounts = valvesStatus[ valve ].positions[ VALVE_POSITION_C_CLOSE ]; - // If bypass mode has been turned off if ( valvesStatus[ valve ].bypassModeStatus.hasBypassModeBeenRequeseted == FALSE ) { // Change the control mode to PID setValveControlMode( valve, VALVE_CONTROL_MODE_ENABLE_PID ); valvesStatus[ valve ].controlMode = VALVE_CONTROL_MODE_ENABLE_PID; - // Set the PWM to 0% and set it - valvesStatus[ valve ].bypassModeStatus.commandedPWMInPercent = 0; - setFPGAValvePWM( valve ); + // Request a change of position to get back to the last known position in PID mode + // It is assumed that the valve is currently in a unknown position and it is commanded + // to go back Position A + valvesStatus[ valve ].currentPosition = VALVE_POSITION_NOT_IN_POSITION; + valvesStatus[ valve ].commandedPosition = VALVE_POSITION_A_INSERT_EJECT; + valvesStatus[ valve ].hasTransitionBeenRequested = TRUE; + state = VALVE_STATE_IDLE; } - // If a valve change either a change in CW or CCW or PWM has changed, set the new valve + // If a valve change either a change in CW or CCW or PWM has changed, set the new valve PWM else if ( valvesStatus[ valve ].bypassModeStatus.hasChangeBeenRequested ) { setFPGAValvePWM( valve ); } - // If the current position is close to either pos B or pos C, stop the valve from moving - if( abs( currentPos - posAInCounts ) < MAX_DEVIATION_FROM_TARGET_IN_COUNTS || - abs( currentPos - posCInCounts ) < MAX_DEVIATION_FROM_TARGET_IN_COUNTS ) - { - valvesStatus[ valve ].bypassModeStatus.commandedPWMInPercent = 0; - setFPGAValvePWM( valve ); - } return state; } @@ -856,8 +855,9 @@ // Get the current PWM values back. // This function is only available if the valves are in bypass mode - //TODO add build switch +#ifdef VALVES_PWM_CONTROL_ENABLED getValvesCurrentPWM(); +#endif } /*********************************************************************//** @@ -876,21 +876,14 @@ VALVE_MODE_T mode; BOOL result = TRUE; - /*VALVE_CONTROL_STATUS_INITIALIZED = 0, - VALVE_CONTROL_STATUS_PID_ENABLED, - VALVE_CONTROL_STATUS_BYPASS_ENABLED, - NUM_OF_VALVE_CONTROL_STATUS - - VALVE_CONTROL_MODE_ENABLE_PID = 0, - VALVE_CONTORL_MODE_ENABLE_BYPASS, - VALVE_CONTROL_MODE_DISABLE_ALL,*/ - + // Get the status of the valves from FPGA U16 status = getFPGAValvesStatus(); for ( valve = VDI; valve < NUM_OF_VALVES; valve++ ) { mode = valvesStatus[ valve ].controlMode; + // Depending on the control mode of the valve, different bit masks will be checked if ( mode == VALVE_CONTROL_MODE_ENABLE_PID ) { if ( ! ( status & valvesControlStatusBits[ valve ][ VALVE_CONTROL_STATUS_INITIALIZED ] ) ) @@ -942,6 +935,7 @@ // Always set the MSB of the S16 to 0 position &= DISABLE_VALVE_CURRENT_RELAXATION; + // If current relaxation is needed, set the MSB to 1 if ( enableCurrentRelaxation ) { position |= ENABLE_VALVE_CURRENT_RELAXATION; @@ -1123,6 +1117,7 @@ valveData.posC = valvesStatus[ valve ].positions[ VALVE_POSITION_C_CLOSE ]; valveData.posA = valvesStatus[ valve ].positions[ VALVE_POSITION_A_INSERT_EJECT ]; valveData.posB = valvesStatus[ valve ].positions[ VALVE_POSITION_B_OPEN ]; + valveData.pwm = valvesStatus[ valve ].bypassModeStatus.currentPWMInPercent; broadcastHDValves( &valveData ); @@ -1147,7 +1142,7 @@ * @param valve that its next step is calculated and set * @return none *************************************************************************/ -static void setValveNextStep( VALVE_T valve ) +static void setValveNextStep( VALVE_T valve, U32 stepChange ) { S16 nextStep = 0; S16 targetPosition = 0; @@ -1157,13 +1152,13 @@ S16 commandedPosition = valvesStatus[ valve ].positions[ commandedPositionEnum ]; // If the next step is less than the specified step change, set that - if ( abs( currentPosition - commandedPosition ) <= STEP_CHANGE_IN_COUNTS ) + if ( abs( currentPosition - commandedPosition ) <= stepChange ) { nextStep = abs( currentPosition - commandedPosition ); } else { - nextStep = STEP_CHANGE_IN_COUNTS; + nextStep = stepChange; } // If the valve is currently in position A and its commanded position is position B, // add the defined number of steps for the next transition @@ -1175,7 +1170,7 @@ { valvesStatus[ valve ].targetPositionInCounts = valvesStatus[ valve ].currentPositionInCounts + nextStep; - if( nextStep < STEP_CHANGE_IN_COUNTS ) + if( nextStep < stepChange ) { targetPosition = valvesStatus[ valve ].targetPositionInCounts; } @@ -1203,7 +1198,7 @@ { valvesStatus[ valve ].targetPositionInCounts = valvesStatus[ valve ].currentPositionInCounts + nextStep; - if ( nextStep < STEP_CHANGE_IN_COUNTS && commandedPositionEnum == VALVE_POSITION_B_OPEN ) + if ( nextStep < HOMING_STEP_CHANGE_IN_COUNTS && commandedPositionEnum == VALVE_POSITION_B_OPEN ) { targetPosition = valvesStatus[ valve ].targetPositionInCounts; } @@ -1235,7 +1230,7 @@ U16 commandedPWMPct = valvesStatus[ valve ].bypassModeStatus.commandedPWMInPercent; // Check the requested direction and convert PWM in percent to counts - if ( valvesStatus[ valve ].bypassModeStatus.direction == CLOCKWISE ) + if ( valvesStatus[ valve ].bypassModeStatus.direction == VAVLE_DIR_CLOCKWISE ) { pwmInCounts = VALVE_CW_PWM_TO_CNT_CONVERSION( commandedPWMPct ); } @@ -1247,23 +1242,19 @@ switch ( valve ) { case VDI: - setFPGAValveDialyzerInletPWM( pwmInCounts ); break; case VDO: - setFPGAValveDialyzerOutletPWM( pwmInCounts ); break; case VBA: - - setFPGAValveBloodVenousPWM( pwmInCounts ); + setFPGAValveBloodArterialPWM( pwmInCounts ); break; case VBV: - - setFPGAValveBloodArterialPWM( pwmInCounts ); + setFPGAValveBloodVenousPWM( pwmInCounts ); break; default: @@ -1296,7 +1287,7 @@ currentPWM = pwmInCounts[ valve ]; // Check if the direction is clockwise or not to use the right conversion equation - if ( valvesStatus[ valve ].bypassModeStatus.direction == CLOCKWISE ) + if ( valvesStatus[ valve ].bypassModeStatus.direction == VAVLE_DIR_CLOCKWISE ) { currentPWM = VALVE_CW_CNT_TO_PWM_CONVERSION( currentPWM ); } @@ -1305,7 +1296,7 @@ currentPWM = VALVE_CCW_CNT_TO_PWM_CONVERSION( currentPWM ); } - valvesStatus[ valve ].bypassModeStatus.currentPWMInPercent = currentPWM * 100; + valvesStatus[ valve ].bypassModeStatus.currentPWMInPercent = currentPWM; } } @@ -1439,16 +1430,22 @@ // Check if the valve is in the range of the valves available if ( valve < NUM_OF_VALVES ) { - // The PWM should be in range and also the valve direction should be legal - if ( pwm >= VALVE_MIN_ALLOWED_PWM_PERCENT && pwm <= VALVE_MAX_ALLOWED_PWM_PERCENT && direction < NUM_OF_VALVE_DIRECTION ) + BOOL homingStatus = valvesStatus[ valve ].hasValveBeenHomed; + + // The PWM should be in range and also the valve direction should be legal and the valve must have been homed + // prior to running this command + if ( pwm <= VALVE_MAX_ALLOWED_PWM_PERCENT && direction < NUM_OF_VALVE_DIRECTION && homingStatus ) { valvesStatus[ (VALVE_T)valve ].bypassModeStatus.commandedPWMInPercent = (U16)pwm; valvesStatus[ (VALVE_T)valve ].bypassModeStatus.direction = (VALVE_DIRECTION_T)direction; + // This flag sets the valves to bypass mode in the idle state. After that the valve will be sitting in the + // bypass mode until this flag is set to FALSE in the reset function. valvesStatus[ (VALVE_T)valve ].bypassModeStatus.hasBypassModeBeenRequeseted = TRUE; + // This flag is used to check if a change in PWM has been requested so the new PWM is processed and set valvesStatus[ (VALVE_T)valve ].bypassModeStatus.hasChangeBeenRequested = TRUE; - } - result = TRUE; + result = TRUE; + } } }