| Line No. | Rev | Author | Line |
|---|---|---|---|
| 1 | 6 | kaklik | /*! \file encoder.h \brief Quadrature Encoder reader/driver. */ |
| 2 | //***************************************************************************** |
||
| 3 | // |
||
| 4 | // File Name : 'encoder.h' |
||
| 5 | // Title : Quadrature Encoder reader/driver |
||
| 6 | // Author : Pascal Stang - Copyright (C) 2003-2004 |
||
| 7 | // Created : 2003.01.26 |
||
| 8 | // Revised : 2004.06.25 |
||
| 9 | // Version : 0.3 |
||
| 10 | // Target MCU : Atmel AVR Series |
||
| 11 | // Editor Tabs : 4 |
||
| 12 | // |
||
| 13 | /// \ingroup driver_hw |
||
| 14 | /// \defgroup encoder Quadrature Encoder Driver (encoder.c) |
||
| 15 | /// \code #include "encoder.h" \endcode |
||
| 16 | /// \par Overview |
||
| 17 | /// This library allows easy interfacing of standard quadrature encoders |
||
| 18 | /// (used for sensing shaft rotational position and speed) to the Atmel |
||
| 19 | /// AVR-series processors. The library uses external interrupts to sense |
||
| 20 | /// and keep track of the encoder's movements. The library is extendable |
||
| 21 | /// with the maximum number of encoders equal to the total number of |
||
| 22 | /// external interrupts available on the target AVR processor. |
||
| 23 | /// |
||
| 24 | /// \note Due to the wide range of external interrupt capability on |
||
| 25 | /// AVR processors, it is difficult for this library to automatically |
||
| 26 | /// adapt to different processors. For this reason, much of the |
||
| 27 | /// configuration responsibility has been left with the user. See |
||
| 28 | /// the encoderconf.h configuration file. |
||
| 29 | // |
||
| 30 | /// \par Operation: |
||
| 31 | /// Quadrature encoders have two digital outputs usually called PhaseA and |
||
| 32 | /// PhaseB. When the encoder rotates, PhaseA and PhaseB produce square wave |
||
| 33 | /// pulses where each pulse represents a fraction of a turn of the encoder |
||
| 34 | /// shaft. Encoders are rated for a certain number of pulses (or counts) per |
||
| 35 | /// complete revolution of the shaft. Common counts/revolution specs are 50, |
||
| 36 | /// 100,128,200,250,256,500,etc. By counting the number of pulses output on |
||
| 37 | /// one of the phases starting from time0, you can calculate the total |
||
| 38 | /// rotational distance the encoder has traveled. |
||
| 39 | /// |
||
| 40 | /// Often, however, we want current position not just total distance traveled. |
||
| 41 | /// For this it is necessary to know not only how far the encoder has traveled, |
||
| 42 | /// but also which direction it was going at each step of the way. To do this |
||
| 43 | /// we need to use both outputs (or phases) of the quadrature encoder. |
||
| 44 | /// |
||
| 45 | /// The pulses from PhaseA and PhaseB on quadrature encoders are always aligned |
||
| 46 | /// 90 degrees out-of-phase (otherwise said: 1/4 wavelength apart). This |
||
| 47 | /// special phase relationship lets us extract both the distance and direction |
||
| 48 | /// the encoder has rotated from the outputs. |
||
| 49 | /// |
||
| 50 | /// To do this, consider Phase A to be the distance counter. On each rising |
||
| 51 | /// edge of PhaseA we will count 1 "tic" of distance, but we need to know the |
||
| 52 | /// direction. Look at the quadrature waveform plot below. Notice that when |
||
| 53 | /// we travel forward in time (left->right), PhaseB is always low (logic 0) at |
||
| 54 | /// the rising edge of PhaseA. When we travel backwards in time (right->left), |
||
| 55 | /// PhaseB is always high (logic 1) at the rising edge of PhaseA. Note that |
||
| 56 | /// traveling forward or backwards in time is the same thing as rotating |
||
| 57 | /// forwards or bardwards. Thus, if PhaseA is our counter, PhaseB indicates |
||
| 58 | /// direction. |
||
| 59 | /// |
||
| 60 | /// Here is an example waveform from a quadrature encoder: |
||
| 61 | /* |
||
| 62 | /// /---\ /---\ /---\ /---\ /---\ /---\ |
||
| 63 | /// Phase A: | | | | | | | | | | | | |
||
| 64 | /// ---/ \---/ \---/ \---/ \---/ \---/ \- |
||
| 65 | /// -\ /---\ /---\ /---\ /---\ /---\ /--- |
||
| 66 | /// Phase B: | | | | | | | | | | | | |
||
| 67 | /// \---/ \---/ \---/ \---/ \---/ \---/ |
||
| 68 | /// Time: <---------------------------------------------------> |
||
| 69 | /// Rotate FWD: >----------------------------------------------> |
||
| 70 | /// Rotate REV: <----------------------------------------------< |
||
| 71 | */ |
||
| 72 | /// To keep track of the encoder position in software, we connect PhaseA to an |
||
| 73 | /// external processor interrupt line, and PhaseB to any I/O pin. We set up |
||
| 74 | /// the external interrupt to trigger whenever PhaseA produces a rising edge. |
||
| 75 | /// When a rising edge is detected, our interrupt handler function is executed. |
||
| 76 | /// Inside the handler function, we quickly check the PhaseB line to see if it |
||
| 77 | /// is high or low. If it is high, we increment the encoder's position |
||
| 78 | /// counter, otherwise we decrement it. The encoder position counter can be |
||
| 79 | /// read at any time to find out the current position. |
||
| 80 | // |
||
| 81 | // NOTE: This code is currently below version 1.0, and therefore is considered |
||
| 82 | // to be lacking in some functionality or documentation, or may not be fully |
||
| 83 | // tested. Nonetheless, you can expect most functions to work. |
||
| 84 | // |
||
| 85 | // This code is distributed under the GNU Public License |
||
| 86 | // which can be found at http://www.gnu.org/licenses/gpl.txt |
||
| 87 | // |
||
| 88 | //***************************************************************************** |
||
| 89 | |||
| 90 | #ifndef ENCODER_H |
||
| 91 | #define ENCODER_H |
||
| 92 | |||
| 93 | #include "global.h" |
||
| 94 | |||
| 95 | // include encoder configuration file |
||
| 96 | #include "encoderconf.h" |
||
| 97 | |||
| 98 | // constants/macros/typdefs |
||
| 99 | |||
| 100 | // defines for processor compatibility |
||
| 101 | // chose proper Interrupt Mask (IMSK) |
||
| 102 | #ifdef EIMSK |
||
| 103 | #define IMSK EIMSK // for processors mega128, mega64 |
||
| 104 | #endif |
||
| 105 | #ifdef GICR |
||
| 106 | #define IMSK GICR // for mega16,32,etc |
||
| 107 | #endif |
||
| 108 | // default |
||
| 109 | #ifndef IMSK |
||
| 110 | #define IMSK GIMSK // for other processors 90s8515, mega163, etc |
||
| 111 | #endif |
||
| 112 | |||
| 113 | |||
| 114 | //! Encoder state structure |
||
| 115 | // stores the position and other information from each encoder |
||
| 116 | typedef struct struct_EncoderState |
||
| 117 | { |
||
| 118 | s32 position; ///< position |
||
| 119 | } EncoderStateType; |
||
| 120 | |||
| 121 | |||
| 122 | // functions |
||
| 123 | |||
| 124 | //! encoderInit() initializes hardware and encoder position readings |
||
| 125 | // Run this init routine once before using any other encoder function. |
||
| 126 | void encoderInit(void); |
||
| 127 | |||
| 128 | //! encoderOff() disables hardware and stops encoder position updates |
||
| 129 | void encoderOff(void); |
||
| 130 | |||
| 131 | //! encoderGetPosition() reads the current position of the encoder |
||
| 132 | s32 encoderGetPosition(u08 encoderNum); |
||
| 133 | |||
| 134 | //! encoderSetPosition() sets the current position of the encoder |
||
| 135 | void encoderSetPosition(u08 encoderNum, s32 position); |
||
| 136 | |||
| 137 | #endif |
Powered by WebSVN v2.8.3