Project

General

Profile

Revision 2001

Commited activities_fair_demo for activites fair Fall 2011

View differences:

trunk/code/projects/activities_fair_demo/lineFollow.h
1
#include <dragonfly_lib.h>
2

  
3
#ifndef _LINEFOLLOW_H_
4
#define _LINEFOLLOW_H_
5

  
6
#define LWHITE			0
7
#define LGREY			1
8
#define LBLACK	 		2
9
#define BAD_READING     3
10
#define CENTER			3
11
#define LINELOST		-1
12

  
13
#define NOBARCODE 		-2
14
#define INTERSECTION 	-25
15

  
16
#define NOLINE			-50
17
#define FULL_LINE 		-51
18

  
19

  
20
//! Number of consecutive barcode color readings for a significant reading.
21
#define MAX_DURATION    20
22
//! Number of consecutive white barcode readings before a barcode reset.
23
#define TIMEOUT_DURATION    1000
24

  
25
#define NUM_READINGS 20
26

  
27
#define LEFT_SENSOR     1
28
#define RIGHT_SENSOR    0
29

  
30
/**
31
 * @brief Initializes line following.
32
 * 
33
 * Must be called before line following will work.
34
 * Turns the analog loop off.
35
 */
36
void lineFollow_init(void);
37

  
38
/**	lineFollow
39
 *	Must call lineFollow_init first
40
 *	Must be called inside a loop
41
 */
42
int lineFollow(int speed);
43

  
44
/**	turnLeft turnRight mergeLeft mergeRight
45
 *	Must be called inside a loop
46
 *	returns 0 when complete
47
 */
48
int turnLeft(void);
49
int turnRight(void);
50
int mergeLeft(void);
51
int mergeRight(void);
52

  
53
void addToBuckets(int curColor, int i);
54
void printBuckets();
55

  
56
/**
57
 * @brief Updates the values stored in the array to white or black based on
58
 * current sensor readings.
59
 *
60
 * @param values The array of five integers to be updated. 
61
 */
62
void updateLine(int* values); 
63

  
64
/**
65
 * @brief Returns an index of the middle of the line based on line readings.
66
 *
67
 * Two special return values are possible:
68
 *   NOLINE if none of the sensors holds a black value, and
69
 *   FULL_LINE if all of the sensors see black.
70
 *
71
 * Otherwise, returns a value from -4 (farthest left) to 4 (farthest right), with
72
 * 0 the line being centered in the middle.
73
 *
74
 * @param colors The array of 5 readings from the line sensor.  Must be either
75
 *    LWHITE or LBLACK.
76
 * @return Either a special value or an index from -4 to 4.
77
 *
78
 */
79
int lineLocate(int* colors);
80

  
81
/**	updatebarCode
82
 *	Reads in and processes
83
 *	bar code data
84
 */
85
void updateBarCode(void);
86

  
87
/**
88
 * @brief Gets the completed value read by the barcode reader, or NOBARCODE.
89
 *
90
 * Returns a bar code if available (if at the end of a barcode) and resets the
91
 * barcodePosition to 0. Otherwise, return NOBARCODE.  *
92
 * @return The value of the barcode if a complete barcode, else NOBARCODE.
93
 */
94
int getBarCode(void);
95

  
96

  
97
//! A simple function to return the minimum of two integers.
98
int min(int x, int y);
99
//! A simple function to return the maximum of two integers.
100
int max(int x, int y);
101

  
102
/** @todo Alex: I hate these functions, but I'm keeping them so code will still work. But we should delete them sometime. */
103

  
104
/**	motorLeft
105
 *	Commands the left motor
106
 *	Cannot be used to stop
107
 *	0-126 are backward
108
 *	127-255 are forward
109
 */
110
void motorLeft(int speed);
111

  
112
/**	motorRight
113
 *	Commands the right motor
114
 *	Cannot be used to stop
115
 *	0-126 are backward
116
 *	127-255 are forward
117
 */
118
void motorRight(int speed);
119

  
120
/**	lost
121
 *	Internal counter to detect if the line was lost
122
 */
123
int lost;
124

  
125
int onLine(void);
126

  
127
#endif
trunk/code/projects/activities_fair_demo/music.c
1
/*********
2
 * Music Library!
3
 * Now with twice the fiber!
4
 * 
5
 *  Jeff Cooper, Fall 2010
6
 ***************/
