00001 /*! \file encoder.h \brief Quadrature Encoder reader/driver. */ 00002 //***************************************************************************** 00003 // 00004 // File Name : 'encoder.h' 00005 // Title : Quadrature Encoder reader/driver 00006 // Author : Pascal Stang - Copyright (C) 2003-2004 00007 // Created : 2003.01.26 00008 // Revised : 2004.06.25 00009 // Version : 0.3 00010 // Target MCU : Atmel AVR Series 00011 // Editor Tabs : 4 00012 // 00013 /// \ingroup driver_hw 00014 /// \defgroup encoder Quadrature Encoder Driver (encoder.c) 00015 /// \code #include "encoder.h" \endcode 00016 /// \par Overview 00017 /// This library allows easy interfacing of standard quadrature encoders 00018 /// (used for sensing shaft rotational position and speed) to the Atmel 00019 /// AVR-series processors. The library uses external interrupts to sense 00020 /// and keep track of the encoder's movements. The library is extendable 00021 /// with the maximum number of encoders equal to the total number of 00022 /// external interrupts available on the target AVR processor. 00023 /// 00024 /// \note Due to the wide range of external interrupt capability on 00025 /// AVR processors, it is difficult for this library to automatically 00026 /// adapt to different processors. For this reason, much of the 00027 /// configuration responsibility has been left with the user. See 00028 /// the encoderconf.h configuration file. 00029 // 00030 /// \par Operation: 00031 /// Quadrature encoders have two digital outputs usually called PhaseA and 00032 /// PhaseB. When the encoder rotates, PhaseA and PhaseB produce square wave 00033 /// pulses where each pulse represents a fraction of a turn of the encoder 00034 /// shaft. Encoders are rated for a certain number of pulses (or counts) per 00035 /// complete revolution of the shaft. Common counts/revolution specs are 50, 00036 /// 100,128,200,250,256,500,etc. By counting the number of pulses output on 00037 /// one of the phases starting from time0, you can calculate the total 00038 /// rotational distance the encoder has traveled. 00039 /// 00040 /// Often, however, we want current position not just total distance traveled. 00041 /// For this it is necessary to know not only how far the encoder has traveled, 00042 /// but also which direction it was going at each step of the way. To do this 00043 /// we need to use both outputs (or phases) of the quadrature encoder. 00044 /// 00045 /// The pulses from PhaseA and PhaseB on quadrature encoders are always aligned 00046 /// 90 degrees out-of-phase (otherwise said: 1/4 wavelength apart). This 00047 /// special phase relationship lets us extract both the distance and direction 00048 /// the encoder has rotated from the outputs. 00049 /// 00050 /// To do this, consider Phase A to be the distance counter. On each rising 00051 /// edge of PhaseA we will count 1 "tic" of distance, but we need to know the 00052 /// direction. Look at the quadrature waveform plot below. Notice that when 00053 /// we travel forward in time (left->right), PhaseB is always low (logic 0) at 00054 /// the rising edge of PhaseA. When we travel backwards in time (right->left), 00055 /// PhaseB is always high (logic 1) at the rising edge of PhaseA. Note that 00056 /// traveling forward or backwards in time is the same thing as rotating 00057 /// forwards or bardwards. Thus, if PhaseA is our counter, PhaseB indicates 00058 /// direction. 00059 /// 00060 /// Here is an example waveform from a quadrature encoder: 00061 /* 00062 /// /---\ /---\ /---\ /---\ /---\ /---\ 00063 /// Phase A: | | | | | | | | | | | | 00064 /// ---/ \---/ \---/ \---/ \---/ \---/ \- 00065 /// -\ /---\ /---\ /---\ /---\ /---\ /--- 00066 /// Phase B: | | | | | | | | | | | | 00067 /// \---/ \---/ \---/ \---/ \---/ \---/ 00068 /// Time: <---------------------------------------------------> 00069 /// Rotate FWD: >----------------------------------------------> 00070 /// Rotate REV: <----------------------------------------------< 00071 */ 00072 /// To keep track of the encoder position in software, we connect PhaseA to an 00073 /// external processor interrupt line, and PhaseB to any I/O pin. We set up 00074 /// the external interrupt to trigger whenever PhaseA produces a rising edge. 00075 /// When a rising edge is detected, our interrupt handler function is executed. 00076 /// Inside the handler function, we quickly check the PhaseB line to see if it 00077 /// is high or low. If it is high, we increment the encoder's position 00078 /// counter, otherwise we decrement it. The encoder position counter can be 00079 /// read at any time to find out the current position. 00080 // 00081 // NOTE: This code is currently below version 1.0, and therefore is considered 00082 // to be lacking in some functionality or documentation, or may not be fully 00083 // tested. Nonetheless, you can expect most functions to work. 00084 // 00085 // This code is distributed under the GNU Public License 00086 // which can be found at http://www.gnu.org/licenses/gpl.txt 00087 // 00088 //***************************************************************************** 00089 00090 #ifndef ENCODER_H 00091 #define ENCODER_H 00092 00093 #include "global.h" 00094 00095 // include encoder configuration file 00096 #include "encoderconf.h" 00097 00098 // constants/macros/typdefs 00099 00100 // defines for processor compatibility 00101 // chose proper Interrupt Mask (IMSK) 00102 #ifdef EIMSK 00103 #define IMSK EIMSK // for processors mega128, mega64 00104 #endif 00105 #ifdef GICR 00106 #define IMSK GICR // for mega16,32,etc 00107 #endif 00108 // default 00109 #ifndef IMSK 00110 #define IMSK GIMSK // for other processors 90s8515, mega163, etc 00111 #endif 00112 00113 00114 //! Encoder state structure 00115 // stores the position and other information from each encoder 00116 typedef struct struct_EncoderState 00117 { 00118 s32 position; ///< position 00119 } EncoderStateType; 00120 00121 00122 // functions 00123 00124 //! encoderInit() initializes hardware and encoder position readings 00125 // Run this init routine once before using any other encoder function. 00126 void encoderInit(void); 00127 00128 //! encoderOff() disables hardware and stops encoder position updates 00129 void encoderOff(void); 00130 00131 //! encoderGetPosition() reads the current position of the encoder 00132 s32 encoderGetPosition(u08 encoderNum); 00133 00134 //! encoderSetPosition() sets the current position of the encoder 00135 void encoderSetPosition(u08 encoderNum, s32 position); 00136 00137 #endif