Project

General

Profile

Statistics
| Revision:

root / branches / encoders / code / lib / src / libdragonfly / encoders.c @ 1345

History | View | Annotate | Download (7.98 KB)

1 749 bneuman
#include "encoders.h"
2
#include "spi.h"
3
#include <dragonfly_lib.h>
4
#include "ring_buffer.h"
5 546 kwoo
6 749 bneuman
unsigned int left_data_buf;
7
unsigned int right_data_buf;
8 844 justin
char encoder_buf_index;
9 749 bneuman
10
unsigned int left_data;
11
unsigned int right_data;
12
13
unsigned int left_data_array[BUFFER_SIZE];
14
unsigned int right_data_array[BUFFER_SIZE];
15
int left_data_idx;
16
int right_data_idx;
17
18
int left_dx;
19
int right_dx;
20
long int timecount;
21
22 771 bneuman
volatile short int data_ready;
23
24 749 bneuman
void encoder_recv(char data);
25
26
//Helper Function Prototypes
27
inline void left_data_array_put(unsigned short int value);
28
inline unsigned int left_data_array_top(void);
29
inline unsigned int left_data_array_prev(void);
30
inline unsigned int left_data_array_bottom(void);
31
32
inline void right_data_array_put(unsigned short int value);
33
inline unsigned int right_data_array_top(void);
34
inline unsigned int right_data_array_prev(void);
35
inline unsigned int right_data_array_bottom(void);
36
37
38
void encoder_recv_complete(){
39 1345 chihsiuh
          encoder_buf_index = 0;
40
        data_ready++;
41 771 bneuman
42 1345 chihsiuh
           spi_transfer(5);
43 749 bneuman
}
44
45 1345 chihsiuh
/**
46
* @brief Initializes encoder variables and the hardware interface.
47
*/
48 749 bneuman
void encoders_init(void){
49
        int i;
50 771 bneuman
51
        data_ready=0;
52 749 bneuman
53 1345 chihsiuh
        spi_init(encoder_recv, encoder_recv_complete);
54 844 justin
        encoder_buf_index = 0;
55 749 bneuman
        left_data_buf = 0;
56
        right_data_buf= 0;
57
        left_data = -1;
58
        right_data = -1;
59 771 bneuman
60 749 bneuman
        //RING_BUFFER_INIT(enc_buffer,BUFFER_SIZE);
61
        left_data_idx = 0;
62
        right_data_idx = 0;
63
        for(i = 0; i < BUFFER_SIZE; i++) {
64
                left_data_array[i] = 0;
65
        }
66
        for(i = 0; i < BUFFER_SIZE; i++) {
67
                right_data_array[i] = 0;
68
        }
69
        spi_transfer(5);
70
}
71
72 809 justin
/**
73 1345 chihsiuh
 * @brief Returns the specified encoders value
74 809 justin
 *
75
 * @param encoder this is the encoder that you want to read. Valid arguments
76
 *          are LEFT and RIGHT
77
 *
78
 * @return the value of the specified encoder
79
 **/
80 749 bneuman
int encoder_read(char encoder){
81 1345 chihsiuh
82
        if(encoder==LEFT) return left_data;
83
        else if(encoder==RIGHT) return right_data;
84
        else return -1;
85 749 bneuman
}
86
87
88 1345 chihsiuh
/**
89
* @brief Outputs encoder direction as FORWARD OR BACK
90
* A STUB! DO NOT use.
91
*
92
* @param encoder The encoder you want the direction of.
93
* Valid arguments are right and left.
94
*
95
* @return FORWARD or BACK (the constants)
96
*/
97 749 bneuman
char encoder_direction(char encoder){
98
        return 0;
99
}
100 1345 chihsiuh
101 809 justin
/**
102 1345 chihsiuh
 * Gets the total distance covered by the specified encoder (in encoder clicks)
103 809 justin
 *
104
 * @param encoder the encoder that you want to read, use LEFT or RIGHT
105
 *
106 1345 chihsiuh
 * @return The distance covered by the specified encoder.
107 809 justin
 **/
108 749 bneuman
int encoder_get_dx(char encoder) {
109 1345 chihsiuh
110
        if(encoder==LEFT) return left_dx;
111
        else if(encoder==RIGHT) return right_dx;
112 749 bneuman
        else return -1;
113
}
114
115 809 justin
/**
116 1345 chihsiuh
 * Resets the distance accumulator for the specified
117 809 justin
 *  encoder.
118
 *
119 1345 chihsiuh
 * @param encoder the encoder that you want to reset distance for
120 809 justin
 **/
