This is a library for processing encoder
Embed:
(wiki syntax)
Show/hide line numbers
ENCODER_PROCESSOR.h
00001 /** 00002 * Note: This is a cross-platform version which is separated from hardware. 00003 * --------------------------------------------------------------------------- 00004 * This module is modified by Chun-Feng Huang for abstracting and more functionality. 00005 * Modified by: Chun-Feng Huang 00006 * E-mail: bens0516@gmail.com 00007 * 00008 */ 00009 00010 //----------------------------------// 00011 /** 00012 * @author Aaron Berk 00013 * 00014 * @section LICENSE 00015 * 00016 * Copyright (c) 2010 ARM Limited 00017 * 00018 * Permission is hereby granted, free of charge, to any person obtaining a copy 00019 * of this software and associated documentation files (the "Software"), to deal 00020 * in the Software without restriction, including without limitation the rights 00021 * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 00022 * copies of the Software, and to permit persons to whom the Software is 00023 * furnished to do so, subject to the following conditions: 00024 * 00025 * The above copyright notice and this permission notice shall be included in 00026 * all copies or substantial portions of the Software. 00027 * 00028 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 00029 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 00030 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 00031 * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 00032 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 00033 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 00034 * THE SOFTWARE. 00035 * 00036 * @section DESCRIPTION 00037 * 00038 * Quadrature Encoder Interface. 00039 * 00040 * A quadrature encoder consists of two code tracks on a disc which are 90 00041 * degrees out of phase. It can be used to determine how far a wheel has 00042 * rotated, relative to a known starting position. 00043 * 00044 * Only one code track changes at a time leading to a more robust system than 00045 * a single track, because any jitter around any edge won't cause a state 00046 * change as the other track will remain constant. 00047 * 00048 * Encoders can be a homebrew affair, consisting of infrared emitters/receivers 00049 * and paper code tracks consisting of alternating black and white sections; 00050 * alternatively, complete disk and PCB emitter/receiver encoder systems can 00051 * be bought, but the interface, regardless of implementation is the same. 00052 * 00053 * +-----+ +-----+ +-----+ 00054 * Channel A | ^ | | | | | 00055 * ---+ ^ +-----+ +-----+ +----- 00056 * ^ ^ 00057 * ^ +-----+ +-----+ +-----+ 00058 * Channel B ^ | | | | | | 00059 * ------+ +-----+ +-----+ +----- 00060 * ^ ^ 00061 * ^ ^ 00062 * 90deg 00063 * 00064 * The interface uses X2 encoding by default which calculates the pulse count 00065 * based on reading the current state after each rising and falling edge of 00066 * channel A. 00067 * 00068 * +-----+ +-----+ +-----+ 00069 * Channel A | | | | | | 00070 * ---+ +-----+ +-----+ +----- 00071 * ^ ^ ^ ^ ^ 00072 * ^ +-----+ ^ +-----+ ^ +-----+ 00073 * Channel B ^ | ^ | ^ | ^ | ^ | | 00074 * ------+ ^ +-----+ ^ +-----+ +-- 00075 * ^ ^ ^ ^ ^ 00076 * ^ ^ ^ ^ ^ 00077 * Pulse count 0 1 2 3 4 5 ... 00078 * 00079 * This interface can also use X4 encoding which calculates the pulse count 00080 * based on reading the current state after each rising and falling edge of 00081 * either channel. 00082 * 00083 * +-----+ +-----+ +-----+ 00084 * Channel A | | | | | | 00085 * ---+ +-----+ +-----+ +----- 00086 * ^ ^ ^ ^ ^ 00087 * ^ +-----+ ^ +-----+ ^ +-----+ 00088 * Channel B ^ | ^ | ^ | ^ | ^ | | 00089 * ------+ ^ +-----+ ^ +-----+ +-- 00090 * ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ 00091 * ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ 00092 * Pulse count 0 1 2 3 4 5 6 7 8 9 ... 00093 * 00094 * It defaults 00095 * 00096 * An optional index channel can be used which determines when a full 00097 * revolution has occured. 00098 * 00099 * If a 4 pules per revolution encoder was used, with X4 encoding, 00100 * the following would be observed. 00101 * 00102 * +-----+ +-----+ +-----+ 00103 * Channel A | | | | | | 00104 * ---+ +-----+ +-----+ +----- 00105 * ^ ^ ^ ^ ^ 00106 * ^ +-----+ ^ +-----+ ^ +-----+ 00107 * Channel B ^ | ^ | ^ | ^ | ^ | | 00108 * ------+ ^ +-----+ ^ +-----+ +-- 00109 * ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ 00110 * ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ 00111 * ^ ^ ^ +--+ ^ ^ +--+ ^ 00112 * ^ ^ ^ | | ^ ^ | | ^ 00113 * Index ------------+ +--------+ +----------- 00114 * ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ 00115 * Pulse count 0 1 2 3 4 5 6 7 8 9 ... 00116 * Rev. count 0 1 2 00117 * 00118 * Rotational position in degrees can be calculated by: 00119 * 00120 * (pulse count / X * N) * 360 00121 * 00122 * Where X is the encoding type [e.g. X4 encoding => X=4], and N is the number 00123 * of pulses per revolution. 00124 * 00125 * Linear position can be calculated by: 00126 * 00127 * (pulse count / X * N) * (1 / PPI) 00128 * 00129 * Where X is encoding type [e.g. X4 encoding => X=44], N is the number of 00130 * pulses per revolution, and PPI is pulses per inch, or the equivalent for 00131 * any other unit of displacement. PPI can be calculated by taking the 00132 * circumference of the wheel or encoder disk and dividing it by the number 00133 * of pulses per revolution. 00134 */ 00135 00136 ////////////////////////////// 00137 #ifndef ENCODER_PROCESSOR_H 00138 #define ENCODER_PROCESSOR_H 00139 // 00140 #include <vector> 00141 00142 using std::vector; 00143 00144 00145 00146 00147 #define PREV_MASK 0x1 // Mask for the previous state in determining direction of rotation. (0b01) 00148 #define CURR_MASK 0x2 // Mask for the current state in determining direction of rotation. (0b10) 00149 #define INVALID 0x3 // Indicating that both phase have changed. (0b11) 00150 00151 // ENCODER_PROCESSOR 00152 //////////////////////// 00153 class ENCODER_PROCESSOR { 00154 00155 public: 00156 00157 double Ts; 00158 00159 // 00160 bool is_initiated; // The state of A and B should be read at first time. 00161 00162 00163 volatile int pulses_; 00164 00165 int delta_count; 00166 vector<int> MA_window; 00167 size_t idx_MA_array; 00168 size_t size_MA_window; 00169 00170 00171 typedef enum Encoding { 00172 00173 X2_ENCODING, 00174 X4_ENCODING 00175 00176 } Encoding; 00177 00178 /** 00179 * Constructor. 00180 * 00181 * Reads the current values on channel A and channel B to determine the 00182 * initial state. 00183 * 00184 * Attaches the encode function to the rise/fall interrupt edges of 00185 * channels A and B to perform X4 encoding. 00186 * 00187 * Attaches the index function to the rise interrupt edge of channel index 00188 * (if it is used) to count revolutions. 00189 * 00190 * @param channelA mbed pin for channel A input. 00191 * @param channelB mbed pin for channel B input. 00192 * @param index mbed pin for optional index channel input, 00193 * (pass NC if not needed). 00194 * @param pulsesPerRev Number of pulses in one revolution. 00195 * @param encoding The encoding to use. Uses X2 encoding by default. X2 00196 * encoding uses interrupts on the rising and falling edges 00197 * of only channel A where as X4 uses them on both 00198 * channels. 00199 */ 00200 ENCODER_PROCESSOR(int pulsesPerRevolution_in, int size_MA_window_in, double sampling_time_in, Encoding encoding = X2_ENCODING); 00201 00202 // Process control 00203 void reset(void); 00204 00205 // Main functions to be call at proper interupts 00206 //---------------------------------------------// 00207 // Call-back function for both pin A and pin B interupt (rise and fall) 00208 void IntrCB_pulseUpdate(int phase_A, int phase_B); 00209 // (Un-necessary) Call-back function for index-pin interupt 00210 void IntrCB_indexUpdate(void); 00211 //---------------------------------------------// 00212 00213 00214 //---------------------------------------------// 00215 // Iterate at each timer interupt 00216 void iterateOnce(void); 00217 //---------------------------------------------// 00218 00219 00220 // Get states 00221 int getEncoderState(void); // Get the combined AB status, A B 00222 int getPulses(void); // Get the total count since last reset 00223 int getRevolutions(void); // Get the number of revolution since last reset 00224 00225 // Get results 00226 // Rotational speed 00227 double getAngularSpeed(void); // rad/s 00228 double getAngularSpeed_deg_s(void); // deg/s 00229 // Angle 00230 double getAngle(bool is_ranged); // rad, if is_ranged, return 0~2*PI 00231 double getAngle_deg(bool is_ranged); // deg, if is_ranged, return 0~360 00232 00233 private: 00234 00235 // Encoding type 00236 Encoding encoding_; 00237 00238 // 00239 int pulsesPerRevolution; 00240 size_t encoderState_pre; 00241 size_t encoderState_now; // (chanA << 1) | (chanB) , A B 00242 00243 // Unit transformation 00244 // Rotational speed 00245 double count_2_rad_s; 00246 double count_2_deg_s; 00247 // Angle 00248 double count_2_rad; 00249 double count_2_deg; 00250 00251 00252 // volatile int pulses_; 00253 volatile int revolutions_; 00254 00255 }; 00256 00257 #endif /* ENCODER_PROCESSOR_H */
Generated on Sat Jul 23 2022 11:47:40 by
1.7.2