-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathCEO_stage2.ino
268 lines (230 loc) · 7.47 KB
/
CEO_stage2.ino
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
//
// begin license header
//
// This file is part of Pixy CMUcam5 or "Pixy" for short
//
// All Pixy source code is provided under the terms of the
// GNU General Public License v2 (http://www.gnu.org/licenses/gpl-2.0.html).
// Those wishing to use Pixy source code, software and/or
// technologies under different licensing terms should contact us at
// [email protected]. Such licensing terms are available for
// all portions of the Pixy codebase presented here.
//
// end license header
//
// This sketch is a good place to start if you're just getting started with
// Pixy and Arduino. This program simply prints the detected object blocks
// (including color codes) through the serial console. It uses the Arduino's
// ICSP port. For more information go here:
//
// http://cmucam.org/projects/cmucam5/wiki/Hooking_up_Pixy_to_a_Microcontroller_(like_an_Arduino)
//
// It prints the detected blocks once per second because printing all of the
// blocks for all 50 frames per second would overwhelm the Arduino's serial port.
//
#include <QTRSensors.h>
#include <ZumoReflectanceSensorArray.h>
#include <ZumoMotors.h>
#include <ZumoBuzzer.h>
#include <Pushbutton.h>
#include <SPI.h>
#include <Pixy.h>
// This is the main Pixy object
Pixy pixy;
//motors
ZumoBuzzer buzzer;
ZumoReflectanceSensorArray reflectanceSensors;
ZumoMotors motors;
Pushbutton button(ZUMO_BUTTON);
int lastError = 0;
int m1Speed = 0;
int m2Speed = 0;
const int MAX_SPEED = 400;
//bool shortCut = false;
int stage = 1;
const int objectWidth = 70;
const int objectWidth2 = 70;
const int minObjectWidth2 = 15;
//TURNING SPEED WHEN SEARCH
const int turningSpeed = 150;
void setup()
{
Serial.begin(9600);
Serial.print("Starting...\n");
motors.setSpeeds(0, 0);
// Play a little welcome song
buzzer.play(">g32>>c32");
// Initialize the reflectance sensors module
reflectanceSensors.init();
// Wait for the user button to be pressed and released
// button.waitForButton();
// Turn on LED to indicate we are in calibration mode
pinMode(13, OUTPUT);
digitalWrite(13, HIGH);
// Wait 1 second and then begin automatic sensor calibration
// by rotating in place to sweep the sensors over the line
delay(1000);
int i;
for(i = 0; i < 80; i++)
{
if ((i > 10 && i <= 30) || (i > 50 && i <= 70))
motors.setSpeeds(-200, 200);
else
motors.setSpeeds(200, -200);
reflectanceSensors.calibrate();
// Since our counter runs to 80, the total delay will be
// 80*20 = 1600 ms.
delay(20);
}
motors.setSpeeds(0,0);
// Turn off LED to indicate we are through with calibration
digitalWrite(13, LOW);
pixy.init();
buzzer.play(">g32>>c32");
// Wait for the user button to be pressed and released
// button.waitForButton();
// Play music and wait for it to finish before we start driving.
delay(3000);
buzzer.play("L16 cdegreg4");
// while(buzzer.isPlaying());
}
void loop()
{
if(stage == 1){
unsigned int sensors[6];
// Get the position of the line. Note that we *must* provide the "sensors"
// argument to readLine() here, even though we are not interested in the
// individual sensor readings
int position = reflectanceSensors.readLine(sensors);
// Our "error" is how far we are away from the center of the line, which
// corresponds to position 2500.
int error = position - 2500;
// Get motor speed difference using proportional and derivative PID terms
// (the integral term is generally not very useful for line following).
// Here we are using a proportional constant of 1/4 and a derivative
// constant of 6, which should work decently for many Zumo motor choices.
// You probably want to use trial and error to tune these constants for
// your particular Zumo and line course.
int speedDifference = 0.15 * error + 40 * (error - lastError);
lastError = error;
m1Speed = MAX_SPEED + speedDifference;
m2Speed = MAX_SPEED - speedDifference;
// Here we constrain our motor speeds to be between 0 and MAX_SPEED.
// Generally speaking, one motor will always be turning at MAX_SPEED
// and the other will be at MAX_SPEED-|speedDifference| if that is positive,
// else it will be stationary. For some applications, you might want to
// allow the motor speed to go negative so that it can spin in reverse.
if (m1Speed < 0)
m1Speed = 0;
if (m2Speed < 0)
m2Speed = 0;
if (m1Speed > MAX_SPEED)
m1Speed = MAX_SPEED;
if (m2Speed > MAX_SPEED)
m2Speed = MAX_SPEED;
}
static int i = 0;
int j;
uint16_t blocks;
char buf[32];
// grab blocks!
blocks = pixy.getBlocks();
// If there are detect blocks, print them!
if (blocks)
{
i++;
// do this (print) every 50 frames because printing every
// frame would bog down the Arduino
if (i%1==0)
{
sprintf(buf, "Detected %d:\n", blocks);
Serial.print(buf);
int maxWidthDetected = 0;
bool detected = false;
int posX = 0;
for (j=0; j<blocks; j++)
{
sprintf(buf, " block %d: ", j);
// Serial.print();
// > 50 then detect zone B
// for bonus detect width>250
if((pixy.blocks[j].signature == 1) && (stage == 1)){
// if(maxWidthDetected > objectWidth){
// stage = 2;
// }
detected = true;
if(pixy.blocks[j].width > maxWidthDetected)
maxWidthDetected = pixy.blocks[j].width;
}else if((pixy.blocks[j].signature == 2) && (stage == 2) &&(pixy.blocks[j].width > minObjectWidth2)){
detected = true;
if(pixy.blocks[j].width > maxWidthDetected){
maxWidthDetected = pixy.blocks[j].width;
posX = pixy.blocks[j].x;
}
// if(pixy.blocks[j].x > (319/3) * 2){
// //turn right
// m1Speed = 150;
// m2Speed = -150;
// Serial.println("I detect it on my right");
// }
// else if(pixy.blocks[j].x < (319/3) * 1){
//
// //turn left
// m1Speed = -150;
// m2Speed = 150;
// Serial.println("I detect it on my left");
// }
// else{
// m1Speed = MAX_SPEED;
// m2Speed = MAX_SPEED;
// Serial.println("I detect it on my center");
// if(pixy.blocks[j].width > objectWidth2){
// stage = 1;
// }
// }
}else if(stage == 3){
m1Speed = 0;
m2Speed = 0;
}
}
if(stage == 1){
if(detected && maxWidthDetected > objectWidth){
stage = 2;
}
}else if(stage == 2){
if(detected){
if(posX > (319/3) * 2){
//turn right
m1Speed = turningSpeed;
m2Speed = -turningSpeed;
Serial.println("I detect it on my right");
}
else if(posX < (319/3) * 1){
//turn left
m1Speed = -turningSpeed;
m2Speed = turningSpeed;
Serial.println("I detect it on my left");
}
else{
m1Speed = MAX_SPEED;
m2Speed = MAX_SPEED;
Serial.println("I detect it on my center");
}
}
if(maxWidthDetected > objectWidth2){
stage = 1;
}
}
}
}else{
if(stage == 2){
m1Speed = turningSpeed;
m2Speed = -turningSpeed;
}
}
if(stage == 3){
m1Speed = 0;
m2Speed = 0;
}
motors.setSpeeds(m1Speed, m2Speed);
}