7
#ifndef MUSIC_FUNCTIONS
8
#define MUSIC_FUNCTIONS
9
void c0(int dur){buzzer_chirp(dur, 16);} 
10
void db0(int dur){buzzer_chirp(dur, 17);} 
11
void d0(int dur){buzzer_chirp(dur, 18);} 
12
void eb0(int dur){buzzer_chirp(dur, 19);} 
13
void e0(int dur){buzzer_chirp(dur, 20);} 
14
void f0(int dur){buzzer_chirp(dur, 21);} 
15
void gb0(int dur){buzzer_chirp(dur, 23);} 
16
void g0(int dur){buzzer_chirp(dur, 24);} 
17
void ab0(int dur){buzzer_chirp(dur, 25);} 
18
void a0(int dur){buzzer_chirp(dur, 27);} 
19
void bb0(int dur){buzzer_chirp(dur, 29);} 
20
void b0(int dur){buzzer_chirp(dur, 30);} 
21
void c1(int dur){buzzer_chirp(dur, 32);} 
22
void db1(int dur){buzzer_chirp(dur, 34);} 
23
void d1(int dur){buzzer_chirp(dur, 36);} 
24
void eb1(int dur){buzzer_chirp(dur, 38);} 
25
void e1(int dur){buzzer_chirp(dur, 41);} 
26
void f1(int dur){buzzer_chirp(dur, 43);} 
27
void gb1(int dur){buzzer_chirp(dur, 46);} 
28
void g1(int dur){buzzer_chirp(dur, 49);} 
29
void ab1(int dur){buzzer_chirp(dur, 51);} 
30
void a1(int dur){buzzer_chirp(dur, 55);} 
31
void bb1(int dur){buzzer_chirp(dur, 58);} 
32
void b1(int dur){buzzer_chirp(dur, 61);} 
33
void c2(int dur){buzzer_chirp(dur, 65);} 
34
void db2(int dur){buzzer_chirp(dur, 69);} 
35
void d2(int dur){buzzer_chirp(dur, 73);} 
36
void eb2(int dur){buzzer_chirp(dur, 77);} 
37
void e2(int dur){buzzer_chirp(dur, 82);} 
38
void f2(int dur){buzzer_chirp(dur, 87);} 
39
void gb2(int dur){buzzer_chirp(dur, 92);} 
40
void g2(int dur){buzzer_chirp(dur, 98);} 
41
void ab2(int dur){buzzer_chirp(dur, 103);} 
42
void a2(int dur){buzzer_chirp(dur, 110);} 
43
void bb2(int dur){buzzer_chirp(dur, 116);} 
44
void b2(int dur){buzzer_chirp(dur, 123);} 
45
void c3(int dur){buzzer_chirp(dur, 130);} 
46
void db3(int dur){buzzer_chirp(dur, 138);} 
47
void d3(int dur){buzzer_chirp(dur, 146);} 
48
void eb3(int dur){buzzer_chirp(dur, 155);} 
49
void e3(int dur){buzzer_chirp(dur, 164);} 
50
void f3(int dur){buzzer_chirp(dur, 174);} 
51
void gb3(int dur){buzzer_chirp(dur, 185);} 
52
void g3(int dur){buzzer_chirp(dur, 196);} 
53
void ab3(int dur){buzzer_chirp(dur, 207);} 
54
void a3(int dur){buzzer_chirp(dur, 220);} 
55
void bb3(int dur){buzzer_chirp(dur, 233);} 
56
void b3(int dur){buzzer_chirp(dur, 246);} 
57
void c4(int dur){buzzer_chirp(dur, 261);} 
58
void db4(int dur){buzzer_chirp(dur, 277);} 
59
void d4(int dur){buzzer_chirp(dur, 293);} 
60
void eb4(int dur){buzzer_chirp(dur, 311);} 
61
void e4(int dur){buzzer_chirp(dur, 329);} 
62
void f4(int dur){buzzer_chirp(dur, 349);} 
63
void gb4(int dur){buzzer_chirp(dur, 369);} 
64
void g4(int dur){buzzer_chirp(dur, 392);} 
65
void ab4(int dur){buzzer_chirp(dur, 415);} 
66
void a4(int dur){buzzer_chirp(dur, 440);} 
67
void bb4(int dur){buzzer_chirp(dur, 466);} 
68
void b4(int dur){buzzer_chirp(dur, 493);} 
69
void c5(int dur){buzzer_chirp(dur, 523);} 
70
void db5(int dur){buzzer_chirp(dur, 554);} 
71
void d5(int dur){buzzer_chirp(dur, 587);} 
72
void eb5(int dur){buzzer_chirp(dur, 622);} 
73
void e5(int dur){buzzer_chirp(dur, 659);} 
74
void f5(int dur){buzzer_chirp(dur, 698);} 
75
void gb5(int dur){buzzer_chirp(dur, 739);} 
76
void g5(int dur){buzzer_chirp(dur, 783);} 
77
void ab5(int dur){buzzer_chirp(dur, 830);} 
78
void a5(int dur){buzzer_chirp(dur, 880);} 
79
void bb5(int dur){buzzer_chirp(dur, 932);} 
80
void b5(int dur){buzzer_chirp(dur, 987);} 
81
void c6(int dur){buzzer_chirp(dur, 1046);} 
82
void db6(int dur){buzzer_chirp(dur, 1108);} 
83
void d6(int dur){buzzer_chirp(dur, 1174);} 
84
void eb6(int dur){buzzer_chirp(dur, 1244);} 
85
void e6(int dur){buzzer_chirp(dur, 1318);} 
86
void f6(int dur){buzzer_chirp(dur, 1396);} 
87
void gb6(int dur){buzzer_chirp(dur, 1479);} 
88
void g6(int dur){buzzer_chirp(dur, 1567);} 
89
void ab6(int dur){buzzer_chirp(dur, 1661);} 
90
void a6(int dur){buzzer_chirp(dur, 1760);} 
91
void bb6(int dur){buzzer_chirp(dur, 1864);} 
92
void b6(int dur){buzzer_chirp(dur, 1975);} 
93
void c7(int dur){buzzer_chirp(dur, 2093);} 
94
void db7(int dur){buzzer_chirp(dur, 2217);} 
95
void d7(int dur){buzzer_chirp(dur, 2349);} 
96
void eb7(int dur){buzzer_chirp(dur, 2489);} 
97
void e7(int dur){buzzer_chirp(dur, 2637);} 
98
void f7(int dur){buzzer_chirp(dur, 2793);} 
99
void gb7(int dur){buzzer_chirp(dur, 2959);} 
100
void g7(int dur){buzzer_chirp(dur, 3135);} 
101
void ab7(int dur){buzzer_chirp(dur, 3322);} 
102
void a7(int dur){buzzer_chirp(dur, 3520);} 
103
void bb7(int dur){buzzer_chirp(dur, 3729);} 
104
void b7(int dur){buzzer_chirp(dur, 3951);} 
105
void c8(int dur){buzzer_chirp(dur, 4186);} 
106
void db8(int dur){buzzer_chirp(dur, 4434);} 
107
void d8(int dur){buzzer_chirp(dur, 4698);} 
108
void eb8(int dur){buzzer_chirp(dur, 4978);} 
109
#endif
trunk/code/projects/activities_fair_demo/lineDrive.c
1
/**
2
 * @file lineDrive.c
3
 *
4
 * Provides functions to implement line driving behavior.  This program extends
5
 * the behavior of the line-following program by following lines automatically
6
 * and implementing behaviors to deal with commands passed to lineDrive.
7
 *
8
 * @author Dan Jacobs
9
 * @date 11-1-2010
10
 */
