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