121 749 bneuman
void encoder_rst_dx(char encoder) {
122 1345 chihsiuh
123
        if(encoder==LEFT) left_dx = 0;
124
        else if(encoder==RIGHT) right_dx = 0;
125 749 bneuman
}
126
127 1345 chihsiuh
/**
128
* @brief Returns the number of encoder reads that have occurred.
129
*
130
* @return The time count.
131
*/
132 749 bneuman
int encoder_get_tc(void) {
133
        return timecount;
134
}
135
136 1345 chihsiuh
/**
137
* @brief Resets the encoder read counter.
138
*/
139 749 bneuman
void encoder_rst_tc(void) {
140
        timecount = 0;
141
}
142
143 1345 chihsiuh
///////////////////////////////////////////////////////////////////////
144
int left_data_at(int index) {
145
        int tmp_idx = left_data_idx - index;
146
        if (tmp_idx < 0)
147
                tmp_idx += BUFFER_SIZE;
148
        return left_data_array[tmp_idx];
149
}
150 749 bneuman
151 1345 chihsiuh
int right_data_at(int index) {
152
        int tmp_idx = right_data_idx - index;
153
        if (tmp_idx < 0)
154
                tmp_idx += BUFFER_SIZE;
155
        return right_data_array[tmp_idx];
156
}
157
158
159
int get_dx(char encoder, int index) {
160
        int dx, ctr;
161
        ctr = 0;
162
        dx = 1024;
163
        do {
164
                if (encoder == LEFT)
165
                        dx = left_data_at(index+ctr+38) - left_data_at(index+ctr);
166
                else
167
                        dx = right_data_at(index+ctr) - right_data_at(index+ctr+38);
168
                ctr++;
169
        } while ((dx > 30 || dx < -30) && ctr < 3);
170
        if (dx > 30 || dx < -30)
171
                return ERR_VEL;
172
        return dx;
173
}
174
/**
175
* @brief Returns the approximated instantaneous velocity of the robot
176
* in terms of encoder clicks.
177
*
178
* @param encoder RIGHT or LEFT - the wheel you want the velocity for.
179
*
180
* @return The instantaneous velocity for the given wheel.
181
*/
182 771 bneuman
int encoder_get_v(char encoder){
183 1345 chihsiuh
        /*
184
        if (encoder == LEFT)
185
                return left_data_array_bottom() - left_data_array_top();
186 771 bneuman

187 1345 chihsiuh
        if (encoder == RIGHT)
188
                return right_data_array_top() - right_data_array_bottom();
189 771 bneuman

190 1345 chihsiuh
        return -1;
191
        */
192
        int vel1, vel2, tmp;
193
        vel1 = get_dx(encoder, 0);
194
        vel2 = get_dx(encoder, 1);
195
196
        if (vel1 == ERR_VEL && vel2 == ERR_VEL)
197
                return ERR_VEL << 1;
198
        else if (vel2 == ERR_VEL)
199
                return vel1 << 1;
200
        else if (vel1 == ERR_VEL)
201
                return vel2 << 1;
202
        else
203
                return vel1 + vel2;
204 771 bneuman
}
205 1345 chihsiuh
/////////////////////////////////////////////////////////////////////////
206 771 bneuman
207 1345 chihsiuh
/**
208
* @brief Waits until n encoder reads have occurred.
209
* Counter is reset on functions exit.
210
*
211
* @param n
212
*/
213 771 bneuman
void encoder_wait(int n){
214
        while(data_ready<n);
215
        data_ready=0;
216
}
217
218
219 749 bneuman
//Full reads occur every 40 microseconds. This function should be called
220
//every 8 microseconds.
221
void encoder_recv(char data){
222
        short int dx;
223
224 809 justin
        //Parse the encoder data, comes in over 5 bytes 16 bits per encoder,
225
        // second is offset by 1 bit.
226 844 justin
        switch(encoder_buf_index){
227 809 justin
        case 0:
228
                right_data_buf |= ((short)data)<<8 & 0xff00;
229
                break;
230
        case 1:
231
                right_data_buf |= ((short)data) & 0xff;
232
                break;
233
        case 2:
234
                left_data_buf |= (((short)data) << 9) & (0x7F << 9);
235
                break;
236
        case 3:
237
                left_data_buf |= (((short)data) << 1) & (0xFF<<1);
238
                break;
239
        case 4: left_data_buf |= (((short)data)>>7) & 0x1;
240
        }
241 771 bneuman
242 844 justin
        encoder_buf_index = (encoder_buf_index + 1) % 5;
243 752 bneuman
244 844 justin
        if(encoder_buf_index==0) {
245 1345 chihsiuh
246
                /*Error handling for the left encoder*/
247
                if(!(left_data_buf & OCF))
248
                        left_data = ENCODER_DATA_NOT_READY;
249
                if(left_data_buf & (COF | LIN))
250
                        left_data = ENCODER_MISALIGNED;
251
                else if((left_data_buf & MagINCn) && (left_data_buf & MagDECn))
252
                        left_data = ENCODER_MAGNET_FAILURE;
253 809 justin
                else left_data = (left_data_buf>>5) & 1023;
254 771 bneuman
255 1345 chihsiuh
                /*Error handling for the right encoder*/
256
                 if(!(right_data_buf & OCF))
257
                        right_data = ENCODER_DATA_NOT_READY;
258
                if(right_data_buf & (COF | LIN))
259
                        right_data = ENCODER_MISALIGNED;
260
                else if ((right_data_buf & MagINCn)  && (right_data_buf & MagDECn))
261
                        right_data = ENCODER_MAGNET_FAILURE;
262 809 justin
                else right_data = (right_data_buf>>5) & 1023;
263 771 bneuman
264 809 justin
                  left_data_buf = 0;
265
                right_data_buf = 0;
266 749 bneuman
267 1345 chihsiuh
                /*Above 1023 is invalid data*/
268
                if(!(left_data > 1023)) {
269 771 bneuman
                        left_data_array_put(left_data);
270 752 bneuman
271 771 bneuman
                        //Adjust left accumulator
272 1345 chihsiuh
                        dx = - left_data + left_data_array_prev();
273 771 bneuman
274 809 justin
                        if(left_data_array_prev()==0)  dx=0;
275 752 bneuman
276 809 justin
                        if(dx > 512) left_dx += dx - 1023; //Underflow
277
                        else if(dx < -512) left_dx += dx + 1023; //Overflow
278
                        else left_dx += dx;
279 749 bneuman
                }
280
281 1345 chihsiuh
                /*Above 1023 is invalid data*/
282
                if(!(right_data > 1023)) {
283 771 bneuman
                        right_data_array_put(right_data);
284 749 bneuman
285 771 bneuman
                        //Adjust right accumulator
286
                        dx = right_data - right_data_array_prev();
287 752 bneuman
288 809 justin
                        if(right_data_array_prev()==0) dx=0;
289
290
                        if(dx > 512) right_dx += dx - 1023; //underflow
291
                        else if(dx < -512) right_dx += dx + 1023; //overflow
292
                        else right_dx += dx;
293 749 bneuman
                }
294 809 justin
        }
295 749 bneuman
296 809 justin
        //Increment timecount accumulator
297
        timecount++;
298 749 bneuman
}
299
300 844 justin
301 749 bneuman
//Helper Functions
302
inline void left_data_array_put(unsigned short int value) {
303
        if(left_data_idx == BUFFER_SIZE-1)
304
                left_data_idx = 0;
305
        else
306
                left_data_idx++;
307
        left_data_array[left_data_idx] = value;
308
}
309
310
inline unsigned int left_data_array_top(void) {
311
        return left_data_array[left_data_idx];
312
}
313
314
inline unsigned int left_data_array_prev(void) {
315
        if(left_data_idx == 0)
316
                return left_data_array[BUFFER_SIZE-1];
317
        else
318
                return left_data_array[left_data_idx - 1];
319
}
320
321
inline unsigned int left_data_array_bottom(void) {
322
        if(left_data_idx == BUFFER_SIZE-1)
323
                return left_data_array[0];
324
        else
325
                return left_data_array[left_data_idx + 1];
326
}
327
328
inline void right_data_array_put(unsigned short int value) {
329
        if(right_data_idx == BUFFER_SIZE-1)
330
                right_data_idx = 0;
331
        else
332
                right_data_idx++;
333
        right_data_array[right_data_idx] = value;
334
}
335
336
inline unsigned int right_data_array_top(void) {
337
        return right_data_array[right_data_idx];
338
}
339
340
inline unsigned int right_data_array_prev(void) {
341
        if(right_data_idx == 0)
342
                return right_data_array[BUFFER_SIZE-1];
343
        else
344
                return right_data_array[right_data_idx - 1];
345
}
346
347
inline unsigned int right_data_array_bottom(void) {
348
        if(right_data_idx == BUFFER_SIZE-1)
349
                return right_data_array[0];
350
        else
351
                return right_data_array[right_data_idx + 1];
352
}