Quadrature Encoder Interface for motion control with resistance to jitter and chatter on AB signals and motor vibrations

Dependents:   QEIx4_Example realtimeMM_V3 realtimeMM_V3

Quadrature Encoder Interface for Motion Control.

A class to decode pulses on a rotary encoder with AB signals (quadrature encoder). It uses all 4 edges of the AB signals to increase the counter resolution 4 times of cycles per rotation/revolution (CPR) (e.g. an encoder with 500 CPR get 2000 counts per rotation)

In opposite to most common QEI implementation this is resistant to jitter and chatter on AB signals and motor vibrations. When using interrupts (IRQ_NO_JAMMING-mode) only the needed edge and pin is activated to prevent jamming CPU time with unnecessary interrupts. Whes reaching the next position the edge that triggerd this position (state) is ignored to aboid oscillating up/down counts.

It can also be used in polling mode i.g. in idle routines if interrupts are not desired. At this mode be sure that the sampling frequency is heigher than the maximum rotation speed (expeced counts per second)

The internal state machine is based on a look up table (LUT) to minimize interrupt retention time and get all necessary flags at once.

Additional the rotation speed of the encoder can be measured. The algorithm is based on the measuring time between the edges to get a very precise speed at very slow rotation.

The library is designed to support closed loop speed- and motion-controller for also slow and smooth motions like movie camera motion control.

Quadrature Encoder Signals:

/media/uploads/jocis/qeix4.png

(+) Count UP; (-) Count DOWN

Committer:
jocis
Date:
Tue Sep 30 12:34:07 2014 +0000
Revision:
1:ac6b7b1bf6c5
Child:
2:c0b87b11b9cd
Added speed measurement; improved state machine and irq handling

Who changed what in which revision?

