This is a library for processing encoder

Embed: (wiki syntax)

« Back to documentation index

Show/hide line numbers ENCODER_PROCESSOR.h Source File

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 */