User | Revision | Line number | New contents of line |
farbodjam |
0:fc0482177a6d
|
1
|
/**
|
farbodjam |
0:fc0482177a6d
|
2
|
* @author Aaron Berk
|
farbodjam |
0:fc0482177a6d
|
3
|
*
|
farbodjam |
0:fc0482177a6d
|
4
|
* @section LICENSE
|
farbodjam |
0:fc0482177a6d
|
5
|
*
|
farbodjam |
0:fc0482177a6d
|
6
|
* Copyright (c) 2010 ARM Limited
|
farbodjam |
0:fc0482177a6d
|
7
|
*
|
farbodjam |
0:fc0482177a6d
|
8
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
farbodjam |
0:fc0482177a6d
|
9
|
* of this software and associated documentation files (the "Software"), to deal
|
farbodjam |
0:fc0482177a6d
|
10
|
* in the Software without restriction, including without limitation the rights
|
farbodjam |
0:fc0482177a6d
|
11
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
farbodjam |
0:fc0482177a6d
|
12
|
* copies of the Software, and to permit persons to whom the Software is
|
farbodjam |
0:fc0482177a6d
|
13
|
* furnished to do so, subject to the following conditions:
|
farbodjam |
0:fc0482177a6d
|
14
|
*
|
farbodjam |
0:fc0482177a6d
|
15
|
* The above copyright notice and this permission notice shall be included in
|
farbodjam |
0:fc0482177a6d
|
16
|
* all copies or substantial portions of the Software.
|
farbodjam |
0:fc0482177a6d
|
17
|
*
|
farbodjam |
0:fc0482177a6d
|
18
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
farbodjam |
0:fc0482177a6d
|
19
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
farbodjam |
0:fc0482177a6d
|
20
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
farbodjam |
0:fc0482177a6d
|
21
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
farbodjam |
0:fc0482177a6d
|
22
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
farbodjam |
0:fc0482177a6d
|
23
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
farbodjam |
0:fc0482177a6d
|
24
|
* THE SOFTWARE.
|
farbodjam |
0:fc0482177a6d
|
25
|
*
|
farbodjam |
0:fc0482177a6d
|
26
|
* @section DESCRIPTION
|
farbodjam |
0:fc0482177a6d
|
27
|
*
|
farbodjam |
0:fc0482177a6d
|
28
|
* Quadrature Encoder Interface.
|
farbodjam |
0:fc0482177a6d
|
29
|
*
|
farbodjam |
0:fc0482177a6d
|
30
|
* A quadrature encoder consists of two code tracks on a disc which are 90
|
farbodjam |
0:fc0482177a6d
|
31
|
* degrees out of phase. It can be used to determine how far a wheel has
|
farbodjam |
0:fc0482177a6d
|
32
|
* rotated, relative to a known starting position.
|
farbodjam |
0:fc0482177a6d
|
33
|
*
|
farbodjam |
0:fc0482177a6d
|
34
|
* Only one code track changes at a time leading to a more robust system than
|
farbodjam |
0:fc0482177a6d
|
35
|
* a single track, because any jitter around any edge won't cause a state
|
farbodjam |
0:fc0482177a6d
|
36
|
* change as the other track will remain constant.
|
farbodjam |
0:fc0482177a6d
|
37
|
*
|
farbodjam |
0:fc0482177a6d
|
38
|
* Encoders can be a homebrew affair, consisting of infrared emitters/receivers
|
farbodjam |
0:fc0482177a6d
|
39
|
* and paper code tracks consisting of alternating black and white sections;
|
farbodjam |
0:fc0482177a6d
|
40
|
* alternatively, complete disk and PCB emitter/receiver encoder systems can
|
farbodjam |
0:fc0482177a6d
|
41
|
* be bought, but the interface, regardless of implementation is the same.
|
farbodjam |
0:fc0482177a6d
|
42
|
*
|
farbodjam |
0:fc0482177a6d
|
43
|
* +-----+ +-----+ +-----+
|
farbodjam |
0:fc0482177a6d
|
44
|
* Channel A | ^ | | | | |
|
farbodjam |
0:fc0482177a6d
|
45
|
* ---+ ^ +-----+ +-----+ +-----
|
farbodjam |
0:fc0482177a6d
|
46
|
* ^ ^
|
farbodjam |
0:fc0482177a6d
|
47
|
* ^ +-----+ +-----+ +-----+
|
farbodjam |
0:fc0482177a6d
|
48
|
* Channel B ^ | | | | | |
|
farbodjam |
0:fc0482177a6d
|
49
|
* ------+ +-----+ +-----+ +-----
|
farbodjam |
0:fc0482177a6d
|
50
|
* ^ ^
|
farbodjam |
0:fc0482177a6d
|
51
|
* ^ ^
|
farbodjam |
0:fc0482177a6d
|
52
|
* 90deg
|
farbodjam |
0:fc0482177a6d
|
53
|
*
|
farbodjam |
0:fc0482177a6d
|
54
|
* The interface uses X2 encoding by default which calculates the pulse count
|
farbodjam |
0:fc0482177a6d
|
55
|
* based on reading the current state after each rising and falling edge of
|
farbodjam |
0:fc0482177a6d
|
56
|
* channel A.
|
farbodjam |
0:fc0482177a6d
|
57
|
*
|
farbodjam |
0:fc0482177a6d
|
58
|
* +-----+ +-----+ +-----+
|
farbodjam |
0:fc0482177a6d
|
59
|
* Channel A | | | | | |
|
farbodjam |
0:fc0482177a6d
|
60
|
* ---+ +-----+ +-----+ +-----
|
farbodjam |
0:fc0482177a6d
|
61
|
* ^ ^ ^ ^ ^
|
farbodjam |
0:fc0482177a6d
|
62
|
* ^ +-----+ ^ +-----+ ^ +-----+
|
farbodjam |
0:fc0482177a6d
|
63
|
* Channel B ^ | ^ | ^ | ^ | ^ | |
|
farbodjam |
0:fc0482177a6d
|
64
|
* ------+ ^ +-----+ ^ +-----+ +--
|
farbodjam |
0:fc0482177a6d
|
65
|
* ^ ^ ^ ^ ^
|
farbodjam |
0:fc0482177a6d
|
66
|
* ^ ^ ^ ^ ^
|
farbodjam |
0:fc0482177a6d
|
67
|
* Pulse count 0 1 2 3 4 5 ...
|
farbodjam |
0:fc0482177a6d
|
68
|
*
|
farbodjam |
0:fc0482177a6d
|
69
|
* This interface can also use X4 encoding which calculates the pulse count
|
farbodjam |
0:fc0482177a6d
|
70
|
* based on reading the current state after each rising and falling edge of
|
farbodjam |
0:fc0482177a6d
|
71
|
* either channel.
|
farbodjam |
0:fc0482177a6d
|
72
|
*
|
farbodjam |
0:fc0482177a6d
|
73
|
* +-----+ +-----+ +-----+
|
farbodjam |
0:fc0482177a6d
|
74
|
* Channel A | | | | | |
|
farbodjam |
0:fc0482177a6d
|
75
|
* ---+ +-----+ +-----+ +-----
|
farbodjam |
0:fc0482177a6d
|
76
|
* ^ ^ ^ ^ ^
|
farbodjam |
0:fc0482177a6d
|
77
|
* ^ +-----+ ^ +-----+ ^ +-----+
|
farbodjam |
0:fc0482177a6d
|
78
|
* Channel B ^ | ^ | ^ | ^ | ^ | |
|
farbodjam |
0:fc0482177a6d
|
79
|
* ------+ ^ +-----+ ^ +-----+ +--
|
farbodjam |
0:fc0482177a6d
|
80
|
* ^ ^ ^ ^ ^ ^ ^ ^ ^ ^
|
farbodjam |
0:fc0482177a6d
|
81
|
* ^ ^ ^ ^ ^ ^ ^ ^ ^ ^
|
farbodjam |
0:fc0482177a6d
|
82
|
* Pulse count 0 1 2 3 4 5 6 7 8 9 ...
|
farbodjam |
0:fc0482177a6d
|
83
|
*
|
farbodjam |
0:fc0482177a6d
|
84
|
* It defaults
|
farbodjam |
0:fc0482177a6d
|
85
|
*
|
farbodjam |
0:fc0482177a6d
|
86
|
* An optional index channel can be used which determines when a full
|
farbodjam |
0:fc0482177a6d
|
87
|
* revolution has occured.
|
farbodjam |
0:fc0482177a6d
|
88
|
*
|
farbodjam |
0:fc0482177a6d
|
89
|
* If a 4 pules per revolution encoder was used, with X4 encoding,
|
farbodjam |
0:fc0482177a6d
|
90
|
* the following would be observed.
|
farbodjam |
0:fc0482177a6d
|
91
|
*
|
farbodjam |
0:fc0482177a6d
|
92
|
* +-----+ +-----+ +-----+
|
farbodjam |
0:fc0482177a6d
|
93
|
* Channel A | | | | | |
|
farbodjam |
0:fc0482177a6d
|
94
|
* ---+ +-----+ +-----+ +-----
|
farbodjam |
0:fc0482177a6d
|
95
|
* ^ ^ ^ ^ ^
|
farbodjam |
0:fc0482177a6d
|
96
|
* ^ +-----+ ^ +-----+ ^ +-----+
|
farbodjam |
0:fc0482177a6d
|
97
|
* Channel B ^ | ^ | ^ | ^ | ^ | |
|
farbodjam |
0:fc0482177a6d
|
98
|
* ------+ ^ +-----+ ^ +-----+ +--
|
farbodjam |
0:fc0482177a6d
|
99
|
* ^ ^ ^ ^ ^ ^ ^ ^ ^ ^
|
farbodjam |
0:fc0482177a6d
|
100
|
* ^ ^ ^ ^ ^ ^ ^ ^ ^ ^
|
farbodjam |
0:fc0482177a6d
|
101
|
* ^ ^ ^ +--+ ^ ^ +--+ ^
|
farbodjam |
0:fc0482177a6d
|
102
|
* ^ ^ ^ | | ^ ^ | | ^
|
farbodjam |
0:fc0482177a6d
|
103
|
* Index ------------+ +--------+ +-----------
|
farbodjam |
0:fc0482177a6d
|
104
|
* ^ ^ ^ ^ ^ ^ ^ ^ ^ ^
|
farbodjam |
0:fc0482177a6d
|
105
|
* Pulse count 0 1 2 3 4 5 6 7 8 9 ...
|
farbodjam |
0:fc0482177a6d
|
106
|
* Rev. count 0 1 2
|
farbodjam |
0:fc0482177a6d
|
107
|
*
|
farbodjam |
0:fc0482177a6d
|
108
|
* Rotational position in degrees can be calculated by:
|
farbodjam |
0:fc0482177a6d
|
109
|
*
|
farbodjam |
0:fc0482177a6d
|
110
|
* (pulse count / X * N) * 360
|
farbodjam |
0:fc0482177a6d
|
111
|
*
|
farbodjam |
0:fc0482177a6d
|
112
|
* Where X is the encoding type [e.g. X4 encoding => X=4], and N is the number
|
farbodjam |
0:fc0482177a6d
|
113
|
* of pulses per revolution.
|
farbodjam |
0:fc0482177a6d
|
114
|
*
|
farbodjam |
0:fc0482177a6d
|
115
|
* Linear position can be calculated by:
|
farbodjam |
0:fc0482177a6d
|
116
|
*
|
farbodjam |
0:fc0482177a6d
|
117
|
* (pulse count / X * N) * (1 / PPI)
|
farbodjam |
0:fc0482177a6d
|
118
|
*
|
farbodjam |
0:fc0482177a6d
|
119
|
* Where X is encoding type [e.g. X4 encoding => X=44], N is the number of
|
farbodjam |
0:fc0482177a6d
|
120
|
* pulses per revolution, and PPI is pulses per inch, or the equivalent for
|
farbodjam |
0:fc0482177a6d
|
121
|
* any other unit of displacement. PPI can be calculated by taking the
|
farbodjam |
0:fc0482177a6d
|
122
|
* circumference of the wheel or encoder disk and dividing it by the number
|
farbodjam |
0:fc0482177a6d
|
123
|
* of pulses per revolution.
|
farbodjam |
0:fc0482177a6d
|
124
|
*/
|
farbodjam |
0:fc0482177a6d
|
125
|
|
farbodjam |
0:fc0482177a6d
|
126
|
#ifndef QEI_H
|
farbodjam |
0:fc0482177a6d
|
127
|
#define QEI_H
|
farbodjam |
0:fc0482177a6d
|
128
|
|
farbodjam |
0:fc0482177a6d
|
129
|
/**
|
farbodjam |
0:fc0482177a6d
|
130
|
* Includes
|
farbodjam |
0:fc0482177a6d
|
131
|
*/
|
farbodjam |
0:fc0482177a6d
|
132
|
#include "mbed.h"
|
farbodjam |
0:fc0482177a6d
|
133
|
|
farbodjam |
0:fc0482177a6d
|
134
|
/**
|
farbodjam |
0:fc0482177a6d
|
135
|
* Defines
|
farbodjam |
0:fc0482177a6d
|
136
|
*/
|
farbodjam |
0:fc0482177a6d
|
137
|
#define PREV_MASK 0x1 //Mask for the previous state in determining direction
|
farbodjam |
0:fc0482177a6d
|
138
|
//of rotation.
|
farbodjam |
0:fc0482177a6d
|
139
|
#define CURR_MASK 0x2 //Mask for the current state in determining direction
|
farbodjam |
0:fc0482177a6d
|
140
|
//of rotation.
|
farbodjam |
0:fc0482177a6d
|
141
|
#define INVALID 0x3 //XORing two states where both bits have changed.
|
farbodjam |
0:fc0482177a6d
|
142
|
|
farbodjam |
0:fc0482177a6d
|
143
|
/**
|
farbodjam |
0:fc0482177a6d
|
144
|
* Quadrature Encoder Interface.
|
farbodjam |
0:fc0482177a6d
|
145
|
*/
|
farbodjam |
0:fc0482177a6d
|
146
|
class QEI {
|
farbodjam |
0:fc0482177a6d
|
147
|
|
farbodjam |
0:fc0482177a6d
|
148
|
public:
|
farbodjam |
0:fc0482177a6d
|
149
|
|
farbodjam |
0:fc0482177a6d
|
150
|
typedef enum Encoding {
|
farbodjam |
0:fc0482177a6d
|
151
|
|
farbodjam |
0:fc0482177a6d
|
152
|
X2_ENCODING,
|
farbodjam |
0:fc0482177a6d
|
153
|
X4_ENCODING
|
farbodjam |
0:fc0482177a6d
|
154
|
|
farbodjam |
0:fc0482177a6d
|
155
|
} Encoding;
|
farbodjam |
0:fc0482177a6d
|
156
|
|
farbodjam |
0:fc0482177a6d
|
157
|
/**
|
farbodjam |
0:fc0482177a6d
|
158
|
* Constructor.
|
farbodjam |
0:fc0482177a6d
|
159
|
*
|
farbodjam |
0:fc0482177a6d
|
160
|
* Reads the current values on channel A and channel B to determine the
|
farbodjam |
0:fc0482177a6d
|
161
|
* initial state.
|
farbodjam |
0:fc0482177a6d
|
162
|
*
|
farbodjam |
0:fc0482177a6d
|
163
|
* Attaches the encode function to the rise/fall interrupt edges of
|
farbodjam |
0:fc0482177a6d
|
164
|
* channels A and B to perform X4 encoding.
|
farbodjam |
0:fc0482177a6d
|
165
|
*
|
farbodjam |
0:fc0482177a6d
|
166
|
* Attaches the index function to the rise interrupt edge of channel index
|
farbodjam |
0:fc0482177a6d
|
167
|
* (if it is used) to count revolutions.
|
farbodjam |
0:fc0482177a6d
|
168
|
*
|
farbodjam |
0:fc0482177a6d
|
169
|
* @param channelA mbed pin for channel A input.
|
farbodjam |
0:fc0482177a6d
|
170
|
* @param channelB mbed pin for channel B input.
|
farbodjam |
0:fc0482177a6d
|
171
|
* @param index mbed pin for optional index channel input,
|
farbodjam |
0:fc0482177a6d
|
172
|
* (pass NC if not needed).
|
farbodjam |
0:fc0482177a6d
|
173
|
* @param pulsesPerRev Number of pulses in one revolution.
|
farbodjam |
0:fc0482177a6d
|
174
|
* @param encoding The encoding to use. Uses X2 encoding by default. X2
|
farbodjam |
0:fc0482177a6d
|
175
|
* encoding uses interrupts on the rising and falling edges
|
farbodjam |
0:fc0482177a6d
|
176
|
* of only channel A where as X4 uses them on both
|
farbodjam |
0:fc0482177a6d
|
177
|
* channels.
|
farbodjam |
0:fc0482177a6d
|
178
|
*/
|
farbodjam |
0:fc0482177a6d
|
179
|
QEI(PinName channelA, PinName channelB, PinName index, int pulsesPerRev, Encoding encoding = X2_ENCODING);
|
farbodjam |
0:fc0482177a6d
|
180
|
|
farbodjam |
0:fc0482177a6d
|
181
|
/**
|
farbodjam |
0:fc0482177a6d
|
182
|
* Reset the encoder.
|
farbodjam |
0:fc0482177a6d
|
183
|
*
|
farbodjam |
0:fc0482177a6d
|
184
|
* Sets the pulses and revolutions count to zero.
|
farbodjam |
0:fc0482177a6d
|
185
|
*/
|
farbodjam |
0:fc0482177a6d
|
186
|
void reset(void);
|
farbodjam |
0:fc0482177a6d
|
187
|
|
farbodjam |
0:fc0482177a6d
|
188
|
/**
|
farbodjam |
0:fc0482177a6d
|
189
|
* Read the state of the encoder.
|
farbodjam |
0:fc0482177a6d
|
190
|
*
|
farbodjam |
0:fc0482177a6d
|
191
|
* @return The current state of the encoder as a 2-bit number, where:
|
farbodjam |
0:fc0482177a6d
|
192
|
* bit 1 = The reading from channel B
|
farbodjam |
0:fc0482177a6d
|
193
|
* bit 2 = The reading from channel A
|
farbodjam |
0:fc0482177a6d
|
194
|
*/
|
farbodjam |
0:fc0482177a6d
|
195
|
int getCurrentState(void);
|
farbodjam |
0:fc0482177a6d
|
196
|
|
farbodjam |
0:fc0482177a6d
|
197
|
/**
|
farbodjam |
0:fc0482177a6d
|
198
|
* Read the number of pulses recorded by the encoder.
|
farbodjam |
0:fc0482177a6d
|
199
|
*
|
farbodjam |
0:fc0482177a6d
|
200
|
* @return Number of pulses which have occured.
|
farbodjam |
0:fc0482177a6d
|
201
|
*/
|
farbodjam |
0:fc0482177a6d
|
202
|
int getPulses(void);
|
farbodjam |
0:fc0482177a6d
|
203
|
|
farbodjam |
0:fc0482177a6d
|
204
|
/**
|
farbodjam |
0:fc0482177a6d
|
205
|
* Read the number of revolutions recorded by the encoder on the index channel.
|
farbodjam |
0:fc0482177a6d
|
206
|
*
|
farbodjam |
0:fc0482177a6d
|
207
|
* @return Number of revolutions which have occured on the index channel.
|
farbodjam |
0:fc0482177a6d
|
208
|
*/
|
farbodjam |
0:fc0482177a6d
|
209
|
int getRevolutions(void);
|
farbodjam |
0:fc0482177a6d
|
210
|
|
farbodjam |
0:fc0482177a6d
|
211
|
private:
|
farbodjam |
0:fc0482177a6d
|
212
|
|
farbodjam |
0:fc0482177a6d
|
213
|
/**
|
farbodjam |
0:fc0482177a6d
|
214
|
* Update the pulse count.
|
farbodjam |
0:fc0482177a6d
|
215
|
*
|
farbodjam |
0:fc0482177a6d
|
216
|
* Called on every rising/falling edge of channels A/B.
|
farbodjam |
0:fc0482177a6d
|
217
|
*
|
farbodjam |
0:fc0482177a6d
|
218
|
* Reads the state of the channels and determines whether a pulse forward
|
farbodjam |
0:fc0482177a6d
|
219
|
* or backward has occured, updating the count appropriately.
|
farbodjam |
0:fc0482177a6d
|
220
|
*/
|
farbodjam |
0:fc0482177a6d
|
221
|
void encode(void);
|
farbodjam |
0:fc0482177a6d
|
222
|
|
farbodjam |
0:fc0482177a6d
|
223
|
/**
|
farbodjam |
0:fc0482177a6d
|
224
|
* Called on every rising edge of channel index to update revolution
|
farbodjam |
0:fc0482177a6d
|
225
|
* count by one.
|
farbodjam |
0:fc0482177a6d
|
226
|
*/
|
farbodjam |
0:fc0482177a6d
|
227
|
void index(void);
|
farbodjam |
0:fc0482177a6d
|
228
|
|
farbodjam |
0:fc0482177a6d
|
229
|
Encoding encoding_;
|
farbodjam |
0:fc0482177a6d
|
230
|
|
farbodjam |
0:fc0482177a6d
|
231
|
InterruptIn channelA_;
|
farbodjam |
0:fc0482177a6d
|
232
|
InterruptIn channelB_;
|
farbodjam |
0:fc0482177a6d
|
233
|
InterruptIn index_;
|
farbodjam |
0:fc0482177a6d
|
234
|
|
farbodjam |
0:fc0482177a6d
|
235
|
int pulsesPerRev_;
|
farbodjam |
0:fc0482177a6d
|
236
|
int prevState_;
|
farbodjam |
0:fc0482177a6d
|
237
|
int currState_;
|
farbodjam |
0:fc0482177a6d
|
238
|
|
farbodjam |
0:fc0482177a6d
|
239
|
volatile int pulses_;
|
farbodjam |
0:fc0482177a6d
|
240
|
volatile int revolutions_;
|
farbodjam |
0:fc0482177a6d
|
241
|
|
farbodjam |
0:fc0482177a6d
|
242
|
};
|
farbodjam |
0:fc0482177a6d
|
243
|
|
farbodjam |
0:fc0482177a6d
|
244
|
#endif /* QEI_H */
|