Alarma Arduino
Alarma Arduino
Alarma Arduino
7 de noviembre de 2019
Índice general
Información general 2
i
Indice de Códigos
1. Botones . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 4
2. Demostración . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 6
3. Encoders . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 20
4. Seguidor de línea . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 22
5. Prueba sensor de línea . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 25
6. Control remoto . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . 28
ii
Códigos ejemplo para el robot
Pololu Zumo 32U4
1
Información general
El robot Zumo 32U4 es un robot completo y versátil controlado por un microcontrolador ATmega32U4 compatible
con Arduino. Cuando se ensambla, el robot con seguimiento de bajo perfil mide menos de 10 cm en cada lado, por lo
que es adecuado para competiciones de Mini-Sumo.
En el corazón del Zumo 32U4 hay un microcontrolador AVR ATmega32U4 integrado de Atmel, junto con dos
controladores de puente H que alimentan los motores del robot. El robot también presenta una variedad de sensores,
incluidos codificadores de cuadratura y sensores de inercia (acelerómetro y giroscopio) en la placa principal, junto con
sensores de reflectancia y proximidad en la matriz de sensores frontal. Los botones pulsadores integrados ofrecen una
interfaz conveniente para la entrada del usuario, y una pantalla LCD, un zumbador y LED indicadores le permiten
al robot proporcionar retroalimentación.
2
INDICE DE CÓDIGOS 3
Todos estos ejemplos los pueden consultar directamente en el IDE de Arduino, una vez descarguen e instalen la
biblioteca correspondiente.
Botones
1 /* This example demonstrates three different ways to
2 interface with a user pushbutton on the Zumo 32U4. */
3
4 #include <Wire.h>
5 #include <Zumo32U4.h>
6
4
INDICE DE CÓDIGOS 5
Demostración
1 /* This demo program shows many features of the Zumo 32U4.
2
3 It uses the buttons, LCD, and buzzer to provide a user interface.
4 It presents a menu to the user that lets the user select from
5 several different demos.
6
7 To use this demo program, you will need to have the LCD connected
8 to the Zumo 32U4. If you cannot see any text on the LCD,
9 try rotating the contrast potentiometer. */
10
11 #include <Wire.h>
12 #include <Zumo32U4.h>
13
14 Zumo32U4LCD lcd;
15 Zumo32U4Buzzer buzzer;
16 Zumo32U4ButtonA buttonA;
17 Zumo32U4ButtonB buttonB;
18 Zumo32U4ButtonC buttonC;
19 Zumo32U4LineSensors lineSensors;
20 Zumo32U4ProximitySensors proxSensors;
21 LSM303 compass;
22 L3G gyro;
23 Zumo32U4Motors motors;
24 Zumo32U4Encoders encoders;
25
26 char buttonMonitor();
27
28 class Menu
29 {
30 public:
31 struct Item
32 {
33 const char * name;
34 void (* action)();
35 };
36
37 Menu(Item * items, uint8_t itemCount)
38 {
39 this->items = items;
40 this->itemCount = itemCount;
41 lcdItemIndex = 0;
42 }
43
44 void lcdUpdate(uint8_t index)
45 {
46 lcd.clear();
INDICE DE CÓDIGOS 7
47 lcd.print(items[index].name);
48 lcd.gotoXY(0, 1);
49 lcd.print(F("\x7f" "A \xa5" "B C\x7e"));
50 }
51
52 void action(uint8_t index)
53 {
54 items[index].action();
55 }
56
57 // Prompts the user to choose one of the menu items,
58 // then runs it, then returns.
59 void select()
60 {
61 lcdUpdate(lcdItemIndex);
62
63 while (1)
64 {
65 switch (buttonMonitor())
66 {
67 case ’A’:
68 // The A button was pressed so decrement the index.
69 if (lcdItemIndex == 0)
70 {
71 lcdItemIndex = itemCount - 1;
72 }
73 else
74 {
75 lcdItemIndex--;
76 }
77 lcdUpdate(lcdItemIndex);
78 break;
79
80 case ’C’:
81 // The C button was pressed so increase the index.
82 if (lcdItemIndex >= itemCount - 1)
83 {
84 lcdItemIndex = 0;
85 }
86 else
87 {
88 lcdItemIndex++;
89 }
90 lcdUpdate(lcdItemIndex);
91 break;
92
93 case ’B’:
94 // The B button was pressed so run the item and return.
95 action(lcdItemIndex);
96 return;
97 }
98 }
99 }
100
101 private:
102 Item * items;
INDICE DE CÓDIGOS 8
159 0b11111,
160 0b00100,
161 0b01110,
162 0b11111,
163 0b00000,
164 };
165
166 // This character is two solid arrows pointing down.
167 const char reverseArrowsSolid[] PROGMEM = {
168 0b00000,
169 0b11111,
170 0b01110,
171 0b00100,
172 0b11111,
173 0b01110,
174 0b00100,
175 0b00000,
176 };
177
178 void loadCustomCharacters()
179 {
180 // The LCD supports up to 8 custom characters. Each character
181 // has a number between 0 and 7. We assign #7 to be the back
182 // arrow; other characters are loaded by individual demos as
183 // needed.
184
185 lcd.loadCustomCharacter(backArrow, 7);
186 }
187
188 // Assigns #0-6 to be bar graph characters.
189 void loadCustomCharactersBarGraph()
190 {
191 static const char levels[] PROGMEM = {
192 0, 0, 0, 0, 0, 0, 0, 63, 63, 63, 63, 63, 63, 63
193 };
194 lcd.loadCustomCharacter(levels + 0, 0); // 1 bar
195 lcd.loadCustomCharacter(levels + 1, 1); // 2 bars
196 lcd.loadCustomCharacter(levels + 2, 2); // 3 bars
197 lcd.loadCustomCharacter(levels + 3, 3); // 4 bars
198 lcd.loadCustomCharacter(levels + 4, 4); // 5 bars
199 lcd.loadCustomCharacter(levels + 5, 5); // 6 bars
200 lcd.loadCustomCharacter(levels + 6, 6); // 7 bars
201 }
202
203 // Assigns #0-4 to be arrow symbols.
204 void loadCustomCharactersMotorDirs()
205 {
206 lcd.loadCustomCharacter(forwardArrows, 0);
207 lcd.loadCustomCharacter(reverseArrows, 1);
208 lcd.loadCustomCharacter(forwardArrowsSolid, 2);
209 lcd.loadCustomCharacter(reverseArrowsSolid, 3);
210 }
211
212 // Clears the LCD and puts [back_arrow]B on the second line
213 // to indicate to the user that the B button goes back.
214 void displayBackArrow()
INDICE DE CÓDIGOS 10
215 {
216 lcd.clear();
217 lcd.gotoXY(0,1);
218 lcd.print(F("\7B"));
219 lcd.gotoXY(0,0);
220 }
221
222 // Blinks all three LEDs in sequence.
223 void ledDemo()
224 {
225 displayBackArrow();
226
227 uint8_t state = 3;
228 static uint16_t lastUpdateTime = millis() - 2000;
229 while (buttonMonitor() != ’B’)
230 {
231 if ((uint16_t)(millis() - lastUpdateTime) >= 500)
232 {
233 lastUpdateTime = millis();
234 state = state + 1;
235 if (state >= 4) { state = 0; }
236
237 switch (state)
238 {
239 case 0:
240 buzzer.play("c32");
241 lcd.gotoXY(0, 0);
242 lcd.print(F("Red "));
243 ledRed(1);
244 ledGreen(0);
245 ledYellow(0);
246 break;
247
248 case 1:
249 buzzer.play("e32");
250 lcd.gotoXY(0, 0);
251 lcd.print(F("Green"));
252 ledRed(0);
253 ledGreen(1);
254 ledYellow(0);
255 break;
256
257 case 2:
258 buzzer.play("g32");
259 lcd.gotoXY(0, 0);
260 lcd.print(F("Yellow"));
261 ledRed(0);
262 ledGreen(0);
263 ledYellow(1);
264 break;
265 }
266 }
267 }
268
269 ledRed(0);
270 ledYellow(0);
INDICE DE CÓDIGOS 11
271 ledGreen(0);
272 }
273
274 void printBar(uint8_t height)
275 {
276 if (height > 8) { height = 8; }
277 static const char barChars[] = {’ ’, 0, 1, 2, 3, 4, 5, 6, 255};
278 lcd.print(barChars[height]);
279 }
280
281 // Display line sensor readings. Holding button C turns off
282 // the IR emitters.
283 void lineSensorDemo()
284 {
285 loadCustomCharactersBarGraph();
286 displayBackArrow();
287 lcd.gotoXY(6, 1);
288 lcd.print(’C’);
289
290 uint16_t lineSensorValues[3];
291 char c;
292
293 while (buttonMonitor() != ’B’)
294 {
295 bool emittersOff = buttonC.isPressed();
296
297 if (emittersOff)
298 {
299 lineSensors.read(lineSensorValues, QTR_EMITTERS_OFF);
300 }
301 else
302 {
303 lineSensors.read(lineSensorValues, QTR_EMITTERS_ON);
304 }
305
306 lcd.gotoXY(1, 0);
307 for (uint8_t i = 0; i < 3; i++)
308 {
309 uint8_t barHeight = map(lineSensorValues[i], 0, 2000, 0, 8);
310 printBar(barHeight);
311 lcd.print(’ ’);
312 }
313
314 // Display an indicator of whether emitters are on or
315 // off.
316 lcd.gotoXY(7, 1);
317 if (emittersOff)
318 {
319 lcd.print(’\xa5’); // centered dot
320 }
321 else
322 {
323 lcd.print(’*’);
324 }
325 }
326 }
INDICE DE CÓDIGOS 12
327
328 // Display proximity sensor readings.
329 void proxSensorDemo()
330 {
331 loadCustomCharactersBarGraph();
332 displayBackArrow();
333
334 while (buttonMonitor() != ’B’)
335 {
336 bool proxLeftActive = proxSensors.readBasicLeft();
337 bool proxFrontActive = proxSensors.readBasicFront();
338 bool proxRightActive = proxSensors.readBasicRight();
339 proxSensors.read();
340
341 lcd.gotoXY(0, 0);
342 printBar(proxSensors.countsLeftWithLeftLeds());
343 printBar(proxSensors.countsLeftWithRightLeds());
344 lcd.print(’ ’);
345 printBar(proxSensors.countsFrontWithLeftLeds());
346 printBar(proxSensors.countsFrontWithRightLeds());
347 lcd.print(’ ’);
348 printBar(proxSensors.countsRightWithLeftLeds());
349 printBar(proxSensors.countsRightWithRightLeds());
350
351 // On the last 3 characters of the second line, display
352 // basic readings of the sensors taken without sending
353 // IR pulses.
354 lcd.gotoXY(5, 1);
355 printBar(proxLeftActive);
356 printBar(proxFrontActive);
357 printBar(proxRightActive);
358 }
359 }
360
361 // Starts I2C and initializes the inertial sensors.
362 void initInertialSensors()
363 {
364 Wire.begin();
365 compass.init();
366 compass.enableDefault();
367 gyro.init();
368 gyro.enableDefault();
369 }
370
371 // Given 3 readings for axes x, y, and z, prints the sign
372 // and axis of the largest reading unless it is below the
373 // given threshold.
374 void printLargestAxis(int16_t x, int16_t y, int16_t z, uint16_t threshold)
375 {
376 int16_t largest = x;
377 char axis = ’X’;
378
379 if (abs(y) > abs(largest))
380 {
381 largest = y;
382 axis = ’Y’;
INDICE DE CÓDIGOS 13
383 }
384 if (abs(z) > abs(largest))
385 {
386 largest = z;
387 axis = ’Z’;
388 }
389
390 if (abs(largest) < threshold)
391 {
392 lcd.print(" ");
393 }
394 else
395 {
396 bool positive = (largest > 0);
397 lcd.print(positive ? ’+’ : ’-’);
398 lcd.print(axis);
399 }
400 }
401
402 // Print the direction of the largest rotation rate measured
403 // by the gyro and the up direction based on the
404 // accelerometer’s measurement of gravitational acceleration
405 // (assuming gravity is the dominant force acting on the
406 // Zumo).
407 void inertialDemo()
408 {
409 displayBackArrow();
410
411 lcd.gotoXY(3, 0);
412 lcd.print(F("Rot"));
413 lcd.gotoXY(4, 1);
414 lcd.print(F("Up"));
415
416 while (buttonMonitor() != ’B’)
417 {
418 compass.read();
419 gyro.read();
420
421 lcd.gotoXY(6, 0);
422 printLargestAxis(gyro.g.x, gyro.g.y, gyro.g.z, 2000);
423 lcd.gotoXY(6, 1);
424 printLargestAxis(compass.a.x, compass.a.y, compass.a.z, 200);
425 }
426 }
427
428 // Provides an interface to test the motors. Holding button A or C
429 // causes the left or right motor to accelerate; releasing the
430 // button causes the motor to decelerate. Tapping the button while
431 // the motor is not running reverses the direction it runs.
432 //
433 // If the showEncoders argument is true, encoder counts are
434 // displayed on the first line of the LCD; otherwise, an
435 // instructional message is shown.
436 void motorDemoHelper(bool showEncoders)
437 {
438 loadCustomCharactersMotorDirs();
INDICE DE CÓDIGOS 14
439 lcd.clear();
440 lcd.gotoXY(1, 1);
441 lcd.print(F("A \7B C"));
442
443 int16_t leftSpeed = 0, rightSpeed = 0;
444 int8_t leftDir = 1, rightDir = 1;
445 uint16_t lastUpdateTime = millis() - 100;
446 uint8_t btnCountA = 0, btnCountC = 0, instructCount = 0;
447
448 int16_t encCountsLeft = 0, encCountsRight = 0;
449 char buf[4];
450
451 while (buttonMonitor() != ’B’)
452 {
453 encCountsLeft += encoders.getCountsAndResetLeft();
454 if (encCountsLeft < 0) { encCountsLeft += 1000; }
455 if (encCountsLeft > 999) { encCountsLeft -= 1000; }
456
457 encCountsRight += encoders.getCountsAndResetRight();
458 if (encCountsRight < 0) { encCountsRight += 1000; }
459 if (encCountsRight > 999) { encCountsRight -= 1000; }
460
461 // Update the LCD and motors every 50 ms.
462 if ((uint16_t)(millis() - lastUpdateTime) > 50)
463 {
464 lastUpdateTime = millis();
465
466 lcd.gotoXY(0, 0);
467 if (showEncoders)
468 {
469 sprintf(buf, " %03d", encCountsLeft);
470 lcd.print(buf);
471 lcd.gotoXY(5, 0);
472 sprintf(buf, " %03d", encCountsRight);
473 lcd.print(buf);
474 }
475 else
476 {
477 // Cycle the instructions every 2 seconds.
478 if (instructCount == 0)
479 {
480 lcd.print("Hold=run");
481 }
482 else if (instructCount == 40)
483 {
484 lcd.print("Tap=flip");
485 }
486 if (++instructCount == 80) { instructCount = 0; }
487 }
488
489 if (buttonA.isPressed())
490 {
491 if (btnCountA < 4)
492 {
493 btnCountA++;
494 }
INDICE DE CÓDIGOS 15
495 else
496 {
497 // Button has been held for more than 200 ms, so
498 // start running the motor.
499 leftSpeed += 15;
500 }
501 }
502 else
503 {
504 if (leftSpeed == 0 && btnCountA > 0 && btnCountA < 4)
505 {
506 // Motor isn’t running and button was pressed for
507 // 200 ms or less, so flip the motor direction.
508 leftDir = -leftDir;
509 }
510 btnCountA = 0;
511 leftSpeed -= 30;
512 }
513
514 if (buttonC.isPressed())
515 {
516 if (btnCountC < 4)
517 {
518 btnCountC++;
519 }
520 else
521 {
522 // Button has been held for more than 200 ms, so
523 // start running the motor.
524 rightSpeed += 15;
525 }
526 }
527 else
528 {
529 if (rightSpeed == 0 && btnCountC > 0 && btnCountC < 4)
530 {
531 // Motor isn’t running and button was pressed for
532 // 200 ms or less, so flip the motor direction.
533 rightDir = -rightDir;
534 }
535 btnCountC = 0;
536 rightSpeed -= 30;
537 }
538
539 leftSpeed = constrain(leftSpeed, 0, 400);
540 rightSpeed = constrain(rightSpeed, 0, 400);
541
542 motors.setSpeeds(leftSpeed * leftDir, rightSpeed * rightDir);
543
544 // Display arrows pointing the appropriate direction
545 // (solid if the motor is running, chevrons if not).
546 lcd.gotoXY(0, 1);
547 if (leftSpeed == 0)
548 {
549 lcd.print((leftDir > 0) ? ’\0’ : ’\1’);
550 }
INDICE DE CÓDIGOS 16
551 else
552 {
553 lcd.print((leftDir > 0) ? ’\2’ : ’\3’);
554 }
555 lcd.gotoXY(7, 1);
556 if (rightSpeed == 0)
557 {
558 lcd.print((rightDir > 0) ? ’\0’ : ’\1’);
559 }
560 else
561 {
562 lcd.print((rightDir > 0) ? ’\2’ : ’\3’);
563 }
564 }
565 }
566 motors.setSpeeds(0, 0);
567 }
568
569
570 // Motor demo with instructions.
571 void motorDemo()
572 {
573 motorDemoHelper(false);
574 }
575
576 // Motor demo with encoder counts.
577 void encoderDemo()
578 {
579 motorDemoHelper(true);
580 }
581
582 const char fugue[] PROGMEM =
583 "! T120O5L16agafaea dac+adaea fa<aa<bac#a dac#adaea f"
584 "O6dcd<b-d<ad<g d<f+d<gd<ad<b- d<dd<ed<f+d<g d<f+d<gd<ad"
585 "L8MS<b-d<b-d MLe-<ge-<g MSc<ac<a MLd<fd<f O5MSb-gb-g"
586 "ML>c#e>c#e MS afaf ML gc#gc# MS fdfd ML e<b-e<b-"
587 "O6L16ragafaea dac#adaea fa<aa<bac#a dac#adaea faeadaca"
588 "<b-acadg<b-g egdgcg<b-g <ag<b-gcf<af dfcf<b-f<af"
589 "<gf<af<b-e<ge c#e<b-e<ae<ge <fe<ge<ad<fd"
590 "O5e>ee>ef>df>d b->c#b->c#a>df>d e>ee>ef>df>d"
591 "e>d>c#>db>d>c#b >c#agaegfe fO6dc#dfdc#<b c#4";
592
593 const char fugueTitle[] PROGMEM =
594 " Fugue in D Minor - by J.S. Bach ";
595
596 // Play a song on the buzzer and display its title.
597 void musicDemo()
598 {
599 displayBackArrow();
600
601 uint8_t fugueTitlePos = 0;
602 uint16_t lastShiftTime = millis() - 2000;
603
604 while (buttonMonitor() != ’B’)
605 {
606 // Shift the song title to the left every 250 ms.
INDICE DE CÓDIGOS 17
719 // code:
720 bool brownout = MCUSR >> BORF & 1;
721 MCUSR = 0;
722
723 if (brownout)
724 {
725 // The board was reset by a brownout reset
726 // (VCC dropped below 4.3 V).
727 // Play a special sound and display a note to the user.
728
729 buzzer.playFromProgramSpace(beepBrownout);
730 lcd.clear();
731 lcd.print(F("Brownout"));
732 lcd.gotoXY(0, 1);
733 lcd.print(F(" reset! "));
734 delay(1000);
735 }
736 else
737 {
738 buzzer.playFromProgramSpace(beepWelcome);
739 }
740
741 lcd.clear();
742 lcd.print(F(" Zumo"));
743 lcd.gotoXY(2, 1);
744 lcd.print(F("32U4"));
745
746 delay(1000);
747
748 lcd.clear();
749 lcd.print(F("Demo"));
750 lcd.gotoXY(0, 1);
751 lcd.print(F("Program"));
752 delay(1000);
753
754 lcd.clear();
755 lcd.print(F("Use B to"));
756 lcd.gotoXY(0, 1);
757 lcd.print(F("select."));
758 delay(1000);
759
760 lcd.clear();
761 lcd.print(F("Press B"));
762 lcd.gotoXY(0, 1);
763 lcd.print(F("-try it!"));
764
765 while (buttonMonitor() != ’B’){}
766
767 buzzer.playFromProgramSpace(beepThankYou);
768 lcd.clear();
769 lcd.print(F(" Thank"));
770 lcd.gotoXY(0, 1);
771 lcd.print(F(" you!"));
772 delay(1000);
773 }
774
INDICE DE CÓDIGOS 20
775 // This function prompts the user to choose something from the
776 // main menu, runs their selection, and then returns.
777 void mainMenuSelect()
778 {
779 lcd.clear();
780 lcd.print(F(" Main"));
781 lcd.gotoXY(0, 1);
782 lcd.print(F(" Menu"));
783 delay(1000);
784 mainMenu.select();
785 }
786
787 void loop()
788 {
789 mainMenuSelect();
790 }
Código 2: Demostración
Encoders
1 /* This program shows how to read the encoders on the Zumo 32U4.
2 The encoders can tell you how far, and in which direction each
3 motor has turned.
4
5 You can press button A on the Zumo to drive both motors forward
6 at full speed. You can press button C to drive both motors
7 in reverse at full speed.
8
9 Encoder counts are printed to the LCD and to the serial monitor.
10
11 On the LCD, the top line shows the counts from the left encoder,
12 and the bottom line shows the counts from the right encoder.
13 Encoder errors should not happen, but if one does happen then the
14 buzzer will beep and an exclamation mark will appear temporarily
15 on the LCD.
16
17 In the serial monitor, the first and second numbers represent
18 counts from the left and right encoders, respectively. The third
19 and fourth numbers represent errors from the left and right
20 encoders, respectively. */
21
22 #include <Wire.h>
23 #include <Zumo32U4.h>
24
25 Zumo32U4Encoders encoders;
26 Zumo32U4LCD lcd;
27 Zumo32U4Buzzer buzzer;
28 Zumo32U4Motors motors;
29 Zumo32U4ButtonA buttonA;
30 Zumo32U4ButtonC buttonC;
31
32 const char encoderErrorLeft[] PROGMEM = "!<c2";
33 const char encoderErrorRight[] PROGMEM = "!<e2";
34
INDICE DE CÓDIGOS 21
35 char report[80];
36
37 void setup()
38 {
39
40 }
41
42 void loop()
43 {
44 static uint8_t lastDisplayTime;
45 static uint8_t displayErrorLeftCountdown = 0;
46 static uint8_t displayErrorRightCountdown = 0;
47
48 if ((uint8_t)(millis() - lastDisplayTime) >= 100)
49 {
50 lastDisplayTime = millis();
51
52 int16_t countsLeft = encoders.getCountsLeft();
53 int16_t countsRight = encoders.getCountsRight();
54
55 bool errorLeft = encoders.checkErrorLeft();
56 bool errorRight = encoders.checkErrorRight();
57
58 if(encoders.checkErrorLeft())
59 {
60 // An error occurred on the left encoder channel.
61 // Display it on the LCD for the next 10 iterations and
62 // also beep.
63 displayErrorLeftCountdown = 10;
64 buzzer.playFromProgramSpace(encoderErrorLeft);
65 }
66
67 if(encoders.checkErrorRight())
68 {
69 // An error occurred on the left encoder channel.
70 // Display it on the LCD for the next 10 iterations and
71 // also beep.
72 displayErrorRightCountdown = 10;
73 buzzer.playFromProgramSpace(encoderErrorRight);
74 }
75
76 // Update the LCD with encoder counts and error info.
77 lcd.clear();
78 lcd.print(countsLeft);
79 lcd.gotoXY(0, 1);
80 lcd.print(countsRight);
81
82 if (displayErrorLeftCountdown)
83 {
84 // Show an exclamation point on the first line to
85 // indicate an error from the left encoder.
86 lcd.gotoXY(7, 0);
87 lcd.print(’!’);
88 displayErrorLeftCountdown--;
89 }
90
INDICE DE CÓDIGOS 22
91 if (displayErrorRightCountdown)
92 {
93 // Show an exclamation point on the second line to
94 // indicate an error from the left encoder.
95 lcd.gotoXY(7, 1);
96 lcd.print(’!’);
97 displayErrorRightCountdown--;
98 }
99
100 // Send the information to the serial monitor also.
101 snprintf_P(report, sizeof(report),
102 PSTR(" %6d %6d %1d %1d"),
103 countsLeft, countsRight, errorLeft, errorRight);
104 Serial.println(report);
105 }
106
107 if (buttonA.isPressed())
108 {
109 motors.setSpeeds(400, 400);
110 }
111 else if (buttonC.isPressed())
112 {
113 motors.setSpeeds(-400, -400);
114 }
115 else
116 {
117 motors.setSpeeds(0, 0);
118 }
119 }
Código 3: Encoders
Seguidor de línea
1 /* This example uses the line sensors on the Zumo 32U4 to follow
2 a black line on a white background, using a PID-based algorithm.
3 It works decently on courses with smooth, 6" radius curves and
4 has been tested with Zumos using 75:1 HP motors. Modifications
5 might be required for it to work well on different courses or
6 with different motors.
7
8 This demo requires a Zumo 32U4 Front Sensor Array to be
9 connected, and jumpers on the front sensor array must be
10 installed in order to connect pin 4 to DN4 and pin 20 to DN2. */
11
12 #include <Wire.h>
13 #include <Zumo32U4.h>
14
15 // This is the maximum speed the motors will be allowed to turn.
16 // A maxSpeed of 400 lets the motors go at top speed. Decrease
17 // this value to impose a speed limit.
18 const uint16_t maxSpeed = 400;
19
20 Zumo32U4Buzzer buzzer;
21 Zumo32U4LineSensors lineSensors;
INDICE DE CÓDIGOS 23
22 Zumo32U4Motors motors;
23 Zumo32U4ButtonA buttonA;
24 Zumo32U4LCD lcd;
25
26 int16_t lastError = 0;
27
28 #define NUM_SENSORS 5
29 unsigned int lineSensorValues[NUM_SENSORS];
30
31 // Sets up special characters in the LCD so that we can display
32 // bar graphs.
33 void loadCustomCharacters()
34 {
35 static const char levels[] PROGMEM = {
36 0, 0, 0, 0, 0, 0, 0, 63, 63, 63, 63, 63, 63, 63
37 };
38 lcd.loadCustomCharacter(levels + 0, 0); // 1 bar
39 lcd.loadCustomCharacter(levels + 1, 1); // 2 bars
40 lcd.loadCustomCharacter(levels + 2, 2); // 3 bars
41 lcd.loadCustomCharacter(levels + 3, 3); // 4 bars
42 lcd.loadCustomCharacter(levels + 4, 4); // 5 bars
43 lcd.loadCustomCharacter(levels + 5, 5); // 6 bars
44 lcd.loadCustomCharacter(levels + 6, 6); // 7 bars
45 }
46
47 void printBar(uint8_t height)
48 {
49 if (height > 8) { height = 8; }
50 const char barChars[] = {’ ’, 0, 1, 2, 3, 4, 5, 6, 255};
51 lcd.print(barChars[height]);
52 }
53
54 void calibrateSensors()
55 {
56 lcd.clear();
57
58 // Wait 1 second and then begin automatic sensor calibration
59 // by rotating in place to sweep the sensors over the line
60 delay(1000);
61 for(uint16_t i = 0; i < 120; i++)
62 {
63 if (i > 30 && i <= 90)
64 {
65 motors.setSpeeds(-200, 200);
66 }
67 else
68 {
69 motors.setSpeeds(200, -200);
70 }
71
72 lineSensors.calibrate();
73 }
74 motors.setSpeeds(0, 0);
75 }
76
77 // Displays a bar graph of sensor readings on the LCD.
INDICE DE CÓDIGOS 24
134
135 // Our "error" is how far we are away from the center of the
136 // line, which corresponds to position 2000.
137 int16_t error = position - 2000;
138
139 // Get motor speed difference using proportional and derivative
140 // PID terms (the integral term is generally not very useful
141 // for line following). Here we are using a proportional
142 // constant of 1/4 and a derivative constant of 6, which should
143 // work decently for many Zumo motor choices. You probably
144 // want to use trial and error to tune these constants for your
145 // particular Zumo and line course.
146 int16_t speedDifference = error / 4 + 6 * (error - lastError);
147
148 lastError = error;
149
150 // Get individual motor speeds. The sign of speedDifference
151 // determines if the robot turns left or right.
152 int16_t leftSpeed = (int16_t)maxSpeed + speedDifference;
153 int16_t rightSpeed = (int16_t)maxSpeed - speedDifference;
154
155 // Constrain our motor speeds to be between 0 and maxSpeed.
156 // One motor will always be turning at maxSpeed, and the other
157 // will be at maxSpeed-|speedDifference| if that is positive,
158 // else it will be stationary. For some applications, you
159 // might want to allow the motor speed to go negative so that
160 // it can spin in reverse.
161 leftSpeed = constrain(leftSpeed, 0, (int16_t)maxSpeed);
162 rightSpeed = constrain(rightSpeed, 0, (int16_t)maxSpeed);
163
164 motors.setSpeeds(leftSpeed, rightSpeed);
165 }
Código 4: Seguidor de línea
19 In order for the second and forth sensors to work, jumpers on the
20 front sensor array must be installed in order to connect pin 4 to
21 DN4 and pin 20 to DN2. */
22
23 #include <Wire.h>
24 #include <Zumo32U4.h>
25
26 Zumo32U4LCD lcd;
27 Zumo32U4ButtonA buttonA;
28 Zumo32U4ButtonB buttonB;
29 Zumo32U4ButtonC buttonC;
30 Zumo32U4LineSensors lineSensors;
31 Zumo32U4ProximitySensors proxSensors;
32
33 #define NUM_SENSORS 5
34 uint16_t lineSensorValues[NUM_SENSORS];
35
36 bool useEmitters = true;
37
38 uint8_t selectedSensorIndex = 0;
39
40 void setup()
41 {
42 lineSensors.initFiveSensors();
43
44 loadCustomCharacters();
45 }
46
47 void loadCustomCharacters()
48 {
49 static const char levels[] PROGMEM = {
50 0, 0, 0, 0, 0, 0, 0, 63, 63, 63, 63, 63, 63, 63
51 };
52 lcd.loadCustomCharacter(levels + 0, 0); // 1 bar
53 lcd.loadCustomCharacter(levels + 1, 1); // 2 bars
54 lcd.loadCustomCharacter(levels + 2, 2); // 3 bars
55 lcd.loadCustomCharacter(levels + 3, 3); // 4 bars
56 lcd.loadCustomCharacter(levels + 4, 4); // 5 bars
57 lcd.loadCustomCharacter(levels + 5, 5); // 6 bars
58 lcd.loadCustomCharacter(levels + 6, 6); // 7 bars
59 }
60
61 void printBar(uint8_t height)
62 {
63 if (height > 8) { height = 8; }
64 const char barChars[] = {’ ’, 0, 1, 2, 3, 4, 5, 6, 255};
65 lcd.print(barChars[height]);
66 }
67
68 void printReadingsToLCD()
69 {
70 // On the first line of the LCD, display the bar graph.
71 lcd.gotoXY(0, 0);
72 for (uint8_t i = 0; i < 5; i++)
73 {
74 uint8_t barHeight = map(lineSensorValues[i], 0, 2000, 0, 8);
INDICE DE CÓDIGOS 27
75 printBar(barHeight);
76 }
77
78 // Print "E" if the emitters are on, "e" if they are off.
79 lcd.gotoXY(7, 0);
80 lcd.print(useEmitters ? ’E’ : ’e’);
81
82 // On the second line of the LCD, display one raw reading.
83 lcd.gotoXY(0, 1);
84 lcd.print(selectedSensorIndex);
85 lcd.print(F(": "));
86 lcd.print(lineSensorValues[selectedSensorIndex]);
87 lcd.print(F(" "));
88 }
89
90 // Prints a line with all the sensor readings to the serial
91 // monitor.
92 void printReadingsToSerial()
93 {
94 char buffer[80];
95 sprintf(buffer, " %4d %4d %4d %4d %4d %c\n",
96 lineSensorValues[0],
97 lineSensorValues[1],
98 lineSensorValues[2],
99 lineSensorValues[3],
100 lineSensorValues[4],
101 useEmitters ? ’E’ : ’e’
102 );
103 Serial.print(buffer);
104 }
105
106 void loop()
107 {
108 static uint16_t lastSampleTime = 0;
109
110 if ((uint16_t)(millis() - lastSampleTime) >= 100)
111 {
112 lastSampleTime = millis();
113
114 // Read the line sensors.
115 lineSensors.read(lineSensorValues, useEmitters ? QTR_EMITTERS_ON : QTR_EMITTERS_OFF);
116
117 // Send the results to the LCD and to the serial monitor.
118 printReadingsToLCD();
119 printReadingsToSerial();
120 }
121
122 // If button A is pressed, select the previous sensor.
123 if (buttonA.getSingleDebouncedPress())
124 {
125 selectedSensorIndex = (selectedSensorIndex + NUM_SENSORS - 1) % NUM_SENSORS;
126 }
127
128 // If button B is pressed, select the next sensor.
129 if (buttonB.getSingleDebouncedPress())
130 {
INDICE DE CÓDIGOS 28
Control remoto
1 /* This example shows how to use the receivers for the infrared
2 proximity sensors on the Zumo 32U4 to detect and decode commands
3 from an infrared remote. This code is designed to work with the
4 Mini IR Remote Control available from Pololu:
5
6 https://www.pololu.com/product/2777
7
8 For this code to work, jumpers on the front sensor array should
9 be installed in order to connect pin 4 to RGT and connect pin 20
10 to LFT.
11
12 The arrow buttons control the robot’s movement, while the number
13 buttons from 1 to 3 play different notes on the buzzer.
14
15 To change what actions are performed when a button press is
16 detected, you should change the processRemoteCommand and
17 stopCurrentCommand functions.
18
19 If you have a different remote that uses the NEC protocol with a
20 38 kHz, 940 nm infrared emitter, it should be possible to make it
21 work with this code. You can use this code to decode the
22 messages from your remote, and then you can edit the constants in
23 RemoteConstants.h to match what was transmitted from your
24 remote. */
25
26 #include <Wire.h>
27 #include <Zumo32U4.h>
28 #include "RemoteConstants.h"
29 #include "RemoteDecoder.h"
30
31 // This variable sets the amount of time (in milliseconds) that
32 // we wait before considering the current message from the remote
33 // to have expired. This type of remote typically sends a repeat
34 // command every 109 ms, so a timeout value of 115 was chosen.
35 // You can increase this timeout to 230 if you want to be more
36 // tolerant of errors that occur while you are holding down the
37 // button, but it will make the robot slower to respond when you
38 // release the button.
39 const uint16_t messageTimeoutMs = 115;
40
41 // This variable is true if the last message received from the
INDICE DE CÓDIGOS 29
98
99 // Check how long ago the current message was last verified.
100 // If it is longer than the timeout time, then the message has
101 // expired and we should stop executing it.
102 if (messageActive && (uint16_t)(millis() - lastMessageTimeMs) > messageTimeoutMs)
103 {
104 messageActive = false;
105 stopCurrentCommand();
106 }
107 }
108
109 void processRemoteEvents()
110 {
111 if (decoder.getAndResetMessageFlag())
112 {
113 // The remote decoder received a new message, so record what
114 // time it was received and process it.
115 lastMessageTimeMs = millis();
116 messageActive = true;
117 processRemoteMessage(decoder.getMessage());
118 }
119
120 if (decoder.getAndResetRepeatFlag())
121 {
122 // The remote decoder receiver a "repeat" command, which is
123 // sent about every 109 ms while the button is being held
124 // down. It contains no data. We record what time the
125 // repeat command was received so we can know that the
126 // current message is still active.
127 lastMessageTimeMs = millis();
128 }
129 }
130
131 void processRemoteMessage(const uint8_t * message)
132 {
133 // Print the raw message on the first line of the LCD, in hex.
134 // The first two bytes are usually an address, and the third
135 // byte is usually a command. The last byte is supposed to be
136 // the bitwise inverse of the third byte, and if that is the
137 // case, then we don’t print it.
138 lcd.clear();
139 char buffer[9];
140 if (message[2] + message[3] == 0xFF)
141 {
142 sprintf(buffer, " %02X %02X %02X ",
143 message[0], message[1], message[2]);
144 }
145 else
146 {
147 sprintf(buffer, " %02X %02X %02X %02X",
148 message[0], message[1], message[2], message[3]);
149 }
150 lcd.print(buffer);
151
152 // Go to the next line of the LCD.
153 lcd.gotoXY(0, 1);
INDICE DE CÓDIGOS 31
154
155 // Make sure the address matches what we expect.
156 if (message[0] != remoteAddressByte0 ||
157 message[1] != remoteAddressByte1)
158 {
159 lcd.print(F("bad addr"));
160 return;
161 }
162
163 // Make sure that the last byte is the logical inverse of the
164 // command byte.
165 if (message[2] + message[3] != 0xFF)
166 {
167 lcd.print(F("bad cmd"));
168 return;
169 }
170
171 stopCurrentCommand();
172 processRemoteCommand(message[2]);
173 }
174
175 // Start running the new command.
176 void processRemoteCommand(uint8_t command)
177 {
178 switch(command)
179 {
180 case remoteUp:
181 lcd.print(F("up"));
182 motors.setSpeeds(400, 400);
183 break;
184
185 case remoteDown:
186 lcd.print(F("down"));
187 motors.setSpeeds(-400, -400);
188 break;
189
190 case remoteLeft:
191 lcd.print(F("left"));
192 motors.setSpeeds(-250, 250);
193 break;
194
195 case remoteRight:
196 lcd.print(F("right"));
197 motors.setSpeeds(250, -250);
198 break;
199
200 case remoteStopMode:
201 lcd.print(F("stop"));
202 break;
203
204 case remoteEnterSave:
205 lcd.print(F("enter"));
206 break;
207
208 case remoteVolMinus:
209 lcd.print(F("vol-"));
INDICE DE CÓDIGOS 32
210 break;
211
212 case remoteVolPlus:
213 lcd.print(F("vol+"));
214 break;
215
216 case remotePlayPause:
217 lcd.print(F("play"));
218 break;
219
220 case remoteSetup:
221 lcd.print(F("setup"));
222 break;
223
224 case remoteBack:
225 lcd.print(F("back"));
226 break;
227
228 case remote0:
229 lcd.print(F("0"));
230 break;
231
232 case remote1:
233 lcd.print(F("1"));
234 buzzer.playNote(NOTE_C(4), 200, 15);
235 break;
236
237 case remote2:
238 lcd.print(F("2"));
239 buzzer.playNote(NOTE_D(4), 200, 15);
240 break;
241
242 case remote3:
243 lcd.print(F("3"));
244 buzzer.playNote(NOTE_E(4), 200, 15);
245 break;
246
247 case remote4:
248 lcd.print(F("4"));
249 break;
250
251 case remote5:
252 lcd.print(F("5"));
253 break;
254
255 case remote6:
256 lcd.print(F("6"));
257 break;
258
259 case remote7:
260 lcd.print(F("7"));
261 break;
262
263 case remote8:
264 lcd.print(F("8"));
265 break;
INDICE DE CÓDIGOS 33
266
267 case remote9:
268 lcd.print(F("9"));
269 break;
270 }
271 }
272
273 // Stops the current remote control command. This is called when
274 // a new command is received or if the current command has
275 // expired.
276 void stopCurrentCommand()
277 {
278 motors.setSpeeds(0, 0);
279 buzzer.stopPlaying();
280 }
Código 6: Control remoto