Simon Ford
/
LabVIEW_PID
Simple PID example for LabVIEW
QEI.h
- Committer:
- simon
- Date:
- 2010-08-03
- Revision:
- 1:ddfe18427154
- Parent:
- 0:e3b759ab4b5c
File content as of revision 1:ddfe18427154:
//****************************************************************************/ //@section LICENSE // //Copyright (c) 2010 ARM Limited // //Permission is hereby granted, free of charge, to any person obtaining a copy //of this software and associated documentation files (the "Software"), to deal //in the Software without restriction, including without limitation the rights //to use, copy, modify, merge, publish, distribute, sublicense, and/or sell //copies of the Software, and to permit persons to whom the Software is //furnished to do so, subject to the following conditions: // //The above copyright notice and this permission notice shall be included in //all copies or substantial portions of the Software. // //THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR //IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, //FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE //AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER //LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, //OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN //THE SOFTWARE. //****************************************************************************/ //@section DESCRIPTION // // Quadrature Encoder Interface. // // A quadrature encoder consists of two code tracks on a disk which are 90 // degrees out of phase. It can be used to determine how far a wheel has // rotated, relative to a known starting position. // // Only one code track changes at a time leading to a more robust system than // a single track, because any jitter around any edge won't cause a state // change as the other track will remain constant. // // Encoders can be a homebrew affair, consisting of infrared emitters/receivers // and paper code tracks consisting of alternating black and white sections; // alternatively, complete disk and PCB emitter/receiver encoder systems can // be bought, but the interface, regardless of implementation is the same. // // +-----+ +-----+ +-----+ // Channel A | ^ | | | | | // ---+ ^ +-----+ +-----+ +----- // ^ ^ // ^ +-----+ +-----+ +-----+ // Channel B ^ | | | | | | // ------+ +-----+ +-----+ +----- // ^ ^ // ^ ^ // 90deg // // This interface uses X4 encoding which calculates the pulse count based on // reading the current state after each rising and falling edge of either // channel. // // +-----+ +-----+ +-----+ // Channel A | | | | | | // ---+ +-----+ +-----+ +----- // ^ ^ ^ ^ ^ // ^ +-----+ ^ +-----+ ^ +-----+ // Channel B ^ | ^ | ^ | ^ | ^ | | // ------+ ^ +-----+ ^ +-----+ +-- // ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ // ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ // Pulse count 0 1 2 3 4 5 6 7 8 9 ... // // An optional index channel can be used which determines when a full // revolution has occured. // // If a 4 pules per revolution encoder was used, the following would be // observed. // // +-----+ +-----+ +-----+ // Channel A | | | | | | // ---+ +-----+ +-----+ +----- // ^ ^ ^ ^ ^ // ^ +-----+ ^ +-----+ ^ +-----+ // Channel B ^ | ^ | ^ | ^ | ^ | | // ------+ ^ +-----+ ^ +-----+ +-- // ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ // ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ // ^ ^ ^ +--+ ^ ^ +--+ ^ // ^ ^ ^ | | ^ ^ | | ^ // Index ------------+ +--------+ +----------- // ^ ^ ^ ^ ^ ^ ^ ^ ^ ^ // Pulse count 0 1 2 3 4 5 6 7 8 9 ... // Rev. count 0 1 2 // // Rotational position in degrees can be calculated by: // // (pulse count / X * N) * 360 // // Where X is the encoding type [in our case X=4], and N is the number of // pulses per revolution. // // Linear position can be calculated by: // // (pulse count / X * N) * (1 / PPI) // // Where X is encoding type [in our case X=4], N is the number of pulses per // revolution, and PPI is pulses per inch, or the equivalent for any other // unit of displacement. PPI can be calculated by taking the circumference // of the wheel or encoder disk and dividing it by the number of pulses per // revolution. //****************************************************************************/ #ifndef QEI_H #define QEI_H //****************************************************************************/ // Includes //****************************************************************************/ #include "mbed.h" //****************************************************************************/ // Defines //****************************************************************************/ #define PREV_MASK 0x1 //Mask for the previous state in determining direction //of rotation. #define CURR_MASK 0x2 //Mask for the current state in determining direction //of rotation. #define INVALID 0x3 //XORing two states where both bits have changed. /** * Quadrature Encoder Interface. */ class QEI { public: /** * Constructor. * * Reads the current values on channel A and channel B to determine the * initial state. * * Attaches the encode function to the rise/fall interrupt edges of * channels A and B to perform X4 encoding. * * Attaches the index function to the rise interrupt edge of channel index * (if it is used) to count revolutions. * * @param channelA mbed pin for channel A input. * @param channelB mbed pin for channel B input. * @param index mbed pin for optional index channel input, * (pass NC if not needed). * @param pulsesPerRev Number of pulses in one revolution. */ QEI(PinName channelA, PinName channelB, PinName index, int pulsesPerRev); /** * Reset the encoder. * * Sets the pulses and revolutions count to zero. */ void reset(void); /** * Read the state of the encoder. * * @return The current state of the encoder as a 2-bit number, where: * bit 1 = The reading from channel B * bit 2 = The reading from channel A */ int getCurrentState(void); /** * Read the number of pulses recorded by the encoder. * * @return Number of pulses which have occured. */ int getPulses(void); private: /** * Update the pulse count. * * Called on every rising/falling edge of channels A/B. * * Reads the state of the channels and determines whether a pulse forward * or backward has occured, updating the count appropriately. */ void encode(void); /** * Called on every rising edge of channel index to update revolution * count by one. */ void index(void); InterruptIn* channelA_; InterruptIn* channelB_; InterruptIn* index_; int pulsesPerRev_; int revolutions_; int prevState_; int currState_; volatile int pulses_; }; #endif /* QEI_H */