Project

General

Profile

Statistics
| Revision:

root / trunk / code / projects / linefollowing / lineFollow.c @ 1945

History | View | Annotate | Download (8.63 KB)

1
/**
2
 * @file lineFollow.c
3
 * @defgroup lineFollwing Line Following
4
 *
5
 * Takes care of following a line. Running this program is done by calling the
6
 * init() function and then the lineFollow(speed) command.  However, direct use
7
 * of this class is discouraged as its behavior is used by lineDrive.c, which
8
 * extends this class to provide behavior functionality.
9
 *
10
 * @author Dan Jacobs and the Colony Project
11
 * @date 11-1-2010
12
 */
13

    
14
#include "lineFollow.h"
15

    
16
//! The number of bits expected in a barcode
17
#define CODESIZE 5 
18

    
19
int countHi = 0;
20
int countLo = 0;
21
int maxAvg, avg;
22
int barCode[ CODESIZE ];
23
int barCodePosition=0;
24

    
25
int duration = 0;
26
int lastColor = 0;
27
char isReset = 0;
28

    
29
int turnDistance=0;
30
//! Counts the number of full line readings before we determine an intersection
31
int intersectionFilter=0;
32
int disableBarCode=0;
33

    
34
//! Keeps track of where the encoder of one motor started, for use in turns.
35
int encoderStart = -1;
36
int encoderReset = 0;   // 0 if encoderStart has no value set
37

    
38

    
39
void lineFollow_init()
40
{
41
        analog_init(0);
42
        lost = 0;
43
        intersectionFilter=0;
44
        disableBarCode=0;
45
}
46

    
47

    
48
/** 
49
 * Follows a line at the given speed.
50
 * @param speed The speed with which to follow the line.
51
 */
52
int lineFollow(int speed)
53
{
54
        int colors[5];
55
        int position;
56
        
57

    
58
        updateLine(colors);
59
        position = lineLocate(colors);         
60
        
61
        //not on line
62
        if(position == NOLINE)
63
        {
64
                if(lost++ > 20)
65
                {
66
                        orb2_set_color(GREEN);
67
                        motors_off();
68
                        return LINELOST;
69
                }
70
        }
71
        else if(position == FULL_LINE)
72
        {
73
                if(intersectionFilter++ > 4)
74
                {
75
                        orb2_set_color(RED);
76
                        barCodePosition=0;
77
                        disableBarCode=50;
78
                }
79
        }
80
        //on line
81
        else
82
        {
83
                position*=30;
84
                orb2_set_color(ORB_OFF);
85
                motorLeft(min(speed+position, 255));
86
                motorRight(min(speed-position, 255));
87
                lost=0;
88
                intersectionFilter=0;
89
        }
90

    
91
    // If we're running over a line, stop reading barcodes for a sec
92
        if(disableBarCode-- > 0)
93
        {
94
        // Return intersection once we cross the line
95
                if(disableBarCode) return NOBARCODE;
96
                return INTERSECTION;
97
        }
98
        updateBarCode();
99
        return getBarCode();
100
}
101

    
102

    
103
/**
104
 * Implements the left merge, assuming a line exists to the left.  Works by
105
 * turning off the line at an increasing angle and waiting to hit another line
106
 * on the left.
107
 */
108
int mergeLeft()
109
{
110
        motor_l_set(FORWARD, 200);
111
        if(turnDistance!=21)motor_r_set(FORWARD, 230);
112
        else motor_r_set(FORWARD, 210);
113
        int colors[5];
114
        updateLine(colors);
115
        int position = lineLocate(colors);
116
        if(position>3 || position<-3)turnDistance++;
117

    
118
        if(turnDistance>20)
119
        {
120
        turnDistance=21;
121
        
122
                if(position<3 && position>-3)
123
                {
124
                        turnDistance = 0;
125
                        return 0;
126
                }        
127
        }
128
        return 1;
129
}
130

    
131

    
132
/**
133
 * Implements the right merge, assuming a line exists to the right.  Works by
134
 * turning off the line at an increasing angle and waiting to hit another line
135
 * on the right.
136
 */