11

  
12
#include "lineDrive.h"
13

  
14
int state[5];       //! Stores a queue of sub-commands to be executed
15
int stateCounter;
16
int stateLength;
17

  
18
//! Whether lineDrive is currently paused. Set to 0 on initialization.
19
int stopped=1;
20

  
21

  
22
/**
23
 * Starts the line following procedure. Must be called before other
24
 * line-following functions will work.  This function essentially resets the
25
 * state of line-following.
26
 */
27
void lineDrive_init()
28
{
29
	lineFollow_init();
30
	for(int i=0; i<5; i++)state[i]=0;
31
	stateCounter=0;
32
	stateLength=0;
33
	stopped=0;
34
}
35

  
36

  
37
/**
38
 * Follows a line and executes whatever command is next on the queue.
39
 * @param speed The speed with which to drive along the line.
40
 */
41
int doDrive(int speed)
42
{
43
	if(stopped)
44
	{
45
		motor_l_set(FORWARD, 0);
46
		motor_r_set(FORWARD, 0);
47
		return NORMAL;
48
	}
49

  
50

  
51
	int code;
52
	switch(state[0])
53
	{	
54
	case ISTRAIGHT:
55
		code = lineFollow(speed);
56
		if(code==INTERSECTION)
57
		{
58
			for(int i=0; i<4; i++) state[i]=state[i+1];
59
			state[4]=0;
60
			if(state[0]==0)stateCounter++;
61
			break;
62
		}
63
		else if(code==NOBARCODE) return NORMAL;
64
		return code;
65

  
66

  
67
	case ILEFT:
68
		code = turnLeft();
69
		if(code==0)
70
		{
71
			state[0]=0;
72
			stateCounter++;
73
		}
74
		break;
75

  
76
        case IRIGHT:
77
                code = turnRight();
78
                if(code==0)
79
                {
80
			state[0]=0;
81
			stateCounter++;
82
		}
83
                break;
84

  
85

  
86
	case MERGELEFT:
87
		code = mergeLeft();
88
		if(code==0)
89
		{
90
			state[0]=0;
91
			stateLength=0;
92
			return FINISHED;
93
		}
94
		return NORMAL;
95

  
96
	case MERGERIGHT:
97
                code = mergeRight();
98
                if(code==0)
99
                {
100
                        state[0]=0;
101
                        stateLength=0;
102
			return FINISHED;
103
                }
104
                return NORMAL;
105

  
106
	default:
107
		return LOST;
108

  
109
	}
110

  
111
	if(stateCounter>=stateLength)
112
	{
113
		stateCounter=stateLength=0;
114
		return FINISHED;
115
	}
116
	return NORMAL;
117
}
118

  
119

  
120
/** Starts the line-drive process if paused. */
121
void start(void){stopped=0;}
122

  
123
/** Pauses the line-drive process. Default is started. */
124
void stop(void){stopped=1;}
125

  
126

  
127
/**
128
 * Defines a merge command in the direction specified.  A merge is a switch
129
 * of lanes.
130
 * @param dir Left or right, defined by ILEFT or IRIGHT
131
 */
132
int merge(int dir)
133
{
134
	if(stateLength!=0)return ERROR;
135
	stateLength++;
136
	state[0]=(dir==ILEFT ? MERGELEFT : MERGERIGHT);
137
	return NORMAL;
138
}
139

  
140
/**
141
 * Executes an intersection turn where the intersection type is specified by the
142
 * parameters. 
143
 * @param type A valid defined intersection type
144
 * @param dir The direction to turn at the intersection
145
 */
