![](/media/cache/profiles/c51ce410c124a10e0db5e4b97fc2af39.50x50_q85.jpg)
Simple PID example for LabVIEW
Embed:
(wiki syntax)
Show/hide line numbers
QEI.h
00001 //****************************************************************************/ 00002 //@section LICENSE 00003 // 00004 //Copyright (c) 2010 ARM Limited 00005 // 00006 //Permission is hereby granted, free of charge, to any person obtaining a copy 00007 //of this software and associated documentation files (the "Software"), to deal 00008 //in the Software without restriction, including without limitation the rights 00009 //to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 00010 //copies of the Software, and to permit persons to whom the Software is 00011 //furnished to do so, subject to the following conditions: 00012 // 00013 //The above copyright notice and this permission notice shall be included in 00014 //all copies or substantial portions of the Software. 00015 // 00016 //THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 00017 //IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 00018 //FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 00019 //AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 00020 //LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 00021 //OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 00022 //THE SOFTWARE. 00023 //****************************************************************************/ 00024 //@section DESCRIPTION 00025 // 00026 // Quadrature Encoder Interface. 00027 // 00028 // A quadrature encoder consists of two code tracks on a disk which are 90 00029 // degrees out of phase. It can be used to determine how far a wheel has 00030 // rotated, relative to a known starting position. 00031 // 00032 // Only one code track changes at a time leading to a more robust system than 00033 // a single track, because any jitter around any edge won't cause a state 00034 // change as the other track will remain constant. 00035 // 00036 // Encoders can be a homebrew affair, consisting of infrared emitters/receivers 00037 // and paper code tracks consisting of alternating black and white sections; 00038 // alternatively, complete disk and PCB emitter/receiver encoder systems can 00039 // be bought, but the interface, regardless of implementation is the same. 00040 // 00041 // +-----+ +-----+ +-----+ 00042 // Channel A | ^ | | | | | 00043 // ---+ ^ +-----+ +-----+ +----- 00044 // ^ ^ 00045 // ^ +-----+ +-----+ +-----+ 00046 // Channel B ^ | | | | | | 00047 // ------+ +-----+ +-----+ +----- 00048 // ^ ^ 00049 // ^ ^ 00050 // 90deg 00051 // 00052 // This interface uses X4 encoding which calculates the pulse count based on 00053 // reading the current state after each rising and falling edge of either 00054 // channel. 00055 // 00056 // +-----+ +-----+ +-----+ 00057 // Channel A | | | | | | 00058 // ---+ +-----+ +-----+ +----- 00059 // ^ ^ ^ ^ ^ 00060 // ^ +-----+ ^ +-----+ ^ +-----+ 00061 // Channel B ^ | ^ | ^ | ^ | ^ | | 00062 // ------+ ^ +-----+ ^ +-----+ +-- 00063 // ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ 00064 // ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ 00065 // Pulse count 0 1 2 3 4 5 6 7 8 9 ... 00066 // 00067 // An optional index channel can be used which determines when a full 00068 // revolution has occured. 00069 // 00070 // If a 4 pules per revolution encoder was used, the following would be 00071 // observed. 00072 // 00073 // +-----+ +-----+ +-----+ 00074 // Channel A | | | | | | 00075 // ---+ +-----+ +-----+ +----- 00076 // ^ ^ ^ ^ ^ 00077 // ^ +-----+ ^ +-----+ ^ +-----+ 00078 // Channel B ^ | ^ | ^ | ^ | ^ | | 00079 // ------+ ^ +-----+ ^ +-----+ +-- 00080 // ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ 00081 // ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ 00082 // ^ ^ ^ +--+ ^ ^ +--+ ^ 00083 // ^ ^ ^ | | ^ ^ | | ^ 00084 // Index ------------+ +--------+ +----------- 00085 // ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ 00086 // Pulse count 0 1 2 3 4 5 6 7 8 9 ... 00087 // Rev. count 0 1 2 00088 // 00089 // Rotational position in degrees can be calculated by: 00090 // 00091 // (pulse count / X * N) * 360 00092 // 00093 // Where X is the encoding type [in our case X=4], and N is the number of 00094 // pulses per revolution. 00095 // 00096 // Linear position can be calculated by: 00097 // 00098 // (pulse count / X * N) * (1 / PPI) 00099 // 00100 // Where X is encoding type [in our case X=4], N is the number of pulses per 00101 // revolution, and PPI is pulses per inch, or the equivalent for any other 00102 // unit of displacement. PPI can be calculated by taking the circumference 00103 // of the wheel or encoder disk and dividing it by the number of pulses per 00104 // revolution. 00105 //****************************************************************************/ 00106 00107 #ifndef QEI_H 00108 #define QEI_H 00109 00110 //****************************************************************************/ 00111 // Includes 00112 //****************************************************************************/ 00113 #include "mbed.h" 00114 00115 //****************************************************************************/ 00116 // Defines 00117 //****************************************************************************/ 00118 #define PREV_MASK 0x1 //Mask for the previous state in determining direction 00119 //of rotation. 00120 #define CURR_MASK 0x2 //Mask for the current state in determining direction 00121 //of rotation. 00122 #define INVALID 0x3 //XORing two states where both bits have changed. 00123 00124 /** 00125 * Quadrature Encoder Interface. 00126 */ 00127 class QEI { 00128 00129 public: 00130 00131 /** 00132 * Constructor. 00133 * 00134 * Reads the current values on channel A and channel B to determine the 00135 * initial state. 00136 * 00137 * Attaches the encode function to the rise/fall interrupt edges of 00138 * channels A and B to perform X4 encoding. 00139 * 00140 * Attaches the index function to the rise interrupt edge of channel index 00141 * (if it is used) to count revolutions. 00142 * 00143 * @param channelA mbed pin for channel A input. 00144 * @param channelB mbed pin for channel B input. 00145 * @param index mbed pin for optional index channel input, 00146 * (pass NC if not needed). 00147 * @param pulsesPerRev Number of pulses in one revolution. 00148 */ 00149 QEI(PinName channelA, PinName channelB, PinName index, int pulsesPerRev); 00150 00151 /** 00152 * Reset the encoder. 00153 * 00154 * Sets the pulses and revolutions count to zero. 00155 */ 00156 void reset(void); 00157 00158 /** 00159 * Read the state of the encoder. 00160 * 00161 * @return The current state of the encoder as a 2-bit number, where: 00162 * bit 1 = The reading from channel B 00163 * bit 2 = The reading from channel A 00164 */ 00165 int getCurrentState(void); 00166 00167 /** 00168 * Read the number of pulses recorded by the encoder. 00169 * 00170 * @return Number of pulses which have occured. 00171 */ 00172 int getPulses(void); 00173 00174 private: 00175 00176 /** 00177 * Update the pulse count. 00178 * 00179 * Called on every rising/falling edge of channels A/B. 00180 * 00181 * Reads the state of the channels and determines whether a pulse forward 00182 * or backward has occured, updating the count appropriately. 00183 */ 00184 void encode(void); 00185 00186 /** 00187 * Called on every rising edge of channel index to update revolution 00188 * count by one. 00189 */ 00190 void index(void); 00191 00192 InterruptIn* channelA_; 00193 InterruptIn* channelB_; 00194 InterruptIn* index_; 00195 00196 int pulsesPerRev_; 00197 int revolutions_; 00198 int prevState_; 00199 int currState_; 00200 00201 volatile int pulses_; 00202 00203 }; 00204 00205 #endif /* QEI_H */
Generated on Tue Jul 12 2022 11:13:38 by
![doxygen](doxygen.png)