User:Steven J. Koch/Notebook/Kochlab/2009/06/29/Feedback 96 Debugging/Richard Yeh stop condition C dcode
From OpenWetWare
< User:Steven J. Koch | Notebook | Kochlab | 2009 | 06 | 29 | Feedback 96 Debugging
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;
}