146
int turn(int type, int dir)
147
{
148
	if(stateLength!=0)return ERROR;
149
	if(dir==IRIGHT)
150
    {
151
        stateLength++;
152
        state[1]=IRIGHT;
153
        return NORMAL;
154
    }
155
	if(dir==IUTURN)
156
    {
157
        stateLength+=2;
158
        state[1]=state[2]=ILEFT;
159
        return NORMAL;
160
    }
161
	if(dir==ISTRAIGHT && type==SINGLE)
162
    {
163
        stateLength++;
164
        state[1]=ISTRAIGHT;
165
        return NORMAL;
166
    }
167
	if(dir==ISTRAIGHT)
168
    {
169
        stateLength+=2;
170
        state[1]=state[2]=ISTRAIGHT;
171
        return NORMAL;
172
    }
173
	// At this point, must be left turn
174
	if(type==SINGLE)
175
    {
176
        stateLength++;
177
        state[1]=ILEFT;
178
        return NORMAL;
179
    }
180
	if(type==DOUBLE_C || type==DOUBLE_T)
181
    {
182
        stateLength+=3;
183
        state[1]=state[3]=ISTRAIGHT;
184
        state[2]=ILEFT;
185
        return NORMAL;
186
    }
187
	if(type==ON_RAMP)
188
    {
189
        stateLength+=2;
190
        state[1]=ILEFT;
191
        state[2]=ISTRAIGHT;
192
        return NORMAL;
193
    }
194
	if(type==OFF_RAMP)
195
    {
196
        stateLength+=2;
197
        state[1]=ISTRAIGHT;
198
        state[2]=ILEFT;
199
        return NORMAL;
200
    }
201

  
202
	//Should never get here
203
	return ERROR;
204
}
205

  
trunk/code/projects/activities_fair_demo/main.c
1
/*
2
 * main.c for activities fair demo
3
 * 
4
 * Author: Colony Project, CMU Robotics Club
5
 */
