User:Steven J. Koch/Notebook/Kochlab/2009/06/29/Feedback 96 Debugging/Richard Yeh stop condition C dcode

From OpenWetWare

Jump to: navigation, search

Richard Yeh's C code for the stop condition

/*	feedback0B-stop_condition.c
 *	
 *	2000 Nov 12	SJK & RCY
 *		This file contains the definition of the function that
 *		checks various conditions to decide whether to exit the
 *		feedback loop.  It's supposed to be compatible with the
 *		force clamp and velocity clamp programs written by SJK.
 *
 *		Feedback programs that use this function can be dropped
 *		into the versatile feedback program (currently under development)
 *		as individual feedback steps.  Some other restrictions,
 *		not enumerated here, also apply to the programs used in
 *		that manner.
 *		
 *		The conditions that we check (reference 001019 e-mail) are:
 *
 *			+ Trap position moved out of specified range
 *				(this is not necessarily the absolute range
 *				 of the instrument, which is checked separately)
 *			+ Trap power set out of specified range
 *			+ Feedback set point reached
 *				(process variable within some percent of process variable)
 *			+ Number of data points taken exceeds value
 *			+ Number of data points taken after set point first reached
 *
 *		Multiple conditions may be specified. When this is the case,
 *		a global logical OR or logical AND will be applied.
 *
 *		Through some conversions performed within the LabVIEW VIs
 *		that specify the feedback steps and exit conditions
 *		(see 'Feedback0B-Edit Feedback Step-Main.vi') these exit
 *		conditions cover:
 *
 *			+ Force exceeds some value (velocity clamp; position fixed)
 *			+ Time exceeds some value (number of data points, given loop time)
 *			+ Time after set point first reached exceeds some value
 */

/*	The 32-bit integer condition encodes the conditions
 *	that would cause the program to stop.  It's also
 *	used as a status value.  The bit field is arranged
 *	as described below:
 */

//	The least-significant 12 bits are more important
//	bits 1-4:	
#define	CONDITIONFOOTSWITCHRELEASED			0x00000001
#define	CONDITIONDATAARRAYFULL				0x00000008
//	bits 5-8:	unused
//	bits 9-12:	hard limits on AOD 2
#define	CONDITIONHARDAOD2FREQHIGH			0x00000100
#define	CONDITIONHARDAOD2FREQLOW			0x00000200
#define	CONDITIONHARDAOD2VOLTHIGH			0x00000400
#define	CONDITIONHARDAOD2VOLTLOW			0x00000800
//	bits 13-16:	unused
//	bits 17-20:	soft limits on AOD 2
#define	CONDITIONSOFTAOD2FREQHIGH			0x00010000
#define	CONDITIONSOFTAOD2FREQLOW			0x00020000
#define	CONDITIONSOFTAOD2VOLTHIGH			0x00040000
#define	CONDITIONSOFTAOD2VOLTLOW			0x00080000
//	bits 21-24:	PID and other software-related limits
#define	CONDITIONSETPOINTREACHED			0x00100000
#define	CONDITIONNUMBEROFDATAPOINTS			0x00200000
#define	CONDITIONDATAPOINTSAFTERSETPOINT	0x00400000

//	bits 13-24: these are used in the logical AND computation
#define	BITSFORLOGICALAND					0x00FFF000

//	The next-most-significant 2 bits: error conditions
#define	ERRORCOMPAREVALUES					0x10000000
//	The most significant bit: AND or OR conditions for bits 13-24?
#define	CONDITIONLOGICALAND					0x80000000

//	either MHz or volts
#define	TWEAK001	0.00001

#include "Eserrlp.h"//"E series Register Level Programming"
#include "feedback0b-stop_condition.h"

/*	compare_stop_condition_values
 *	2000 Nov 13	RCY
 *	This function first checks whether condition contains all the bits
 *	set in returnval.  If not, then the function returns 0x0.
 *	If condition does contain the bits in returnval, then the function
 *	compares the values of a and b.
 *	If a < b, then the function returns 0x0.  Otherwise, it returns returnval.
 */
__int32 compare_stop_condition_values
	(__int32 condition, __int32 returnval, double a, double b)
{
	if (0x0 != (returnval & condition))
		//	then we must check
	{
		if (! (a < b))	//	then values are not in the proper order
		{
			return returnval;
		}
	}
	return	0x0;	//	nothing to check, or values are fine, not triggering stop condition
}


