Project

General

Profile

Statistics
| Revision:

root / branches / encoders / code / projects / libdragonfly / encoders.c @ 854

History | View | Annotate | Download (7.44 KB)

1
#include "encoders.h"
2
#include "spi.h"
3
#include <dragonfly_lib.h>
4
#include "ring_buffer.h"
5

    
6
unsigned int left_data_buf;
7
unsigned int right_data_buf;
8
char encoder_buf_index;
9

    
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
int left_v;
23
int right_v;
24

    
25

    
26
volatile short int data_ready;
27

    
28
void encoder_recv(char data);
29

    
30
//Helper Function Prototypes
31
inline void left_data_array_put(unsigned short int value);
32
inline unsigned int left_data_array_top(void);
33
inline unsigned int left_data_array_prev(void);
34
inline unsigned int left_data_array_bottom(void);
35

    
36
inline void right_data_array_put(unsigned short int value);
37
inline unsigned int right_data_array_top(void);
38
inline unsigned int right_data_array_prev(void);
39
inline unsigned int right_data_array_bottom(void);
40

    
41

    
42
void encoder_recv_complete(){
43
          encoder_buf_index = 0;
44
        data_ready++;
45
  
46
           spi_transfer(5);
47
}
48

    
49
/** 
50
* @brief Initializes encoder variables and the hardware interface.
51
*/
52
void encoders_init(void){
53
        int i;
54
        
55
        data_ready=0;
56

    
57
        spi_init(encoder_recv, encoder_recv_complete);
58
        encoder_buf_index = 0;
59
        left_data_buf = 0;
60
        right_data_buf= 0;
61
        left_data = -1;
62
        right_data = -1;
63
        
64
        
65
        left_v=0;
66
        right_v=0;
67
        
68
        //RING_BUFFER_INIT(enc_buffer,BUFFER_SIZE);
69
        left_data_idx = 0;
70
        right_data_idx = 0;
71
        for(i = 0; i < BUFFER_SIZE; i++) {
72
                left_data_array[i] = 0;
73
        }
74
        for(i = 0; i < BUFFER_SIZE; i++) {
75
                right_data_array[i] = 0;
76
        }
77
        spi_transfer(5);
78
}
79

    
80
/**
81
 * @brief Returns the specified encoders value
82
 *
83
 * @param encoder this is the encoder that you want to read. Valid arguments
84
 *          are LEFT and RIGHT
85
 *
86
 * @return the value of the specified encoder
87
 **/
88
int encoder_read(char encoder){
89
        
90
        if(encoder==LEFT) return left_data;
91
        else if(encoder==RIGHT) return right_data;
92
        else return -1;
93
}
94

    
95

    
96
/** 
97
* @brief Outputs encoder direction as FORWARD OR BACK
98
* A STUB! DO NOT use.
99
* 
100
* @param encoder The encoder you want the direction of.
101
* Valid arguments are right and left.
102
* 
103
* @return FORWARD or BACK (the constants)
104
*/
105
char encoder_direction(char encoder){
106
        return 0;
107
}
108

    
109
/**
110
 * Gets the total distance covered by the specified encoder (in encoder clicks)
111
 *
112
 * @param encoder the encoder that you want to read, use LEFT or RIGHT
113
 *
114
 * @return The distance covered by the specified encoder.
115
 **/
116
int encoder_get_dx(char encoder) {
117
        
118
        if(encoder==LEFT) return left_dx;
119
        else if(encoder==RIGHT) return right_dx;
120
        else return -1;
121
}
122

    
123
/**
124
 * Resets the distance accumulator for the specified
125
 *  encoder.
126
 *
127
 * @param encoder the encoder that you want to reset distance for
128
 **/