UserRevisionLine numberNew contents of line
jocis 1:ac6b7b1bf6c5 1 /*
jocis 1:ac6b7b1bf6c5 2 Copyright (c) 2011 Andy Kirkham
jocis 1:ac6b7b1bf6c5 3 modified by Jochen Krapf
jocis 1:ac6b7b1bf6c5 4
jocis 1:ac6b7b1bf6c5 5 Permission is hereby granted, free of charge, to any person obtaining a copy
jocis 1:ac6b7b1bf6c5 6 of this software and associated documentation files (the "Software"), to deal
jocis 1:ac6b7b1bf6c5 7 in the Software without restriction, including without limitation the rights
jocis 1:ac6b7b1bf6c5 8 to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
jocis 1:ac6b7b1bf6c5 9 copies of the Software, and to permit persons to whom the Software is
jocis 1:ac6b7b1bf6c5 10 furnished to do so, subject to the following conditions:
jocis 1:ac6b7b1bf6c5 11
jocis 1:ac6b7b1bf6c5 12 The above copyright notice and this permission notice shall be included in
jocis 1:ac6b7b1bf6c5 13 all copies or substantial portions of the Software.
jocis 1:ac6b7b1bf6c5 14
jocis 1:ac6b7b1bf6c5 15 THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
jocis 1:ac6b7b1bf6c5 16 IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
jocis 1:ac6b7b1bf6c5 17 FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
jocis 1:ac6b7b1bf6c5 18 AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
jocis 1:ac6b7b1bf6c5 19 LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
jocis 1:ac6b7b1bf6c5 20 OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
jocis 1:ac6b7b1bf6c5 21 THE SOFTWARE.
jocis 1:ac6b7b1bf6c5 22 */
jocis 1:ac6b7b1bf6c5 23
jocis 1:ac6b7b1bf6c5 24 #ifndef AJK_FPOINTER_H
jocis 1:ac6b7b1bf6c5 25 #define AJK_FPOINTER_H
jocis 1:ac6b7b1bf6c5 26
jocis 1:ac6b7b1bf6c5 27 namespace AjK {
jocis 1:ac6b7b1bf6c5 28
jocis 1:ac6b7b1bf6c5 29 class FPointerDummy;
jocis 1:ac6b7b1bf6c5 30
jocis 1:ac6b7b1bf6c5 31 /** FPointer - Adds callbacks that take and return a 32bit uint32_t data type.
jocis 1:ac6b7b1bf6c5 32 *
jocis 1:ac6b7b1bf6c5 33 * The Mbed library supplies a callback using the FunctionPointer object as
jocis 1:ac6b7b1bf6c5 34 * defined in FunctionPointer.h However, this callback system does not allow
jocis 1:ac6b7b1bf6c5 35 * the caller to pass a value to the callback. Likewise, the callback itself
jocis 1:ac6b7b1bf6c5 36 * cannot return a value.
jocis 1:ac6b7b1bf6c5 37 *
jocis 1:ac6b7b1bf6c5 38 * FPointer operates in the same way but allows the callback function to be
jocis 1:ac6b7b1bf6c5 39 * passed one arg, a uint32_t value. Additionally, the callback can return
jocis 1:ac6b7b1bf6c5 40 * a single uint32_t value. The reason for using uint32_t is that the Mbed
jocis 1:ac6b7b1bf6c5 41 * and the microcontroller (LPC1768) have a natural data size of 32bits and
jocis 1:ac6b7b1bf6c5 42 * this means we can use the uint32_t as a pointer. See example1.h for more
jocis 1:ac6b7b1bf6c5 43 * information. This example passes an "int" by passing a pointer to that
jocis 1:ac6b7b1bf6c5 44 * int as a 32bit value. Using this technique you can pass any value you like.
jocis 1:ac6b7b1bf6c5 45 * All you have to do is pass a pointer to your value cast to (uint32_t). Your
jocis 1:ac6b7b1bf6c5 46 * callback can the deference it to get the original value.
jocis 1:ac6b7b1bf6c5 47 *
jocis 1:ac6b7b1bf6c5 48 * example2.h shows how to do the same thing but demostrates how to specify
jocis 1:ac6b7b1bf6c5 49 * the callback into a class object/method.
jocis 1:ac6b7b1bf6c5 50 *
jocis 1:ac6b7b1bf6c5 51 * Finally, example3.h shows how to pass multiple values. In this example we
jocis 1:ac6b7b1bf6c5 52 * define a data structure and in the callback we pass a pointer to that
jocis 1:ac6b7b1bf6c5 53 * data structure thus allowing the callback to again get the values.
jocis 1:ac6b7b1bf6c5 54 *
jocis 1:ac6b7b1bf6c5 55 * Note, when passing pointers to variables to the callback, if the callback
jocis 1:ac6b7b1bf6c5 56 * function/method changes that variable's value then it will also change the
jocis 1:ac6b7b1bf6c5 57 * value the caller sees. If C pointers are new to you, you are strongly
jocis 1:ac6b7b1bf6c5 58 * advised to read up on the subject. It's pointers that often get beginners
jocis 1:ac6b7b1bf6c5 59 * into trouble when mis-used.
jocis 1:ac6b7b1bf6c5 60 *
jocis 1:ac6b7b1bf6c5 61 * @see example1.h
jocis 1:ac6b7b1bf6c5 62 * @see example2.h
jocis 1:ac6b7b1bf6c5 63 * @see example3.h
jocis 1:ac6b7b1bf6c5 64 * @see http://mbed.org/handbook/C-Data-Types
jocis 1:ac6b7b1bf6c5 65 * @see http://mbed.org/projects/libraries/svn/mbed/trunk/FunctionPointer.h
jocis 1:ac6b7b1bf6c5 66 */
jocis 1:ac6b7b1bf6c5 67 class FPointer_vi {
jocis 1:ac6b7b1bf6c5 68
jocis 1:ac6b7b1bf6c5 69 protected:
jocis 1:ac6b7b1bf6c5 70
jocis 1:ac6b7b1bf6c5 71 //! C callback function pointer.
jocis 1:ac6b7b1bf6c5 72 void (*c_callback)(int);
jocis 1:ac6b7b1bf6c5 73
jocis 1:ac6b7b1bf6c5 74 //! C++ callback object/method pointer (the object part).
jocis 1:ac6b7b1bf6c5 75 FPointerDummy *obj_callback;
jocis 1:ac6b7b1bf6c5 76
jocis 1:ac6b7b1bf6c5 77 //! C++ callback object/method pointer (the method part).
jocis 1:ac6b7b1bf6c5 78 void (FPointerDummy::*method_callback)(int);
jocis 1:ac6b7b1bf6c5 79
jocis 1:ac6b7b1bf6c5 80 public:
jocis 1:ac6b7b1bf6c5 81
jocis 1:ac6b7b1bf6c5 82 /** Constructor
jocis 1:ac6b7b1bf6c5 83 */
jocis 1:ac6b7b1bf6c5 84 FPointer_vi() {
jocis 1:ac6b7b1bf6c5 85 c_callback = NULL;
jocis 1:ac6b7b1bf6c5 86 obj_callback = NULL;
jocis 1:ac6b7b1bf6c5 87 method_callback = NULL;
jocis 1:ac6b7b1bf6c5 88 }
jocis 1:ac6b7b1bf6c5 89
jocis 1:ac6b7b1bf6c5 90 /** attach - Overloaded attachment function.
jocis 1:ac6b7b1bf6c5 91 *
jocis 1:ac6b7b1bf6c5 92 * Attach a C type function pointer as the callback.
jocis 1:ac6b7b1bf6c5 93 *
jocis 1:ac6b7b1bf6c5 94 * Note, the callback function prototype must be:-
jocis 1:ac6b7b1bf6c5 95 * @code
jocis 1:ac6b7b1bf6c5 96 * void myCallbackFunction(int);
jocis 1:ac6b7b1bf6c5 97 * @endcode
jocis 1:ac6b7b1bf6c5 98 * @param A C function pointer to call.
jocis 1:ac6b7b1bf6c5 99 */
jocis 1:ac6b7b1bf6c5 100 void attach(void (*function)(int) = 0) { c_callback = function; }
jocis 1:ac6b7b1bf6c5 101
jocis 1:ac6b7b1bf6c5 102 /** attach - Overloaded attachment function.
jocis 1:ac6b7b1bf6c5 103 *
jocis 1:ac6b7b1bf6c5 104 * Attach a C++ type object/method pointer as the callback.
jocis 1:ac6b7b1bf6c5 105 *
jocis 1:ac6b7b1bf6c5 106 * Note, the callback method prototype must be:-
jocis 1:ac6b7b1bf6c5 107 * @code
jocis 1:ac6b7b1bf6c5 108 * public:
jocis 1:ac6b7b1bf6c5 109 * void myCallbackFunction(int);
jocis 1:ac6b7b1bf6c5 110 * @endcode
jocis 1:ac6b7b1bf6c5 111 * @param A C++ object pointer.
jocis 1:ac6b7b1bf6c5 112 * @param A C++ method within the object to call.
jocis 1:ac6b7b1bf6c5 113 */
jocis 1:ac6b7b1bf6c5 114 template<class T>
jocis 1:ac6b7b1bf6c5 115 void attach(T* item, void (T::*method)(int)) {
jocis 1:ac6b7b1bf6c5 116 obj_callback = (FPointerDummy *)item;
jocis 1:ac6b7b1bf6c5 117 method_callback = (void (FPointerDummy::*)(int))method;
jocis 1:ac6b7b1bf6c5 118 }
jocis 1:ac6b7b1bf6c5 119
jocis 1:ac6b7b1bf6c5 120 /** call - Overloaded callback initiator.
jocis 1:ac6b7b1bf6c5 121 *
jocis 1:ac6b7b1bf6c5 122 * call the callback function.
jocis 1:ac6b7b1bf6c5 123 *
jocis 1:ac6b7b1bf6c5 124 * @param int The value to pass to the callback.
jocis 1:ac6b7b1bf6c5 125 */
jocis 1:ac6b7b1bf6c5 126 void call(int arg) {
jocis 1:ac6b7b1bf6c5 127 if (c_callback != NULL) {
jocis 1:ac6b7b1bf6c5 128 (*c_callback)(arg);
jocis 1:ac6b7b1bf6c5 129 }
jocis 1:ac6b7b1bf6c5 130 else {
jocis 1:ac6b7b1bf6c5 131 if (obj_callback != NULL && method_callback != NULL) {
jocis 1:ac6b7b1bf6c5 132 (obj_callback->*method_callback)(arg);
jocis 1:ac6b7b1bf6c5 133 }
jocis 1:ac6b7b1bf6c5 134 }
jocis 1:ac6b7b1bf6c5 135 }
jocis 1:ac6b7b1bf6c5 136
jocis 1:ac6b7b1bf6c5 137 };
jocis 1:ac6b7b1bf6c5 138
jocis 1:ac6b7b1bf6c5 139 }; // namespace AjK ends
jocis 1:ac6b7b1bf6c5 140
jocis 1:ac6b7b1bf6c5 141 using namespace AjK;
jocis 1:ac6b7b1bf6c5 142
jocis 1:ac6b7b1bf6c5 143 #endif