unsigned __int32	stop_condition_reached (
	unsigned __int32	condition,		//	packed integer as described above
	unsigned __int16	footswitch_dio_port,	//	packed integer selecting port to which footswitch is wired

	double	hardlimit_aod2_freq_high,
	double	hardlimit_aod2_freq_low,
	double	hardlimit_aod2_volt_high,
	double	hardlimit_aod2_volt_low,

	double	softlimit_aod2_freq_high,
	double	softlimit_aod2_freq_low,
	double	softlimit_aod2_volt_high,
	double	softlimit_aod2_volt_low,

	double	setpoint,
	double	setpoint_proximity_margin,	//	

	__int32	*numberofdatapoints,			//	pointer because this function will modify value
	__int32	*numberofdatapointsaftersetpoint,	//	same reason as above

	__int32	array_size,
	__int32	data_index,

	double	aod2_freq_current_value,
	double	aod2_volt_current_value,
	double	process_variable
	)
{
	unsigned __int32	stop_condition_return_value = 0x0;
	unsigned __int32	setpoint_condition = 0x0;
	unsigned __int16	treadle = 0x0;

	//
	//	Check the footswitch state (if desired)
	//		bit-wise AND selects only the specified channel
	//

	if ( 0x0 != (CONDITIONFOOTSWITCHRELEASED & condition) )
	{
		treadle = footswitch_dio_port & Board_Read(DIO_Parallel_Input_Register * 2);
		if ( footswitch_dio_port == treadle )
		{
			stop_condition_return_value |= CONDITIONFOOTSWITCHRELEASED;
			//	exit immediately
			return	stop_condition_return_value;
		}
	}

	//
	//	Check that we won't overwrite memory in the next iteration.
	//		This function expects to be passed the current data index value.
	//      i.e., in Labview one can wire the iteration "i" directly to data_index input
	//

	if ( (data_index + 1) >= array_size)
	{
		stop_condition_return_value |= CONDITIONDATAARRAYFULL;
		//	exit immediately
		return	stop_condition_return_value;
	}

	//
	//	Check the hard limits
	//

	stop_condition_return_value |= compare_stop_condition_values (
		condition,CONDITIONHARDAOD2FREQHIGH,
		aod2_freq_current_value, hardlimit_aod2_freq_high );
	stop_condition_return_value |= compare_stop_condition_values (
		condition,CONDITIONHARDAOD2FREQLOW,
		hardlimit_aod2_freq_low, aod2_freq_current_value + TWEAK001 );
	stop_condition_return_value |= compare_stop_condition_values (
		condition,CONDITIONHARDAOD2VOLTHIGH,
		aod2_volt_current_value, hardlimit_aod2_volt_high );
	stop_condition_return_value |= compare_stop_condition_values (
		condition,CONDITIONHARDAOD2VOLTLOW,
		hardlimit_aod2_volt_low, aod2_volt_current_value + TWEAK001 );


	//
	//	Check whether the AOD settings are within the correct range.
	//		If not, then set the corresponding bits in
	//		stop_condition_return_value.
	//

	stop_condition_return_value |= compare_stop_condition_values ( condition,
		CONDITIONSOFTAOD2FREQHIGH, aod2_freq_current_value, softlimit_aod2_freq_high );

	stop_condition_return_value |= compare_stop_condition_values ( condition,
		CONDITIONSOFTAOD2FREQLOW, softlimit_aod2_freq_low, aod2_freq_current_value + TWEAK001 );

	stop_condition_return_value |= compare_stop_condition_values ( condition,
		CONDITIONSOFTAOD2VOLTHIGH, aod2_volt_current_value, softlimit_aod2_volt_high );

	stop_condition_return_value |= compare_stop_condition_values ( condition,
		CONDITIONSOFTAOD2VOLTLOW, softlimit_aod2_volt_low, aod2_volt_current_value + TWEAK001 );

	//
	//	Check whether "setpoint is reached".
	//	This means to check whether the process variable is within
	//		the setpoint_proximity_margin of the setpoint
	//

	if (0x0 != (CONDITIONSETPOINTREACHED & condition))
		//	then we must check
	{
		if ( (setpoint - setpoint_proximity_margin < process_variable) &&
			 (setpoint + setpoint_proximity_margin > process_variable) )
		{
			stop_condition_return_value |= CONDITIONSETPOINTREACHED;
		}
	}

	//
	//	Check whether the number of data points is exceeded.
	//	I could implement this either by a static variable
	//		or by adjusting the threshold.

	if (0x0 != (CONDITIONNUMBEROFDATAPOINTS & condition))
		//	then we must check
	{
		--(*numberofdatapoints);
		if ( 0 >= *numberofdatapoints)
			//	then we have taken at least the originally-specified
			//	(*numberofdatapoints) data points
		{
			stop_condition_return_value |= CONDITIONNUMBEROFDATAPOINTS;
		}
	}

	//
	//	Check whether the number of data points is exceeded.
	//	I could implement this either by a static variable
	//		or by adjusting the threshold.

	if (0x0 != (CONDITIONDATAPOINTSAFTERSETPOINT & condition))
		//	then we must check
	{
		if ( (setpoint - setpoint_proximity_margin < process_variable) &&
			 (setpoint + setpoint_proximity_margin > process_variable) )
		{
			--(*numberofdatapointsaftersetpoint);
			if ( 0 >= *numberofdatapointsaftersetpoint)
				//	then we have taken at least the originally-specified
				//	(*numberofdatapointsaftersetpoint) data points on the setpoint
			{
				stop_condition_return_value |= CONDITIONDATAPOINTSAFTERSETPOINT;
			}
		}
	}

	//
	//	Calculate the logical AND or OR of the specified stop conditions
	//		depending on the "AND" or the "OR" setting.
	//
	if (CONDITIONLOGICALAND == (CONDITIONLOGICALAND & condition))
		//	we must check whether all conditions succeeded
	{
		//	restrict check to only those conditions specified in BITSFORLOGICALAND
		if ( (BITSFORLOGICALAND & condition) !=
			 (BITSFORLOGICALAND & stop_condition_return_value) )
			//	then not all the conditions were met
		{
			//	unset all bits contained in BITSFORLOGICALAND,
			//	by performing a logical AND with the complement
			//	of BITSFORLOGICALAND
			stop_condition_return_value &= ~ BITSFORLOGICALAND;
		}
		else
		{
			stop_condition_return_value |= CONDITIONLOGICALAND;
		}
	}

	return	stop_condition_return_value;
}
Personal tools