|
1 |
|
|
2 |
/*** PROGRAM INFORMATION ***
|
|
3 |
|
|
4 |
This program assembles a group of robots into a circle and allows them movement
|
|
5 |
within that formation. Robots should be able to break formation and travel as a
|
|
6 |
line, readjust in the face of obstacles, and reform if conditions are necessary.
|
|
7 |
|
|
8 |
The program begins waiting for a button press. When pressed, a robot assumes the
|
|
9 |
BEACON position, which means that it is the robot in the center of the circle and
|
|
10 |
therefore in charge. It then gathers robots around it by sending them commands.
|
|
11 |
This code is executed using two finite state machines, nested inside one another.
|
|
12 |
One controls the overall state of the robot (whether it is a BEACON, an EDGE, or
|
|
13 |
WAITING, for example).
|
|
14 |
|
|
15 |
This code should be implemented so that most useful functions are built in to the
|
|
16 |
machine. For example, the BEACON robot should be able to call methods such as
|
|
17 |
CircleUp() to gather robots around it, and Move(distance) to move the circle group
|
|
18 |
all at once.
|
|
19 |
|
|
20 |
This Code is the property of the Carnegie Mellon Robotics Club and is being used
|
|
21 |
to test formation control in a low-cost robot colony. Thanks to all members of
|
|
22 |
RoboClub, especially Colony president John Sexton and the ever-present Chris Mar.
|
|
23 |
|
|
24 |
AUTHORS: James Carroll, Steve DeVincentis, Hanzhang (Echo) Hu, Nico Paris, Joel Rey,
|
|
25 |
Reva Street, Alex Zirbel */
|
|
26 |
|
|
27 |
|
| 1 |
28 |
#include <dragonfly_lib.h>
|
| 2 |
29 |
#include <wl_basic.h>
|
| 3 |
30 |
#include <encoders.h>
|
| ... | ... | |
| 3 |
30 |
#include "circle.h"
|
| 4 |
31 |
|
| 5 |
|
/*
|
| 6 |
|
Current situation:
|
| 7 |
|
go to the center. ends when each edge robto send "I am here" message
|
|
32 |
/*** TODO: ***
|
| 8 |
33 |
|
| 9 |
|
TODO:
|
| 10 |
|
Center:
|
| 11 |
|
1. Make a move forward method/state to make the circle begin moving as a group.
|
|
34 |
- Transform the code into a method-based state machine that uses the procedural state
|
|
35 |
machines, which are hardcoded and hard to edit, as a backup.
|
|
36 |
- Implement a drive straight method for use in keeping the robots more accurate as a
|
|
37 |
group.
|
|
38 |
- Fix the approach method: good robots usually work well, but bad robots often have
|
|
39 |
errors which might be avoidable with the use of error checking.
|
|
40 |
- Make robots more robust: packages are often lost, which throws the entire procedural
|
|
41 |
nature of the program off.
|
|
42 |
- Consider using the center bot to check distances
|
|
43 |
- More testing is always good and necessary. */
|
| 12 |
44 |
|
| 13 |
|
Edge:
|
| 14 |
|
2. Find a way to follow the middle robot and preserve circle structure, or follow a directional command given by the center robot.
|
| 15 |
|
3. Fix the error case with wireless - if the center robot does not receive the first exist packet, the robot keeps sending it and will cause error later.
|
|
45 |
/*** BOT LOG ***
|
| 16 |
46 |
|
| 17 |
|
In general:
|
| 18 |
|
More testing. Especially with robots that are actually working.
|
| 19 |
|
*/
|
|
47 |
4-1-2010: BOT 7 as BEACON and BOT 1 as EDGE worked extremely well.
|
|
48 |
4-2-2010: BOT 7 and BOT 14 worked extremely well, no matter states. BOT 1 started
|
|
49 |
well, but malfunctioned later. */
|
| 20 |
50 |
|
|
51 |
/*** TERMINOLOGY ***
|
| 21 |
52 |
|
| 22 |
|
/*
|
| 23 |
|
This program is used to make robots target a center (leader) robot using the BOM,
|
| 24 |
|
then drive toward it and stop at a certain distance away.
|
| 25 |
|
|
| 26 |
|
The distance will eventually be adjustable.
|
|
53 |
WAITINGSTATE:
|
|
54 |
The robot waits to be given a signal to do something. Wireless is on, in
|
|
55 |
case the robot is called on to turn into an EDGE. The color should be LIME
|
|
56 |
or YELLOW-GREEN.
|
| 27 |
57 |
|
| 28 |
|
With adjustment, the leader robot will be able to turn and use its standardized
|
| 29 |
|
rangefinder to reposition or space the robots evenly.
|
| 30 |
|
|
| 31 |
|
AuTHORS: Nico, Alex, Reva, Echo, Steve, Joel
|
| 32 |
|
*/
|
|
58 |
BEACON_CONTROL:
|
|
59 |
The code that executes commands when a robot is turned to BEACON mode. This
|
|
60 |
code may run predefined methods for simplicity. One goal is to make these
|
|
61 |
methods change the robot turn to to BEACON_MACHINE mode for a while, and then
|
|
62 |
return to the CONTROL code where they left off.
|
| 33 |
63 |
|
|
64 |
EDGE_CONTROL:
|
|
65 |
Like BEACON_CONTROL, executes whatever orders are required of the robot as an
|
|
66 |
EDGE.
|
| 34 |
67 |
|
| 35 |
|
/*
|
| 36 |
|
TODO:
|
| 37 |
|
Used: Bots 1, 7
|
| 38 |
|
4-1-2010: BOT 7 as BEACON and BOT 1 as EDGE worked extremely well.
|
| 39 |
|
16 Performed Badly
|
| 40 |
|
12 worked ok as beacon, not well as edge
|
| 41 |
|
|
| 42 |
|
Fix orient code so the bot does not toggle back and forth when it tries to turn
|
| 43 |
|
|
| 44 |
|
Use the center bot to check distances
|
| 45 |
|
Done--> Count them ("spam" method)
|
| 46 |
|
Use beacon to find relative positions
|
| 47 |
|
Beacon tells them how to move to be at the right distance
|
| 48 |
|
*done*Wireless communication, initialization
|
| 49 |
|
*/
|
|
68 |
BEACON_MACHINE:
|
|
69 |
A hardcoded list of functions which the robot is capable of running through.
|
|
70 |
Consists of a finite state machine, where the robot executes a set of commands
|
|
71 |
in a procedural manner and then returns to wherever it was in the control code.
|
| 50 |
72 |
|
| 51 |
|
int EDGE = 0;
|
| 52 |
|
int BEACON = 1;
|
|
73 |
EDGE_MACHINE:
|
|
74 |
Like the BEACON_MACHINE, but contains the same sort of procedural information
|
|
75 |
for EDGE robots.
|
|
76 |
|
|
77 |
END:
|
|
78 |
A terminal state of the machine, where the robot just sits and waits. The
|
|
79 |
color should be GREEN and WHITE.
|
|
80 |
|
|
81 |
|
|
82 |
TYPES OF WIRELESS PACKETS:
|
|
83 |
CIRCLE_ACTION_EXIST 'E'
|
|
84 |
CIRCLE_ACTION_POSITION 'P'
|
|
85 |
CIRCLE_ACTION_ACK 'A'
|
|
86 |
A general acknowledgement package.
|
|
87 |
CIRCLE_ACTION_DONE 'D'
|
|
88 |
Used by robots to tell when they have finished their action.
|
|
89 |
CIRCLE_ACTION_GOTYOU 'G'
|
|
90 |
Used by the BEACON to tell a robot when it has been checked off.
|
|
91 |
At this point, the EDGE has been recognized. Used for times when
|
|
92 |
all EDGE robots have to communicate to the center via the spam method.
|
|
93 |
CIRCLE_ACTION_FORWARD 'F'
|
|
94 |
The BEACON tells the rest of the robots to move forward.
|
|
95 |
CIRCLE_CLAIM_CENTER 'C'
|
|
96 |
Sent out by a robot when it takes over as BEACON. */
|
|
97 |
|
|
98 |
|
|
99 |
|
|
100 |
int END = 100;
|
|
101 |
int WAITINGSTATE = 0; /* Define some variables to keep track of the state machine.*/
|
|
102 |
int EDGE_CONTROL = 1;
|
|
103 |
int BEACON_CONTROL = 2;
|
|
104 |
int EDGE_MACHINE = 3;
|
|
105 |
int BEACON_MACHINE = 4;
|
|
106 |
|
|
107 |
|
| 53 |
108 |
int timeout = 0;
|
| 54 |
109 |
int sending = 0;
|
| ... | ... | |
| 85 |
140 |
motor_l_set(BACKWARD,speed);
|
| 86 |
141 |
motor_r_set(FORWARD,speed);
|
| 87 |
142 |
}
|
| 88 |
|
void stop(void){ // could be set to motors_off(), or just use this as an alternative.
|
| 89 |
|
motor_l_set(BACKWARD,0); // stop() is better - motors_off() creates a slight delay to turn them back on.
|
|
143 |
void stop(void){ // could be set to motors_off(), or just use this as an alternative.
|
|
144 |
motor_l_set(BACKWARD,0); // stop() is better - motors_off() creates a slight delay to turn them back on.
|
| 90 |
145 |
motor_r_set(FORWARD,0);
|
| 91 |
146 |
}
|
| 92 |
147 |
void setforward(int spd1, int spd2){
|
| ... | ... | |
| 133 |
188 |
send_buffer[0]=arg0;
|
| 134 |
189 |
send_buffer[1]=arg1;
|
| 135 |
190 |
send_buffer[2]=arg2;
|
| 136 |
|
wl_basic_send_global_packet(42,send_buffer,2);
|
|
191 |
wl_basic_send_global_packet(42,send_buffer,3);
|
| 137 |
192 |
}
|
| 138 |
193 |
|
| 139 |
194 |
/*
|
| ... | ... | |
| 221 |
276 |
|
| 222 |
277 |
|
| 223 |
278 |
|
| 224 |
|
|
| 225 |
|
|
| 226 |
279 |
//*****************************************************************************************************************************************************************************************
|
|
280 |
//*****************************************************************************************************************************************************************************************
|
|
281 |
//*****************************************************************************************************************************************************************************************
|
| 227 |
282 |
|
| 228 |
283 |
|
| 229 |
|
|
| 230 |
|
|
| 231 |
|
|
| 232 |
|
|
| 233 |
284 |
/*
|
| 234 |
|
A double state machine. The robot is either an "edge" or a "beacon" depending on the initial potentiometer reading.
|
|
285 |
A state machine with five states. The robot starts out in WAITINGSTATE mode, from which
|
|
286 |
it recieves a signal of some sort and moves to a different state.
|
| 235 |
287 |
*/
|
| 236 |
288 |
int main(void)
|
| 237 |
289 |
{
|
| ... | ... | |
| 239 |
291 |
dragonfly_init(ALL_ON);
|
| 240 |
292 |
/* Initialize the basic wireless library */
|
| 241 |
293 |
wl_basic_init_default();
|
| 242 |
|
/* Set the XBee channel to your assigned channel */ /* Set the XBee channel to your assigned channel */
|
|
294 |
/* Set the XBee channel to 24 - must be standard among robots */
|
| 243 |
295 |
wl_set_channel(24);
|
| 244 |
296 |
|
| 245 |
297 |
int robotid = get_robotid();
|
| 246 |
|
int centerid = 0;
|
| 247 |
|
int used[17];
|
| 248 |
|
for (int i=0; i<17; i++) used[i] = 0;
|
| 249 |
|
char send_buffer[2];
|
| 250 |
|
int data_length;
|
|
298 |
int centerid = 0; // once the EDGE gets the first signal from a center, it stores who the center is.
|
|
299 |
int used[17]; // stores a list of bots which are in the group by storing a "1" in the array if the robot of that index is in the group.
|
|
300 |
for (int i=0; i<17; i++) used[i] = 0; // initially, no robots in the group.
|
|
301 |
|
|
302 |
int data_length; // keeps track of the length of wireless packets received.
|
| 251 |
303 |
unsigned char *packet_data=wl_basic_do_default(&data_length);
|
| 252 |
304 |
|
| 253 |
|
|
| 254 |
|
int state = EDGE;
|
| 255 |
|
int beacon_State=0;
|
|
305 |
int state = WAITINGSTATE;
|
|
306 |
int beacon_State=0; // these variables keep track of the inner state machines in the procedural MACHINE states.
|
| 256 |
307 |
int edge_State=0;
|
|
308 |
|
| 257 |
309 |
int waitingCounter=0;
|
| 258 |
|
int robotsReceived=0;
|
| 259 |
|
int offset = 20;
|
|
310 |
int robotsReceived=0; // an important variable that stores the size of the group.
|
|
311 |
int offset = 20; // offset for the approaching: how far off the rangefinders can be
|
| 260 |
312 |
int time=0;
|
| 261 |
|
int direction = 4; // keeps track of which way robots are facing relative to the center
|
|
313 |
int direction = 4; // keeps track of which way robots are facing relative to the center
|
|
314 |
int distance=1000; // how far away the robot is. Initialized to a large value to ensure that the robot doesn't think it is already the
|
|
315 |
// right distance away.
|
|
316 |
int onefoot = 250; // how far away to stop.
|
| 262 |
317 |
|
| 263 |
|
if(wheel()>100)
|
| 264 |
|
{
|
| 265 |
|
state=BEACON;
|
| 266 |
|
}
|
| 267 |
|
|
| 268 |
|
int distance=1000; // how far away to stop.
|
| 269 |
|
int onefoot=250, speed=250; // one foot is 490 for bot 1; one foot is 200 for bot6
|
| 270 |
|
|
| 271 |
318 |
while(1)
|
| 272 |
319 |
{
|
| 273 |
320 |
bom_refresh(BOM_ALL);
|
|
321 |
|
|
322 |
/*
|
|
323 |
*******EXPECTED MOVES ********** (OUT OF DATE. Will be updated once changes have been made.)
|
|
324 |
The designed movement:
|
|
325 |
1. one center robot, several edge robots are on;
|
|
326 |
2. center robots: button 1 is pressed;
|
|
327 |
3. center robots: send global package telling edges that he exists;
|
|
328 |
4. EDGE robots response with ACK.
|
|
329 |
5. EDGE robots wait for center robots to finish counting (DONE package)
|
|
330 |
6. EDGE robtos approach the center robtot and stop at the "onefoot" distance, send message to the center
|
|
331 |
*/
|
| 274 |
332 |
|
| 275 |
|
/*
|
| 276 |
|
*******TERMinology**************
|
| 277 |
|
EDGE=0 other names: slave. Definition: robots on the edge of the circle;
|
| 278 |
|
BEACON=1 other name: master. Definition: robots in the center of the circle;
|
| 279 |
333 |
|
| 280 |
|
|
| 281 |
|
*******EXPECTED MOVES **********
|
| 282 |
|
The designed movement:
|
| 283 |
|
1. one center robot, several edge robots are on;
|
| 284 |
|
2. center robots: button 1 is pressed;
|
| 285 |
|
3. center robots: send global package telling edges that he exists;
|
| 286 |
|
4. EDGE robots response with ACK.
|
| 287 |
|
5. EDGE robots wait for center robots to finish counting (DONE package)
|
| 288 |
|
6. EDGE robtos approach the center robtot and stop at the "onefoot" distance, send message to the center
|
| 289 |
|
*/
|
| 290 |
|
|
| 291 |
|
|
| 292 |
|
// decide if its is center or not. This is the main switch loop which governs the entire state of the robot.
|
|
334 |
/* This is the MAIN SWITCH LOOP, which governs the overall status of the robot. */
|
| 293 |
335 |
switch(state)
|
| 294 |
336 |
{
|
| 295 |
|
/**********
|
| 296 |
|
if EDGE /slave robots
|
|
337 |
|
|
338 |
|
|
339 |
/*
|
|
340 |
The WAITINGSTATE. This state constantly checks for wireless packets,
|
|
341 |
and updates its state as soon as it receives a signal.
|
| 297 |
342 |
*/
|
| 298 |
|
case 0:
|
|
343 |
case 0:
|
| 299 |
344 |
|
|
345 |
packet_data=wl_basic_do_default(&data_length);
|
|
346 |
if(packet_data != 0 && data_length>=2 && packet_data[0]==CIRCLE_CLAIM_CENTER)
|
|
347 |
{
|
|
348 |
centerid = packet_data[1];
|
|
349 |
|
|
350 |
send2(CIRCLE_ACTION_ACK,robotid);
|
|
351 |
|
|
352 |
state = EDGE_CONTROL;
|
|
353 |
}
|
|
354 |
|
|
355 |
if(button1_read())
|
|
356 |
{
|
|
357 |
send2(CIRCLE_CLAIM_CENTER, robotid); // becomes the center if button1 is clicked.
|
|
358 |
}
|
|
359 |
|
|
360 |
break;
|
|
361 |
|
|
362 |
|
|
363 |
|
|
364 |
//***********************************************************************************************************************************************************************************
|
|
365 |
|
|
366 |
|
|
367 |
|
|
368 |
/*
|
|
369 |
The CONTROL for the EDGE state. This sets a certain procedure to follow, in the form of simple
|
|
370 |
commands, for a robot to follow if it is set to an EDGE.
|
|
371 |
*/
|
|
372 |
|
|
373 |
case 1:
|
|
374 |
|
|
375 |
break;
|
|
376 |
|
|
377 |
|
|
378 |
|
|
379 |
//***********************************************************************************************************************************************************************************
|
|
380 |
|
|
381 |
|
|
382 |
|
|
383 |
/*
|
|
384 |
The CONTROL for the BEACON state. This sets a certain procedure to follow, in the form of simple
|
|
385 |
commands, for a robot to follow if it is set to a BEACON.
|
|
386 |
*/
|
|
387 |
case 2:
|
|
388 |
|
|
389 |
break;
|
|
390 |
|
|
391 |
|
|
392 |
|
|
393 |
//***********************************************************************************************************************************************************************************
|
|
394 |
|
|
395 |
|
|
396 |
/*
|
|
397 |
The MACHINE for the EDGE state.
|
|
398 |
*/
|
|
399 |
case 3:
|
|
400 |
|
| 300 |
401 |
switch(edge_State)
|
| 301 |
402 |
{
|
| 302 |
403 |
/*
|
| ... | ... | |
| 369 |
470 |
distance = get_distance();
|
| 370 |
471 |
delay_ms(14);
|
| 371 |
472 |
time+=14;
|
| 372 |
|
if(time>500)
|
|
473 |
if(time>50)
|
| 373 |
474 |
{
|
| 374 |
475 |
correctTurn();
|
| 375 |
476 |
time=0;
|
| ... | ... | |
| 401 |
502 |
case 5:
|
| 402 |
503 |
orb2_set_color(YELLOW);
|
| 403 |
504 |
packet_data=wl_basic_do_default(&data_length);
|
| 404 |
|
if(packet_data != 0 && data_length>=2 && packet_data[0]==CIRCLE_ACTION_GOTYOU && packet_data[1] == robotid)
|
|
505 |
if(packet_data != 0 && data_length==3 && packet_data[0]==CIRCLE_ACTION_GOTYOU && packet_data[1] == robotid)
|
| 405 |
506 |
{
|
| 406 |
507 |
bom_off();
|
| 407 |
508 |
direction = packet_data[2];
|
| ... | ... | |
| 410 |
511 |
}
|
| 411 |
512 |
break;
|
| 412 |
513 |
|
| 413 |
|
/* Blinks the direction it should turn. */
|
|
514 |
/* Wait for the center bot to send a DONE packet; then turn to face the right direction. */
|
| 414 |
515 |
case 6:
|
| 415 |
|
slowblink(direction);
|
| 416 |
|
edge_State = 7;
|
|
516 |
orb_set_color(GREEN);
|
|
517 |
packet_data=wl_basic_do_default(&data_length);
|
|
518 |
if(packet_data != 0 && data_length>=2 && packet_data[0]==CIRCLE_ACTION_DONE)
|
|
519 |
{
|
|
520 |
orb_set_color(WHITE);
|
|
521 |
orb2_set_color(CYAN);
|
|
522 |
edge_State = 7;
|
|
523 |
}
|
| 417 |
524 |
break;
|
| 418 |
525 |
|
|
526 |
/* Turn until we reach the right direction (DIRECTION) */
|
| 419 |
527 |
case 7:
|
|
528 |
left(170);
|
|
529 |
bom_refresh(BOM_ALL);
|
|
530 |
if(bom_get_max() == direction)
|
|
531 |
{
|
|
532 |
stop();
|
|
533 |
orb_set_color(YELLOW);
|
|
534 |
edge_State = 8;
|
|
535 |
}
|
|
536 |
break;
|
|
537 |
|
|
538 |
/* Wait for the command to move forward. */
|
|
539 |
case 8:
|
|
540 |
packet_data=wl_basic_do_default(&data_length);
|
|
541 |
if(packet_data != 0 && data_length>=3 && packet_data[0]==CIRCLE_ACTION_FORWARD)
|
|
542 |
{
|
|
543 |
orb_set_color(BLUE);
|
|
544 |
forward(200);
|
|
545 |
delay_ms(2000);
|
|
546 |
edge_State = END;
|
|
547 |
}
|
|
548 |
break;
|
|
549 |
|
|
550 |
/* Terminal. */
|
|
551 |
case 100:
|
|
552 |
stop();
|
| 420 |
553 |
orb_set_color(GREEN);
|
|
554 |
orb2_set_color(WHITE);
|
|
555 |
while(1);
|
| 421 |
556 |
break;
|
| 422 |
557 |
|
| 423 |
558 |
|
| ... | ... | |
| 432 |
567 |
|
| 433 |
568 |
|
| 434 |
569 |
|
| 435 |
|
|
| 436 |
|
//*****************************************************************************************************************************************************************************************
|
| 437 |
|
//*****************************************************************************************************************************************************************************************
|
| 438 |
|
//*****************************************************************************************************************************************************************************************
|
|
570 |
//***********************************************************************************************************************************************************************************
|
| 439 |
571 |
|
| 440 |
572 |
|
| 441 |
573 |
|
| 442 |
574 |
|
| 443 |
|
|
| 444 |
575 |
/*
|
| 445 |
|
The CENTER/BEACON/MASTER robot
|
|
576 |
The MACHINE for the BEACON state
|
| 446 |
577 |
*/
|
| 447 |
|
case 1:
|
|
578 |
case 4:
|
| 448 |
579 |
switch(beacon_State)
|
| 449 |
580 |
{
|
| 450 |
581 |
|
| ... | ... | |
| 544 |
675 |
}
|
| 545 |
676 |
}
|
| 546 |
677 |
|
|
678 |
bom_refresh(BOM_ALL);
|
| 547 |
679 |
direction = bom_get_max();
|
| 548 |
|
if(direction >= 16) direction -= 16;
|
|
680 |
direction += 8;
|
|
681 |
if(direction > 15) direction -= 16;
|
| 549 |
682 |
send3(CIRCLE_ACTION_GOTYOU, i, direction);
|
| 550 |
|
delay_ms(2000);
|
|
683 |
delay_ms(20);
|
| 551 |
684 |
}
|
| 552 |
685 |
}
|
| 553 |
686 |
beacon_State = 6;
|
| 554 |
687 |
break;
|
| 555 |
688 |
|
|
689 |
/* Sends a DONE packet to signify that it has read in all the robots' directions and sent packets.
|
|
690 |
Edge robots should now turn to face the right direction. */
|
|
691 |
case 6:
|
|
692 |
send2(CIRCLE_ACTION_DONE,robotid);
|
|
693 |
bom_on();
|
|
694 |
beacon_State = 7;
|
|
695 |
break;
|
|
696 |
|
|
697 |
/* Tells the robots to move forward and moves itself. */
|
|
698 |
case 7:
|
|
699 |
orb_set_color(YELLOW);
|
|
700 |
delay_ms(5000);
|
|
701 |
|
|
702 |
// format: type of ack, speed, time.
|
|
703 |
send3(CIRCLE_ACTION_FORWARD,200,2000);
|
|
704 |
orb_set_color(BLUE);
|
|
705 |
forward(200);
|
|
706 |
delay_ms(2000);
|
|
707 |
stop();
|
|
708 |
beacon_State = END;
|
|
709 |
break;
|
|
710 |
|
| 556 |
711 |
/* Terminal. */
|
| 557 |
|
case 6:
|
|
712 |
case 100:
|
|
713 |
stop();
|
| 558 |
714 |
orb_set_color(GREEN);
|
|
715 |
orb2_set_color(WHITE);
|
|
716 |
while(1);
|
| 559 |
717 |
break;
|
| 560 |
718 |
}
|
| 561 |
719 |
break;
|
|
720 |
|
|
721 |
//***********************************************************************************************************************************************************************************
|
| 562 |
722 |
|
| 563 |
|
}
|
| 564 |
|
}
|
|
723 |
} // ends the main switch
|
|
724 |
} // ends the main while loop
|
| 565 |
725 |
|
| 566 |
|
orb_set_color(RED);
|
| 567 |
|
while(1); /* END HERE */
|
|
726 |
orb_set_color(RED); // error, we should never break from the while loop!
|
| 568 |
727 |
|
| 569 |
|
//return 0;
|
|
728 |
while(1); /* END HERE, just in case something happened. This way we can see the red orb. */
|
| 570 |
729 |
}
|
|
730 |
|
|
731 |
|