6

  
7
#include <dragonfly_lib.h>
8
#include "../linefollowing/lineDrive.h"
9

  
10
#define LINESPEED 180
11
#define T 100
12
#define SPD 190
13
int main (void) {
14
	
15
	/* Initialize the dragonfly boards, the xbee, encoders, lineFollowing */
16
	dragonfly_init(ALL_ON);
17
	orb_init();
18
	if(button2_read()){
19
		lineDrive_init();
20
		while(true)
21
			doDrive(LINESPEED);
22
	} else {
23
		buzzer_init();
24
		orb1_set_color(YELLOW);
25
		a6(T/2);
26
		orb2_set_color(YELLOW);
27
		e7(T*3);
28
		delay_ms(T*3);
29
		while(1){
30
		  {	//i==1
31
					motor_l_set(FORWARD, SPD);
32
					motor_r_set(BACKWARD, SPD+10);
33
				orb1_set_color(GREEN);
34
			e6(T*2);
35
			b5(T);
36
			c6(T);
37
				orb2_set_color(GREEN);
38
			d6(T*2);
39
				orb2_set_color(CYAN);
40
			c6(T);
41
			
42
					motor_l_set(FORWARD, SPD-10);
43
					motor_r_set(FORWARD, SPD-10);;
44
			b5(T);
45
				orb1_set_color(CYAN);
46
			a5(T*2);
47
			a5(T);
48
			c6(T);
49
				orb1_set_color(ORANGE);
50
				orb2_set_color(ORANGE);
51
			e6(T*2);
52
				orb1_set_color(RED);
53
				orb2_set_color(RED);
54
			d6(T);
55
			c6(T);
56
				orb1_set_color(LIME);
57
				orb2_set_color(LIME);
58
			b5(T*3);
59
			c6(T);
60
			d6(T*2);
61
				orb1_set_color(BLUE);
62
		  }
63

  
64
		{	//i==2
65
					motor_l_set(FORWARD, SPD);
66
					motor_r_set(BACKWARD, SPD);
67
			e6(T*2);
68
				orb2_set_color(BLUE);
69
			c6(T*2);
70
				orb2_set_color(ORB_OFF);
71
			a5(T*2);
72
				orb1_set_color(ORB_OFF);
73
			a5(T);
74
			
75
		{			motors_off();
76
			a5(T*1);
77
			delay_ms(T*2);
78
		}	
79
					motor_l_set(FORWARD, SPD-10);
80
					motor_r_set(FORWARD, SPD-10);
81

  
82
			delay_ms(T);
83
				orb2_set_color(WHITE);
84
			d6(T);
85
			delay_ms(T);
86
				orb1_set_color(WHITE);
87
			f6(T);
88
				orb1_set_color(PINK);
89
				orb2_set_color(PINK);
90
			a6(T);
91
			c6(T/2);
92
			c6(T/2);
93
			g6(T);
94
			f6(T);
95
				orb1_set_color(GREEN);
96
				orb2_set_color(GREEN);
97
			e6(T*2);
98
			delay_ms(T);
99
				orb2_set_color(RED);
100
				orb1_set_color(RED);	
101
			c6(T);
102
			e6(T);
103
			a5(T/2);
104
			g5(T/2);
105

  
106
			d6(T);
107
		}				
108
		{	//i==3
109
					motor_l_set(FORWARD, SPD);
110
					motor_r_set(BACKWARD, SPD);
111
			c6(T);		
112
			b5(T*2);
113

  
114
			delay_ms(T);
115
				orb2_set_color(PURPLE);
116
				orb1_set_color(PURPLE);
117
			c6(T);
118
			d6(T*2);
119
				orb2_set_color(RED);		
120
					motor_r_set(FORWARD, SPD);
121
			e6(T*2);
122
				orb1_set_color(RED);
123
			c6(T*2);
124
				orb1_set_color(ORB_OFF);
125
			a5(T);
126
			a4(T);
127
				orb2_set_color(ORB_OFF);
128
			a5(T);
129
			a4(T);
130
			
131
		{
132
				motors_off();
133
			delay_ms(T*2);
134
				orb2_set_color(ORANGE);
135
				orb1_set_color(ORANGE);
136
			e6(T);
137
		}
138
					motor_l_set(FORWARD, SPD);
139
					motor_r_set(FORWARD, SPD);
140
			e6(T*3);
141
				orb2_set_color(RED);
142
				orb1_set_color(RED);
143
			c6(T*3);	
144
		}	
145
		{	//i==4
146
					motor_l_set(FORWARD, SPD);
147
					motor_r_set(BACKWARD, SPD);
148
			c6(T);
149
				orb2_set_color(MAGENTA);
150
				orb1_set_color(MAGENTA);
151
			d6(T*4);
152
				orb2_set_color(CYAN);
153
				orb1_set_color(CYAN);
154
			b5(T*2);	
155
				
156
					motor_r_set(FORWARD, SPD);
157
			b5(T*2);
158
				orb2_set_color(PURPLE);
159
				orb1_set_color(PURPLE);
160
			c6(T*4);
161
				orb2_set_color(PINK);
162
				orb1_set_color(PINK);
163
			a5(T*4);
164
				orb2_set_color(BLUE);
165
				orb1_set_color(GREEN);
166
			ab5(T*4);
167
				orb1_set_color(BLUE);
168
				orb2_set_color(GREEN);
169
			b5(T);
170
		}	
171
		{	//i==5
172
					motor_l_set(FORWARD, SPD);
173
					motor_r_set(BACKWARD, SPD);
174
			b5(T*2);
175
			delay_ms(T);
176
				orb2_set_color(ORANGE);
177
				orb1_set_color(ORANGE);
178
			e6(T*4);
179
				orb2_set_color(RED);
180
				orb1_set_color(RED);
181
				
182
					motor_r_set(FORWARD, SPD);
183
			c6(T*4);
184
				orb2_set_color(MAGENTA);
185
				orb1_set_color(MAGENTA);
186
			d6(T*4);
187
				orb2_set_color(CYAN);
188
				orb1_set_color(CYAN);
189
			b5(T*4);
190
			c6(T*2);
191
				orb1_set_color(WHITE);
192
			e6(T);
193
		}
194
					motors_off();
195
			
196
		{	//CIRCLE
197

  
198
				motor_l_set(FORWARD, SPD);
199
				motor_r_set(BACKWARD, SPD);
200
			e6(T);
201
				orb2_set_color(WHITE);
202
				
203
			a6(T*4);
204

  
205
		}
206
		{	//RESET
207
				motor_l_set(FORWARD, SPD+50);
208
				motor_r_set(FORWARD, SPD);
209
				
210
				orb1_set_color(LIME);
211
				orb2_set_color(LIME);
212
			ab6(T);
213
				orb1_set_color(ORB_OFF);
214
				orb2_set_color(ORB_OFF);
215
				
216
				delay_ms(T*13);
217
				
218
				motor_l_set(BACKWARD, SPD);
219
				motor_r_set(FORWARD, SPD);
220
				delay_ms(T*3);
221
		}
222
	
223
		motors_off();
224
		delay_ms(T*5);
225
		
226
		}
227
	}
228
	return 0;
229
}
trunk/code/projects/activities_fair_demo/update_linefollow.pl
1
#!/usr/bin/perl -W
2

  
3
my $line;
4
my $line2;
5

  
6
$line = `pwd`;
7
if($line =~ /linefollowing/igs) {
8
	print "Cannot modify linefollow code from linefollow\n";
9
} else {
10
	`rm lineFollow.*`;
11
	`rm lineDrive.*`;
12
	`cp ../linefollowing/lineFollow.* .`;
13
	`cp ../linefollowing/lineDrive.* .`;
14
}
15

  
16
if($line =~ /traffic_navigation/igs) {
17
	while(</*>) {
18
		if(/(.*?test)\.c/) {
19
			`mv $1.c $1.bak`;
20
		}
21
	}
22
}
0 23

  
trunk/code/projects/activities_fair_demo/lineDrive.h
1
#ifndef _LINE_DRIVE_
2
#define _LINE_DRIVE_
3

  
4
#include "lineFollow.h"
5

  
6
/* Old definitions, delete as soon as possible
7
#define DOUBLE   	0
8
#define SINGLE		1
9
#define ON_RAMP		2
10
#define OFF_RAMP	3
11
*/
12

  
13
#define SINGLE      0
14
#define ON_RAMP     1
15
#define OFF_RAMP    2
16
#define DOUBLE_C    3
17
#define DOUBLE_T    4
18

  
19
#define ISTRAIGHT	0
20
#define ILEFT		1
21
#define IRIGHT		2
22
#define IUTURN		3
23

  
24
#define MERGELEFT	4
25
#define MERGERIGHT	5
26

  
27
#define NORMAL		-1
28
#define FINISHED	-2
29
#define LOST		-3
30
#define ERROR		-4
31

  
32

  
33

  
34
void lineDrive_init(void);
35

  
36

  
37

  
38
int doDrive(int speed);
39

  
40
void start(void);
41
void stop(void);
42

  
43

  
44
int merge(int dir);
45

  
46
int turn(int type, int dir);
47

  
48
#endif
trunk/code/projects/activities_fair_demo/lineFollow.c
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
#define LINE_COLOR 200
19

  
20
/**
21
 * Helps with debugging.
22
 * 0 - no debug output.
23
 * 1 - print out buckets
24
 * 2 - print out line sensor readings
25
 */
26
#define DBG_LINEFOLLOW 2
27

  
28
//! Anything lower than this value is white
29
int GREY_THRESHOLD = 300;
30
//! Anything higher than this value is black
31
int BLACK_THRESHOLD = 750;
32

  
33
int countHi = 0;
34
int countLo = 0;
35
int maxAvg, avg;
36

  
37
// Everything has a dimension of 2 for left and right readings
38
int barCode[2][ CODESIZE ];
39
int barCodePosition[2]={0};
40

  
41
int duration[2] = {0};
42
int lastColor[2] = {0};
43
char isReset[2] = {1};
44
int lastReadings[2][ NUM_READINGS ] = {{0}};
45
int lastReadingsPtr[2] = {0};
46
int numLast[2][4] = { {0, 0, 0, NUM_READINGS}, {0, 0, 0, NUM_READINGS} };
47
int bitColor[2] = {0};
48

  
49
int turnDistance=0;
50
//! Counts the number of full line readings before we determine an intersection
51
int intersectionFilter=0;
52
int disableBarCode=0;
53

  
54
//! Keeps track of where the encoder of one motor started, for use in turns.
55
int encoderStart = -1;
56
int encoderReset = 0;   // 0 if encoderStart has no value set
57

  
58

  
59
void lineFollow_init()
60
{
61
    int i, j, curReading;
62
    int lowGrey = 1000, highGrey = 0, lowBlack = 1000,
63
        highBlack = 0;
64

  
65
	analog_init(0);
66
    encoders_init();
67
	lost = 0;
68
	intersectionFilter=0;
69
	disableBarCode=0;
70

  
71
    for(i=0; i<2; i++)
72
    {
73
        for(j=0; j<NUM_READINGS; j++)
74
        {
75
            lastReadings[i][j] = BAD_READING;
76
        }
77
        isReset[i] = 1;
78
    }
79
    
80
    // Calibrate thresholds
81
    orb_set_color(YELLOW);
82
    delay_ms(2000);
83

  
84
    orb_set_color(BLUE);
85

  
86
    for(i=0; i<100; i++)
87
    {
88
        curReading = read_line(LEFT_SENSOR + 6);
89
        if(curReading < lowGrey)
90
            lowGrey = curReading;
91
        if(curReading > highGrey)
92
            highGrey = curReading;
93

  
94
        delay_ms(20);
95
    }
96

  
97
    orb_set_color(YELLOW);
98
    delay_ms(2000);
99

  
100
    orb_set_color(GREEN);
101

  
102
    for(i=0; i<100; i++)
103
    {
104
        curReading = read_line(LEFT_SENSOR + 6);
105
        if(curReading < lowBlack)
106
            lowBlack = curReading;
107
        if(curReading > highBlack)
108
            highBlack = curReading;
109

  
110
        delay_ms(20);
111
    }
112

  
113
    orbs_set(0,0,0,0,0,0);
114

  
115
    GREY_THRESHOLD = (lowGrey + highGrey) / 2;
116
    BLACK_THRESHOLD = (highBlack + lowBlack) / 2;
117

  
118
    usb_puts("Grey: ");
119
    usb_puti(lowGrey);
120
    usb_puts(", ");
121
    usb_puti(highGrey);
122
    usb_puts("\nBlack: ");
123
    usb_puti(lowBlack);
124
    usb_puts(", ");
125
    usb_puti(highBlack);
126
    usb_puts("\nThresholds: ");
127
    usb_puti(GREY_THRESHOLD);
128
    usb_puts(", ");
129
    usb_puti(BLACK_THRESHOLD);
130
    usb_puts("\n\n");
131

  
132
    delay_ms(1500);
133

  
134
    //numLast = { {0, 0, 0, NUM_READINGS}, {0, 0, 0, NUM_READINGS} };
135
}
136

  
137

  
138
/** 
139
 * Follows a line at the given speed.
140
 * @param speed The speed with which to follow the line.
141
 */
142
int lineFollow(int speed)
143
{
144
	int colors[5];
145
	int position;
146
	
147

  
148
	updateLine(colors);
149
	position = lineLocate(colors); 	
150
	
151
	//not on line
152
	if(position == NOLINE)
153
	{
154
		if(lost++ > 20)
155
		{
156
			orb2_set_color(GREEN);
157
			motors_off();
158
			return LINELOST;
159
		}
160
	}
161
	else if(position == FULL_LINE)
162
	{
163
		if(intersectionFilter++ > 4)
164
		{
165
			orb2_set_color(RED);
166
			barCodePosition[0]=0;
167
            barCodePosition[1]=0;
168
			disableBarCode=50;
169
		}
170
	}
171
	//on line
172
	else
173
	{
174
		position*=30;
175
		orb2_set_color(ORB_OFF);
176
		motorLeft(min(speed+position, 255));
177
		motorRight(min(speed-position, 255));
178
		lost=0;
179
		intersectionFilter=0;
180
	}
181

  
182
    // If we're running over a line, stop reading barcodes for a sec
183
	if(disableBarCode-- > 0)
184
	{
185
        // Return intersection once we cross the line
186
		if(disableBarCode) return NOBARCODE;
187
		return INTERSECTION;
188
	}
189
	updateBarCode();
190
	return getBarCode();
191
}
192

  
193

  
194
/**
195
 * Implements the left merge, assuming a line exists to the left.  Works by
196
 * turning off the line at an increasing angle and waiting to hit another line
197
 * on the left.
198
 */
199
int mergeLeft()
200
{
201
	motor_l_set(FORWARD, 200);
202
	if(turnDistance!=21)motor_r_set(FORWARD, 230);
203
	else motor_r_set(FORWARD, 210);
204
	int colors[5];
205
	updateLine(colors);
206
	int position = lineLocate(colors);
207
	if(position>3 || position<-3)turnDistance++;
208

  
209
	if(turnDistance>20)
210
	{
211
	turnDistance=21;
212
	
213
		if(position<3 && position>-3)
214
		{
215
			turnDistance = 0;
216
			return 0;
217
		}	
218
	}
219
	return 1;
220
}
221

  
222

  
223
/**
224
 * Implements the right merge, assuming a line exists to the right.  Works by
225
 * turning off the line at an increasing angle and waiting to hit another line
226
 * on the right.
227
 */
228
int mergeRight()
229
{
230
        motor_r_set(FORWARD, 200);
231
        if(turnDistance!=21)motor_l_set(FORWARD, 230);
232
        else motor_l_set(FORWARD, 210);
233
        int colors[5];
234
        updateLine(colors);
235
        int position = lineLocate(colors);
236
        if(position>3 || position<-3)turnDistance++;
237

  
238
        if(turnDistance>20)
239
        {
240
        turnDistance=21;
241

  
242
                if(position<3 && position>-3)
243
                {
244
                        turnDistance = 0;
245
                        return 0;
246
                } 
247
        }
248
        return 1;
249
}
250

  
251

  
252

  
253
/**
254
 * Turns left at a cross of two lines.  Assumes that we are at lines in a cross
255
 * pattern, and turns until it sets straight on the new line.
256
 * @return 0 if turn finishes otherwise return 1
257
 */
258
int turnLeft()
259
{
260
        /*motor_l_set(BACKWARD, 200);
261
        motor_r_set(FORWARD, 200);
262
        int colors[5];
263
        updateLine(colors);
264
        int position = lineLocate(colors);
265
        if(position>2 || position<-2)turnDistance++;
266
        if(turnDistance>1)
267
        {
268
                if(position<3 && position>-3)
269
                {
270
                        turnDistance = 0;
271
                         return 0;
272
                }
273
        }
274
        return 1;*/
275

  
276
        motor_l_set(BACKWARD,200);
277
        motor_r_set(FORWARD,200);
278
        if(!encoderReset)
279
        {
280
            encoderStart = encoder_get_x(RIGHT);
281
            encoderReset = 1;
282
        }
283

  
284
        if(encoder_get_x(RIGHT) < encoderStart)
285
        {
286
            encoderStart = 0;
287
            // Temporary: display an "error message" in case of overflow.
288
            // Using this for debugging, take it out soon!
289
            motor_l_set(FORWARD,0);
290
            motor_r_set(FORWARD,0);
291
            //orb_set_color(WHITE);
292
            delay_ms(2000);
293
        }
294

  
295
        if(encoder_get_x(RIGHT) - encoderStart > 300)
296
        {
297
            encoderReset = 0;
298
            return 0;
299
        }
300
        return 1;
301
}
302

  
303

  
304

  
305
/**
306
 * Turns right at a cross of two lines.  Assumes that we are at lines in a cross
307
 * pattern, and turns until it sets straight on the new line.
308
 * @return 0 if the turn finishes otherwise return 1
309
 */
310
int turnRight()
311
{
312
        motor_r_set(BACKWARD, 200);
313
        motor_l_set(FORWARD, 200);
314
        int colors[5];
315
        updateLine(colors);
316
        int position = lineLocate(colors);
317
        if(position>2 || position<-2)turnDistance++;
318
        if(turnDistance>1) 
319
	{
320
		if(position<3 && position>-3)
321
		{
322
			turnDistance = 0;
323
			 return 0;
324
		}
325
	}
326
	return 1;
327
}
328

  
329

  
330

  
331
int getBarCode()
332
{
333
	if(barCodePosition[1] != CODESIZE)
334
        return NOBARCODE ;
335
    else
336
    {
337
        int temp = 0;
338
        for(int i=0; i<CODESIZE; i++)
339
            temp += (barCode[1][i] << i);
340
        barCodePosition[1] = 0;
341
        return temp;
342
    }
343
}
344

  
345

  
346

  
347
void updateLine(int* values)
348
{	
349
	for(int i = 0; i<5; i++)
350
		values[i] = (read_line(4-i) < LINE_COLOR ? LWHITE : LBLACK);
351
}
352

  
353

  
354

  
355
int lineLocate(int* colors)
356
{
357
	int i;
358
	int wsum = 0;
359
	int count=0;
360

  
361
	for(i = 0; i<5; i++)
362
	{
363
		count += colors[i]/2;
364
		wsum += (i)*colors[i];
365
	}
366
	if(count==0)
367
		return NOLINE;	
368
	if(count==5)
369
		return FULL_LINE;
370
	return (wsum/count)-4; // Subtract 4 to center the index around the center.
371
}
372

  
373
void printBuckets(int i)
374
{
375
    int j;
376

  
377
    usb_puts("LP[");
378
    usb_puti(i);
379
    usb_puts("]: ");
380
    usb_puti(lastReadingsPtr[i]);
381
    usb_puts(", Totals: ");
382

  
383
    for(int j=0; j<=3; j++)
384
    {
385
        usb_puts("[");
386
        usb_puti(j);
387
        usb_puts("]: ");
388
        usb_puti(numLast[i][j]);
389
        usb_puts(" ");
390
    }
391
    usb_puts("\t ");
392
    usb_puts("\n");
393
}
394

  
395
void addToBuckets(int curColor, int i)
396
{
397
    int oldest = lastReadings[i][lastReadingsPtr[i]];
398
    numLast[i][oldest]--;
399
    lastReadings[i][lastReadingsPtr[i]] = curColor;
400
    lastReadingsPtr[i] = (lastReadingsPtr[i]+1) % NUM_READINGS;
401
    numLast[i][curColor]++;
402

  
403
    if(DBG_LINEFOLLOW == 1)
404
    {
405
        printBuckets(i);
406
    }
407
}
408

  
409
void updateBarCode()
410
{
411
    // USING THESE GLOBAL VARIABLES
412
    // global int duration = 0;
413
    // global int lastColor = 0;
414
    // global int barCodePosition = 0;
415
    // global char isReset = 0;
416

  
417
    // Just uses one sensor for now
418
    for(int i = /*RIGHT*/LEFT_SENSOR; i <= LEFT_SENSOR; i++)
419
    {
420
        // Add 6 to convert left (1) and right (0) to sensor 6 and 7
421
        int curReading = read_line(i + 6);
422
        int curColor;
423

  
424
        if(curReading > BLACK_THRESHOLD)
425
        {
426
            curColor = LBLACK;
427
        }
428
        else if(curReading < GREY_THRESHOLD)
429
        {
430
            curColor = LWHITE;
431
        }
432
        else
433
        {
434
            curColor = LGREY;
435
        }
436

  
437
        // Keep track of this reading
438
        addToBuckets(curColor, i);
439

  
440
        // Just an error check
441
        if(barCodePosition[i] > CODESIZE)
442
        {
443
            barCodePosition[i] = 0;
444
        }
445

  
446
        // We now edit curColor to use the majority of the last buckets.
447
        if(numLast[i][1] > NUM_READINGS / 2)
448
        {
449
            curColor = LGREY;
450
        }
451
        else if(numLast[i][2] > NUM_READINGS / 2)
452
        {
453
            curColor = LBLACK;
454
        }
455
        else if(numLast[i][0] > NUM_READINGS / 2)
456
        {
457
            curColor = LWHITE;
458
            duration[i]++;
459
        }
460
        else
461
        {
462
            curColor = BAD_READING;
463
        }
464

  
465
        // Print out the current reading and label, if in debug mode
466
        if(DBG_LINEFOLLOW == 2)
467
        {
468
            switch(curColor)
469
            {
470
                case LBLACK: usb_puts("LBLACK.\t"); break;
471
                case LGREY: usb_puts("LGREY.\t\t"); break;
472
                case LWHITE: usb_puts("LWHITE.\t\t\t"); break;
473
            }
474
            usb_puti(curReading);
475
            usb_puts("\n");
476
        }
477
    
478
        if(curColor != BAD_READING)
479
        {
480
            // Now we assume our reading is significant - a bit, or a white space
481

  
482
            if(bitColor[i] == LGREY || bitColor[i] == LWHITE)
483
                bitColor[i] = curColor;
484

  
485
            // Only read a value if we have read 0 first (isReset == 1)
486
            if(isReset[i] && (curColor == LBLACK || curColor == LGREY) )
487
            {
488
                isReset[i] = 0;
489
                duration[i] = 0;
490
            }
491
            else if(curColor == LWHITE)
492
            {
493
                if(!isReset[i])
494
                {
495
                    barCode[i][barCodePosition[i]++] = 
496
                        (bitColor[i] == LBLACK) ? 1 : 0;
497
                    usb_puts("Reset. Read bit: ");
498
                    usb_puts(((bitColor[i] == LBLACK) ? "BLACK" : "GREY"));
499
                    usb_puts("\t");
500
                    usb_puts(((curColor==LWHITE) ? "LWHITE" : "NOTWHITE"));
501
                    usb_puts("\n");
502

  
503
                    bitColor[i] = LWHITE;
504
                }
505
                isReset[i] = 1;
506
                orb_set(0, 0, 0);
507
            }
508
        }
509

  
510
        if(curColor == LWHITE && duration[i] > TIMEOUT_DURATION 
511
            && barCodePosition[i] != 0)
512
        {
513
            usb_puts("TIMED OUT. BARCODE READER RESET.\n");
514
            usb_puts("Encoders: ");
515
            usb_puti(encoder_get_dx(LEFT));
516
            usb_puts(", ");
517
            usb_puti(encoder_get_dx(RIGHT));
518
            usb_puts("\n");
519
            barCodePosition[i] = 0;
520
            duration[i] = 0;
521
            isReset[i] = 1;
522
        }
523
    }
524
}
525

  
526

  
527
int min(int x, int y){return x>y ? y : x;}
528
int max(int x, int y){return x<y ? y : x;}
529

  
530
void motorLeft(int speed){
531
	((speed-=127)>=0)?motor_l_set(FORWARD, 160+speed*95/128):motor_l_set(BACKWARD, 160-speed*95/127);
532
}
533

  
534
void motorRight(int speed){
535
        ((speed-=127)>=0)?motor_r_set(FORWARD, 160+speed*95/128):motor_r_set(BACKWARD, 160-speed*95/127);
536
}
trunk/code/projects/activities_fair_demo/Makefile
1
# this is a local makefile special for traffic navigation
2

  
3
# Relative path to the root directory (containing lib directory)
4
ifndef COLONYROOT
5
COLONYROOT := ..
6

  
7
# Target file name (without extension).
8
TARGET = main
9

  
10
# Uncomment this to use the wireless library
11
USE_WIRELESS = 1
12

  
13
# com1 = serial port. Use lpt1 to connect to parallel port.
14
AVRDUDE_PORT = $(shell if uname -s |grep -i w32 >/dev/null; then echo 'COM4:'; else echo '/dev/ttyUSB0'; fi)
15

  
16
else
17
COLONYROOT := ../$(COLONYROOT)
18
endif
19

  
20
include $(COLONYROOT)/Makefile

Also available in: Unified diff