137
int mergeRight()
138
{
139
        motor_r_set(FORWARD, 200);
140
        if(turnDistance!=21)motor_l_set(FORWARD, 230);
141
        else motor_l_set(FORWARD, 210);
142
        int colors[5];
143
        updateLine(colors);
144
        int position = lineLocate(colors);
145
        if(position>3 || position<-3)turnDistance++;
146

    
147
        if(turnDistance>20)
148
        {
149
        turnDistance=21;
150

    
151
                if(position<3 && position>-3)
152
                {
153
                        turnDistance = 0;
154
                        return 0;
155
                } 
156
        }
157
        return 1;
158
}
159

    
160

    
161

    
162
/**
163
 * Turns left at a cross of two lines.  Assumes that we are at lines in a cross
164
 * pattern, and turns until it sets straight on the new line.
165
 * @return 0 if turn finishes otherwise return 1
166
 */
167
int turnLeft()
168
{
169
        /*motor_l_set(BACKWARD, 200);
170
        motor_r_set(FORWARD, 200);
171
        int colors[5];
172
        updateLine(colors);
173
        int position = lineLocate(colors);
174
        if(position>2 || position<-2)turnDistance++;
175
        if(turnDistance>1)
176
        {
177
                if(position<3 && position>-3)
178
                {
179
                        turnDistance = 0;
180
                         return 0;
181
                }
182
        }
183
        return 1;*/
184

    
185
        motor_l_set(BACKWARD,200);
186
        motor_r_set(FORWARD,200);
187
        if(!encoderReset)
188
        {
189
            encoderStart = encoder_get_x(RIGHT);
190
            encoderReset = 1;
191
        }
192

    
193
        if(encoder_get_x(RIGHT) < encoderStart)
194
        {
195
            encoderStart = 0;
196
            // Temporary: display an "error message" in case of overflow.
197
            // Using this for debugging, take it out soon!
198
            motor_l_set(FORWARD,0);
199
            motor_r_set(FORWARD,0);
200
            orb_set_color(WHITE);
201
            delay_ms(2000);
202
        }
203

    
204
        if(encoder_get_x(RIGHT) - encoderStart > 300)
205
        {
206
            encoderReset = 0;
207
            return 0;
208
        }
209
        return 1;
210
}
211

    
212

    
213

    
214
/**
215
 * Turns right at a cross of two lines.  Assumes that we are at lines in a cross
216
 * pattern, and turns until it sets straight on the new line.
217
 * @return 0 if the turn finishes otherwise return 1
218
 */