129
void encoder_rst_dx(char encoder) {
130
        
131
        if(encoder==LEFT) left_dx = 0;
132
        else if(encoder==RIGHT) right_dx = 0;
133
}
134

    
135
/** 
136
* @brief Returns the number of encoder reads that have occurred.
137
* 
138
* @return The time count.
139
*/
140
int encoder_get_tc(void) {
141
        return timecount;
142
}
143

    
144
/** 
145
* @brief Resets the encoder read counter.
146
*/
147
void encoder_rst_tc(void) {
148
        timecount = 0;
149
}
150

    
151

    
152
/** 
153
* @brief Returns the approximated instantaneous velocity of the robot
154
* in terms of encoder clicks.
155
* 
156
* @param encoder RIGHT or LEFT - the wheel you want the velocity for.
157
* 
158
* @return The instantaneous velocity for the given wheel.
159
*/
160
int encoder_get_v(char encoder){
161
        int last, res=0;
162
        
163
        cli();
164
        
165
        if(encoder==LEFT){
166
                if(left_data_idx==0)
167
                        last = BUFFER_SIZE - 1;
168
                else
169
                        last = left_data_idx - 1;
170
                res = ((int)left_data_array[last]) - ((int)left_data_array[left_data_idx]);
171
        }
172
        if(encoder==RIGHT){
173
                if(right_data_idx==0)
174
                        last = BUFFER_SIZE - 1;
175
                else
176
                        last = right_data_idx - 1;
177
                res = ((int)right_data_array[right_data_idx]) - ((int)right_data_array[last]);
178
        }
179
        
180
        sei();
181

    
182
        while(res<MIN_V)//underflow
183
                res+=1024;
184
        while(res>MAX_V)//overflow
185
                res-=1024;
186

    
187
        return res;
188
}
189

    
190

    
191
/** 
192
* @brief Waits until n encoder reads have occurred.
193
* Counter is reset on functions exit.
194
* 
195
* @param n 
196
*/
197
void encoder_wait(int n){
198
        while(data_ready<n);
199
        data_ready=0;
200
}
201

    
202

    
203
//Full reads occur every 40 microseconds. This function should be called
204
//every 8 microseconds.
205
void encoder_recv(char data){
206
        short int dx;
207
        
208
        //Parse the encoder data, comes in over 5 bytes 16 bits per encoder,
209
        // second is offset by 1 bit.
210
        switch(encoder_buf_index){        
211
        case 0: 
212
                right_data_buf |= ((short)data)<<8 & 0xff00;
213
                break;
214
        case 1:
215
                right_data_buf |= ((short)data) & 0xff;
216
                break;
217
        case 2:
218
                left_data_buf |= (((short)data) << 9) & (0x7F << 9);
219
                break;
220
        case 3:
221
                left_data_buf |= (((short)data) << 1) & (0xFF<<1);
222
                break;
223
        case 4: left_data_buf |= (((short)data)>>7) & 0x1;
224
        }        
225
                
226
        encoder_buf_index = (encoder_buf_index + 1) % 5;
227

    
228
        if(encoder_buf_index==0) {
229
                
230
                /*Error handling for the left encoder*/ 
231
                if(!(left_data_buf & OCF)) 
232
                        left_data = ENCODER_DATA_NOT_READY; 
233
                if(left_data_buf & (COF | LIN))  
234
                        left_data = ENCODER_MISALIGNED;
235
                else if((left_data_buf & MagINCn) && (left_data_buf & MagDECn)) 
236
                        left_data = ENCODER_MAGNET_FAILURE;
237
                else left_data = (left_data_buf>>5) & 1023;
238
                        
239
                /*Error handling for the right encoder*/ 
240
                 if(!(right_data_buf & OCF))
241
                        right_data = ENCODER_DATA_NOT_READY;        
242
                if(right_data_buf & (COF | LIN)) 
243
                        right_data = ENCODER_MISALIGNED;
244
                else if ((right_data_buf & MagINCn)  && (right_data_buf & MagDECn)) 
245
                        right_data = ENCODER_MAGNET_FAILURE;
246
                else right_data = (right_data_buf>>5) & 1023;
247
                        
248
                  left_data_buf = 0;
249
                right_data_buf = 0;
250

    
251
                /*Above 1023 is invalid data*/        
252
                if(!(left_data > 1023)) {
253
                        left_data_array_put(left_data);
254

    
255
                        //Adjust left accumulator
256
                        dx = left_data - left_data_array_prev();
257
                        
258
                        //Adjust velocity: save last dx
259
                        left_v = left_dx;
260
                        
261
                        if(left_data_array_prev()==0)  dx=0;
262

    
263
                        if(dx > 512) left_dx += dx - 1023; //Underflow
264
                        else if(dx < -512) left_dx += dx + 1023; //Overflow
265
                        else left_dx += dx;
266
                        
267
                        //Adjust velocity: update
268
                        left_v = left_dx - left_v;
269
                }
270

    
271
                /*Above 1023 is invalid data*/        
272
                if(!(right_data > 1023)) {
273
                        right_data_array_put(right_data);
274

    
275
                        //Adjust right accumulator
276
                        dx = right_data - right_data_array_prev();
277

    
278
                        if(right_data_array_prev()==0) dx=0;
279
                          
280
                        if(dx > 512) right_dx += dx - 1023; //underflow
281
                        else if(dx < -512) right_dx += dx + 1023; //overflow 
282
                        else right_dx += dx;
283
                }
284
        }
285

    
286
        //Increment timecount accumulator
287
        timecount++;
288
}
289

    
290

    
291
//Helper Functions
292
inline void left_data_array_put(unsigned short int value) {
293
        if(left_data_idx == BUFFER_SIZE-1)
294
                left_data_idx = 0;
295
        else
296
                left_data_idx++;
297
        left_data_array[left_data_idx] = value;
298
}
299

    
300
inline unsigned int left_data_array_top(void) {
301
        return left_data_array[left_data_idx];
302
}
303

    
304
inline unsigned int left_data_array_prev(void) {
305
        if(left_data_idx == 0)
306
                return left_data_array[BUFFER_SIZE-1];
307
        else
308
                return left_data_array[left_data_idx - 1];
309
}
310

    
311
inline unsigned int left_data_array_bottom(void) {
312
        if(left_data_idx == BUFFER_SIZE-1)
313
                return left_data_array[0];
314
        else
315
                return left_data_array[left_data_idx + 1];
316
}
317

    
318
inline void right_data_array_put(unsigned short int value) {
319
        if(right_data_idx == BUFFER_SIZE-1)
320
                right_data_idx = 0;
321
        else
322
                right_data_idx++;
323
        right_data_array[right_data_idx] = value;
324
}
325

    
326
inline unsigned int right_data_array_top(void) {
327
        return right_data_array[right_data_idx];
328
}
329

    
330
inline unsigned int right_data_array_prev(void) {
331
        if(right_data_idx == 0)
332
                return right_data_array[BUFFER_SIZE-1];
333
        else
334
                return right_data_array[right_data_idx - 1];
335
}
336

    
337
inline unsigned int right_data_array_bottom(void) {
338
        if(right_data_idx == BUFFER_SIZE-1)
339
                return right_data_array[0];
340
        else
341
                return right_data_array[right_data_idx + 1];
342
}
343