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