219
int turnRight()
220
{
221
        motor_r_set(BACKWARD, 200);
222
        motor_l_set(FORWARD, 200);
223
        int colors[5];
224
        updateLine(colors);
225
        int position = lineLocate(colors);
226
        if(position>2 || position<-2)turnDistance++;
227
        if(turnDistance>1) 
228
        {
229
                if(position<3 && position>-3)
230
                {
231
                        turnDistance = 0;
232
                         return 0;
233
                }
234
        }
235
        return 1;
236
}
237

    
238

    
239

    
240
int getBarCode()
241
{
242
        if(barCodePosition != CODESIZE)
243
        return NOBARCODE ;
244
    else
245
    {
246
        int temp = 0;
247
        for(int i=0; i<CODESIZE; i++)
248
            temp += (barCode[i] << i);
249
        barCodePosition = 0;
250
        return temp;
251
    }
252
}
253

    
254

    
255

    
256
void updateLine(int* values)
257
{        
258
        for(int i = 0; i<5; i++)
259
                values[i] = (read_line(4-i) < 150 ? LWHITE : LBLACK);
260
}
261

    
262

    
263

    
264
int lineLocate(int* colors)
265
{
266
        int i;
267
        int wsum = 0;
268
        int count=0;
269

    
270
        for(i = 0; i<5; i++)
271
        {
272
                count += colors[i]/2;
273
                wsum += (i)*colors[i];
274
        }
275
        if(count==0)
276
                return NOLINE;        
277
        if(count==5)
278
                return FULL_LINE;
279
        return (wsum/count)-4; // Subtract 4 to center the index around the center.
280
}
281

    
282

    
283
// new version by Alex
284
void updateBarCode()
285
{
286
    // USING THESE GLOBAL VARIABLES
287
    // global int duration = 0;
288
    // global int lastColor = 0;
289
    // global int barCodePosition = 0;
290
    // global char isReset = 0;
291

    
292
    // Average the readings of the last 2 sensors
293
    if(read_line(6) - read_line(7) > 150 || read_line(6) - read_line(7) < -150)
294
    {
295
        return;
296
    }
297

    
298
    int curReading = (read_line(6) + read_line(7)) / 2;
299
    int curColor;
300

    
301
    if(curReading > BLACK_THRESHOLD)
302
        curColor = LBLACK;
303
    else if(curReading < GREY_THRESHOLD)
304
        curColor = LWHITE;
305
    else
306
        curColor = LGREY;
307

    
308
    // Just an error check
309
    if(barCodePosition > CODESIZE)
310
    {
311
        barCodePosition = 0;
312
    }
313

    
314
    // We are only interested in consecutive color values
315
    if(curColor == lastColor)
316
    {
317
        duration++;
318
    }
319
    else
320
    {
321
        duration = 0;
322
        lastColor = curColor;
323
    }
324

    
325
    if(duration > MAX_DURATION)
326
    {
327
        // Now we assume our reading is significant - a bit, or a white space
328

    
329
        // Only read a value if we have read 0 first (isReset == 1)
330
        if(isReset && (curColor == LBLACK || curColor == LGREY) )
331
        {
332
            isReset = 0;
333
            usb_puts("Read barcode bit: ");
334
            usb_puti(barCodePosition);
335
            usb_puts(" = ");
336
            usb_puti(curColor);
337
            usb_puts(", curReading = ");
338
            usb_puti(curReading);
339
            usb_puts(".\n");
340

    
341
            barCode[barCodePosition++] = (curColor == LBLACK) ? 1 : 0;
342
        }
343
        else if(curColor == LWHITE)
344
        {
345
            isReset = 1;
346
        }
347
    }
348
    if(duration > TIMEOUT_DURATION && barCodePosition != 0)
349
    {
350
        usb_puts("TIMED OUT. BARCODE READER RESET.\n");
351
        barCodePosition = 0;
352
        duration = 0;
353
    }
354
}
355

    
356
// Dan's version
357
/*void updateBarCode()
358
{
359
        //! Note: currently only uses one of the barcode sensors.
360

361
        //maps the sensors to the analog input ports
362
        int ports[2] = {8,1};
363
        int current[2];
364
//        current[0] = analog_get10(ports[0]);
365
        //current[1] = analog_get10(ports[1]);
366
    current[1] = read_line(6);
367

368
        if(current[1] > 150)
369
        {
370
                if(countHi++ == 0) 
371
                {
372
                        avg = 500;
373
                        maxAvg = 500;
374
                }
375
                else
376
                {
377
                        avg = 3*avg + current[1];
378
                        avg/=4;
379
                        maxAvg = max(maxAvg, avg);
380
                }
381
        }
382
        else if(countHi > 5)
383
        {
384
                if(countLo++ > 15)
385
                {
386
                        countHi = countLo = 0;
387
                        if(maxAvg > 825)
388
                orb1_set_color(RED);
389
                        else orb1_set_color(BLUE);
390
                        barCode[barCodePosition++] = maxAvg > 825 ? 1:0;
391
                }
392
        }
393
        else countHi/=2;
394
        if(countHi==0)countLo=0; 
395
}*/
396

    
397

    
398
int min(int x, int y){return x>y ? y : x;}
399
int max(int x, int y){return x<y ? y : x;}
400

    
401
void motorLeft(int speed){
402
        ((speed-=127)>=0)?motor_l_set(FORWARD, 160+speed*95/128):motor_l_set(BACKWARD, 160-speed*95/127);
403
}
404

    
405
void motorRight(int speed){
406
        ((speed-=127)>=0)?motor_r_set(FORWARD, 160+speed*95/128):motor_r_set(BACKWARD, 160-speed*95/127);
407
}