Difference between revisions of "Otto - riadiaci program v.4"
m |
m |
||
Line 146: | Line 146: | ||
#define PIN_SERVO_LAVA_PATA 5 | #define PIN_SERVO_LAVA_PATA 5 | ||
#define PIN_SERVO_PRAVA_PATA 3 | #define PIN_SERVO_PRAVA_PATA 3 | ||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
− | |||
// tu su serva cislovane 1-6 | // tu su serva cislovane 1-6 |
Revision as of 09:40, 12 August 2018
Program umožňuje priame riadenie robota (aj cez BlueTooth). Teraz už funguje aj na pinoch 2,4 a môže sa naraz programovať aj komunikovať.
Na komunikáciu s robotom môžete použiť napr. program Putty: putty.exe.
Pripojenie na vývody Arduina:
signál | pin |
---|---|
ľavá ruka | 10 |
pravá ruka | 11 |
ľavá noha | 9 |
pravá noha | 6 |
ľavá päta | 5 |
pravá päta | 3 |
TXD BlueTooth | 2 |
RXD BlueTooth | 4 |
TRIG Ultrazvuk | 7 |
ECHO Ultrazvuk | 8 |
Sirena | 12 |
Číslovanie serva v choreografii:
servo | číslo serva v choreografii |
---|---|
ľavá ruka | 5 |
pravá ruka | 6 |
ľavá noha | 4 |
pravá noha | 3 |
ľavá päta | 2 |
pravá päta | 1 |
klaves | servo/funkcia |
---|---|
a/q | ľavá ruka |
;/p | pravá ruka |
z/x | ľavá noha |
,/. | pravá noha |
d/c | ľavá päta |
k/m | pravá päta |
1/9 | zníž/zvýš rýchlosť pohybu |
H | kalibrovať strednú polohu servomotorov
|
J | kalibrovať limity pre všetky stupne voľnosti (len pre priame riadenie) |
G | zobrazenie celej kalibrácie |
E | celú kalibráciu je možné zapísať do trvalej pamäte EEPROM (používať opatrne! - dá sa prepísať najviac 100000-krát), po zapnutí sa automaticky načíta, treba potvrdiť veľkým Y |
minus | zvukový pozdrav |
R | ruky hore-dole |
@ | načítanie choreografie, pozri príklady a formát |
? | zobrazí načítanú choreografiu (kontrola po @) |
t | zatancuje načítanú choreografiu |
U | testuje ultrazvuk |
S | zobrazí aktuálnu polohu servomotorov (vhodné pri ladení choreografie) |
medzera | reset všetkých motorov do strednej polohy |
3,...,6 | zmiešaný pohyb (treba nastaviť vo funkciách kombinacia1() - kombinacia4()) |
v,b,n,j,h,g,f,s,l,o,i,u,y,r,e,w | zvukové efekty 1-16 |
TAB,*,/,+ | zahrá melódiu 1-4 |
W | zapísať choreografiu do EEPROM (opatrne) |
C | načítať choreografiu z EEPROM |
X | formátovať EEPROM na zápis choreografií (opatrne) |
V | vypni/zapni režim nudy |
A | automatický štart choreografie po zapnutí |
Pozrite si (a skopírujte si) príklady choreografií: Otto - príklady choreografií
Download: otto4.ino
1 #include <Servo.h>
2 #include <EEPROM.h>
3 #include <avr/pgmspace.h>
4
5 #define ECHO_BT_TO_USB 1
6
7 #define US_TRIG 7
8 #define US_ECHO 8
9
10 #define BT_RX 2
11 #define BT_TX 4
12
13 #define SIRENA 12
14
15 //maximalna dlzka choreografie
16 #define CHOREO_LEN 200
17
18 #define CAS_OTTO_SA_ZACNE_NUDIT 9000
19
20 // cisla pinov, kde su zapojene servo motory
21 #define PIN_SERVO_LAVA_RUKA 10
22 #define PIN_SERVO_PRAVA_RUKA 11
23 #define PIN_SERVO_LAVA_NOHA 9
24 #define PIN_SERVO_PRAVA_NOHA 6
25 #define PIN_SERVO_LAVA_PATA 5
26 #define PIN_SERVO_PRAVA_PATA 3
27
28 // tu su serva cislovane 1-6
29 #define SERVO_LAVA_RUKA 5
30 #define SERVO_PRAVA_RUKA 6
31 #define SERVO_LAVA_NOHA 4
32 #define SERVO_PRAVA_NOHA 3
33 #define SERVO_LAVA_PATA 2
34 #define SERVO_PRAVA_PATA 1
35
36 // ak su niektore serva naopak, je tu jednotka
37 uint8_t servo_invertovane[6] = {0, 0, 0, 0, 0, 0};
38
39 // znaky, ktorymi sa ovladaju jednotlive stupne volnosti
40 char znaky_zmien[] = {'a', 'q', ';', 'p', 'z', 'x', ',', '.', 'd', 'c', 'k', 'm' };
41 // co robia jednotlive znaky (znamienko urcuje smer)
42 int8_t zmeny[] = {-SERVO_LAVA_RUKA, SERVO_LAVA_RUKA,
43 SERVO_PRAVA_RUKA, -SERVO_PRAVA_RUKA,
44 -SERVO_LAVA_NOHA, SERVO_LAVA_NOHA,
45 -SERVO_PRAVA_NOHA, SERVO_PRAVA_NOHA,
46 SERVO_LAVA_PATA, -SERVO_LAVA_PATA,
47 -SERVO_PRAVA_PATA, SERVO_PRAVA_PATA
48 };
49
50 // sem si mozno ulozit svoju kalibraciu
51 uint8_t prednastavena_kalibracia[] = { 90, 90, 90, 90, 90, 90 };
52
53 uint8_t dolny_limit[] = {0, 0, 0, 0, 0, 0, 0, 0};
54 uint8_t horny_limit[] = {180, 180, 180, 180, 180, 180};
55
56 Servo s[6];
57
58 uint16_t ch_time[CHOREO_LEN];
59 uint8_t ch_servo[CHOREO_LEN];
60 uint8_t ch_val[CHOREO_LEN];
61 int ch_len;
62 uint8_t kalib[6];
63 int stav[6];
64 int krok;
65 uint8_t spomalenie;
66 uint8_t auto_start;
67
68 static volatile int16_t distance;
69 static uint32_t cas_ked_naposledy_stlacil;
70 static uint8_t vypni_nudu;
71
72 void setup() {
73 Serial.begin(9600);
74 init_tone2();
75 init_serial(57600);
76 init_ultrasonic();
77
78 randomSeed(analogRead(1));
79 s[0].attach(PIN_SERVO_PRAVA_PATA);
80 s[1].attach(PIN_SERVO_LAVA_PATA);
81 s[2].attach(PIN_SERVO_PRAVA_NOHA);
82 s[3].attach(PIN_SERVO_LAVA_NOHA);
83 s[4].attach(PIN_SERVO_LAVA_RUKA);
84 s[5].attach(PIN_SERVO_PRAVA_RUKA);
85 precitaj_kalibraciu_z_EEPROM();
86 for (int i = 0; i < 6; i++)
87 {
88 kalib[i] = prednastavena_kalibracia[i];
89 stav[i] = kalib[i];
90 s[i].write(stav[i]);
91 }
92 ch_len = 0;
93 krok = 7;
94 vypni_nudu = 0;
95 spomalenie = 6;
96 ahoj();
97 ruky();
98 delay(100);
99 serial_println_flash(PSTR("\r\n Otto DTDT"));
100 if (auto_start > 0)
101 {
102 delay(7000);
103 while (serial_available()) serial_read();
104 while (Serial.available()) Serial.read();
105 precitaj_choreografiu_z_EEPROM(auto_start);
106 zatancuj_choreografiu(ch_time, ch_servo, ch_val, ch_len);
107 }
108 cas_ked_naposledy_stlacil = millis();
109 }
110
111 void loop() {
112 char z = -1;
113 if (serial_available()) z = serial_read();
114 #ifdef ECHO_BT_TO_USB
115 if (Serial.available()) z = Serial.read();
116 #endif
117
118 if (z != -1)
119 {
120 cas_ked_naposledy_stlacil = millis();
121 if (pohyb_znakom(z)) return;
122 else if (pohyb_kombinacia(z)) return;
123 else if (vydaj_zvukovy_efekt(z)) return;
124 else if (ma_zahrat_melodiu(z)) return;
125 else if (z == '@') nacitaj_choreografiu();
126 else if (z == '?') vypis_choreografiu();
127 else if (z == 't') zatancuj_choreografiu(ch_time, ch_servo, ch_val, ch_len);
128 else if (z == '-') ahoj();
129 else if (z == ' ') reset();
130 else if (z == 'H') kalibruj();
131 else if (z == 'J') nastav_limity();
132 else if (z == 'G') vypis_kalibraciu();
133 else if (z == 'L') nacitaj_kalibraciu();
134 else if (z == 'E') zapis_kalibraciu_do_EEPROM();
135 else if (z == 'R') ruky();
136 else if (z == '9') zvys_krok();
137 else if (z == '1') zniz_krok();
138 else if (z == '8') zvys_spomalenie();
139 else if (z == '7') zniz_spomalenie();
140 else if (z == 'U') test_ultrazvuk();
141 else if (z == 'S') zobraz_stav();
142 else if (z == 'W') skus_zapisat_choreografiu_do_EEPROM();
143 else if (z == 'X') skus_naformatovat_EEPROM_choreografie();
144 else if (z == 'C') skus_nacitat_choreografiu_z_EEPROM();
145 else if (z == 'A') nastav_automaticky_start();
146 else if (z == 'V') prepni_nudu();
147 }
148 int16_t d = measure_distance();
149 if (d < 10) menu_ultrasonic_request();
150
151 skus_ci_sa_nenudi();
152 }
153
154 void nastav_automaticky_start()
155 {
156 serial_print_flash(PSTR("Automaticky start [1,2,3, 0=vypni]:"));
157 char z;
158 do { z = read_char(); } while ((z < '0') || (z > '3'));
159 if (z == '0') EEPROM.write(1, '~');
160 else EEPROM.write(1, z);
161 serial_println_char(z);
162 }
163
164 void prepni_nudu()
165 {
166 vypni_nudu ^= 1;
167 serial_print_flash(PSTR("ticho:"));
168 serial_println_num(vypni_nudu);
169 }
170
171 void skus_ci_sa_nenudi()
172 {
173 if ((millis() - cas_ked_naposledy_stlacil > CAS_OTTO_SA_ZACNE_NUDIT) && !vypni_nudu)
174 {
175 uint8_t rnd = random(21);
176 switch (rnd)
177 {
178 case 0: zatancuj_choreografiu(ch_time, ch_servo, ch_val, ch_len); break;
179 case 1: zahraj_melodiu(1); break;
180 case 2: zahraj_melodiu(2); break;
181 case 3: zahraj_melodiu(3); break;
182 case 4: zahraj_melodiu(4); break;
183 case 5: for (int i = 0; i < 20; i++)
184 {
185 rnd = random(16) + 1;
186 zvukovy_efekt(rnd);
187 }
188 break;
189 default: zvukovy_efekt(rnd - 5); break;
190 }
191 cas_ked_naposledy_stlacil = millis();
192 }
193 }
194
195 const uint8_t klavesy_efektov[] PROGMEM = {'v', 'b', 'n', 'j', 'h', 'g', 'f', 's', 'l', 'o', 'i', 'u', 'y', 'r', 'e', 'w'};
196 #define POCET_KLAVES_EFEKTOV 16
197
198 uint8_t vydaj_zvukovy_efekt(char z)
199 {
200 for (int i = 0; i < POCET_KLAVES_EFEKTOV; i++)
201 if (z == pgm_read_byte(klavesy_efektov + i))
202 {
203 zvukovy_efekt(i + 1);
204 return 1;
205 }
206 return 0;
207 }
208
209 uint8_t ma_zahrat_melodiu(char z)
210 {
211 if (z == 9) zahraj_melodiu(1);
212 else if (z == '*') zahraj_melodiu(2);
213 else if (z == '/') zahraj_melodiu(3);
214 else if (z == '+') zahraj_melodiu(4);
215 else if (z == 27) zastav_melodiu();
216 }
217
218 void efekt1()
219 {
220 uint16_t fre = 100;
221 for (int i = 0; i < 200; i++)
222 {
223 tone2(fre, 2);
224 fre += 10;
225 delay(2);
226 }
227 }
228
229 void efekt2()
230 {
231 uint16_t fre = 2060;
232 for (int i = 0; i < 200; i++)
233 {
234 tone2(fre, 2);
235 fre -= 10;
236 delay(2);
237 }
238 }
239
240 void efekt3()
241 {
242 uint16_t fre;
243 for (int i = 0; i < 200; i++)
244 {
245 fre = random(3000) + 20;
246 tone2(fre, 2);
247 delay(2);
248 }
249 }
250
251 void efekt4()
252 {
253 uint16_t fre = 100;
254 for (int i = 0; i < 200; i++)
255 {
256 (i & 1) ? tone2(fre, 2) : tone2(2100 - fre, 2);
257 fre += 10;
258 delay(2);
259 }
260 }
261
262 void efekt5()
263 {
264 uint16_t fre = 100;
265 for (int i = 0; i < 100; i++)
266 {
267 (i & 1) ? tone2(fre, 4) : tone2(2100 - fre, 4);
268 fre += 20;
269 delay(4);
270 }
271 }
272
273 void efekt6()
274 {
275 uint16_t d = 12;
276 for (int i = 0; i < 20; i++)
277 {
278 tone2(1760, 10);
279 delay(d);
280 d += 3;
281 }
282 }
283
284 void efekt7()
285 {
286 for (int i = 0; i < 40; i++)
287 {
288 if (i & 1) tone2(1760, 10);
289 delay(10);
290 }
291 }
292
293 void efekt8()
294 {
295 uint16_t d = 72;
296 for (int i = 0; i < 20; i++)
297 {
298 tone2(1760, 10);
299 delay(d);
300 d -= 3;
301 }
302 }
303
304 void efekt9()
305 {
306 float fre = 3500;
307 while (fre > 30)
308 {
309 tone2((uint16_t)fre, 2);
310 fre *= 0.97;
311 delay(2);
312 }
313 }
314
315 void efekt10()
316 {
317 float fre = 30;
318 while (fre < 3000)
319 {
320 tone2((uint16_t)fre, 2);
321 fre *= 1.03;
322 delay(2);
323 }
324 }
325
326 void efekt11()
327 {
328 uint16_t fre = 3500;
329 uint16_t d = 42;
330 for (int i = 0; i < 20; i++)
331 {
332 tone2(fre, d);
333 fre -= 165;
334 delay(d);
335 d -= 2;
336 }
337 }
338
339 void efekt12()
340 {
341 float fre = 110;
342 uint8_t d = 42;
343 for (int i = 0; i < 20; i++)
344 {
345 tone2(fre, d);
346 fre += 165;
347 delay(d);
348 d -= 2;
349 }
350 }
351
352 void efekt13()
353 {
354 uint16_t fre = 3400;
355 uint8_t d = 200;
356 uint8_t delta = 1;
357 for (int i = 0; i < 20; i++)
358 {
359 tone2(fre, d);
360 fre -= 165;
361 delay(d);
362 d -= delta;
363 delta++;
364 }
365 tone2(110, 1000);
366 delay(1000);
367 }
368
369 void efekt14()
370 {
371 uint16_t fre = 880;
372 int16_t d = 20;
373 for (int i = 0; i < 20; i++)
374 {
375 tone2(fre, d);
376 delay(d);
377 fre += random(50) - 25;
378 d += random(10) - 5;
379 if (d < 0) d = 1;
380 }
381 }
382
383 void efekt15()
384 {
385 uint16_t fre = 440;
386 int16_t d = 20;
387 for (int i = 0; i < 20; i++)
388 {
389 tone2(fre, d);
390 delay(d);
391 fre += random(25) - 12;
392 d += random(10) - 5;
393 if (d < 0) d = 1;
394 }
395 }
396
397 void efekt16()
398 {
399 uint16_t fre = 1760;
400 int16_t d = 20;
401 for (int i = 0; i < 20; i++)
402 {
403 tone2(fre, d);
404 delay(d);
405 fre += random(100) - 50;
406 d += random(10) - 5;
407 if (d < 0) d = 1;
408 }
409 }
410
411 void zvukovy_efekt(uint8_t cislo)
412 {
413 switch (cislo) {
414 case 1: efekt1(); break;
415 case 2: efekt2(); break;
416 case 3: efekt3(); break;
417 case 4: efekt4(); break;
418 case 5: efekt5(); break;
419 case 6: efekt6(); break;
420 case 7: efekt7(); break;
421 case 8: efekt8(); break;
422 case 9: efekt9(); break;
423 case 10: efekt10(); break;
424 case 11: efekt11(); break;
425 case 12: efekt12(); break;
426 case 13: efekt13(); break;
427 case 14: efekt14(); break;
428 case 15: efekt15(); break;
429 case 16: efekt16(); break;
430 }
431 }
432
433 void test_ultrazvuk()
434 {
435 int i = 0;
436 while ((serial_available() == 0) && (Serial.available() == 0))
437 {
438 serial_println_num(measure_distance());
439 delay(100);
440 }
441 serial_read();
442 }
443
444 void menu_ultrasonic_request()
445 {
446 uint32_t tm = millis();
447 int d = measure_distance();
448 int count = 0;
449 int count2 = 0;
450 while ((millis() - tm < 1500) && ((d < 15) || (count2 < 5)) && (count < 10))
451 {
452 delay(10);
453 d = measure_distance();
454 if (d == 10000) count++;
455 else count = 0;
456 if (d >= 15) count2++;
457 else count2 = 0;
458 if (serial_available() || Serial.available()) return;
459 }
460 if (millis() - tm >= 1500)
461 {
462 ultrasonic_menu();
463 cas_ked_naposledy_stlacil = millis();
464 }
465 }
466
467 void ultrasonic_menu()
468 {
469 int selection = 0;
470 tone2( 880, 200);
471
472 do {
473 int count = 0;
474 do {
475 int32_t d = measure_distance();
476 if (d == 10000) continue;
477 if (d >= 20) count++;
478 else count = 0;
479 delay(10);
480 } while (!serial_available() && !Serial.available() && (count < 20));
481
482 tone2( 440, 200);
483 uint32_t tm = millis();
484 while ((measure_distance() > 15) && (millis() - tm < 1500) && !serial_available() && !Serial.available()) delay(10);
485 if (millis() - tm >= 1500)
486 {
487 tone2( 2000, 50);
488 menu_command(selection);
489 return;
490 }
491 selection++;
492 for (int i = 0; i < selection; i++)
493 {
494 tone2( 1261, 50);
495 delay(250);
496 }
497 } while (!serial_available() && !Serial.available());
498 while (serial_available()) serial_read();
499 while (Serial.available()) Serial.read();
500 }
501
502 void menu_command(int cmd)
503 {
504 if (cmd == 1) vpred();
505 if (cmd == 2) {
506 precitaj_choreografiu_z_EEPROM(1);
507 zatancuj_choreografiu(ch_time, ch_servo, ch_val, ch_len);
508 }
509 if (cmd == 3) {
510 precitaj_choreografiu_z_EEPROM(2);
511 zatancuj_choreografiu(ch_time, ch_servo, ch_val, ch_len);
512 }
513 if (cmd == 4) {
514 precitaj_choreografiu_z_EEPROM(3);
515 zatancuj_choreografiu(ch_time, ch_servo, ch_val, ch_len);
516 }
517 if (cmd == 5) zahraj_melodiu(1);
518 if (cmd == 6) melodia_jedna_druhej();
519 if (cmd == 7) ahoj();
520 if (cmd == 9) zahraj_melodiu(2);
521 if (cmd == 9) zahraj_melodiu(3);
522 if (cmd == 10) zahraj_melodiu(4);
523 }
524
525 void melodia_jedna_druhej()
526 {
527 for (int i = 0; i < 2; i++)
528 {
529 tone2(262, 200);
530 delay(200);
531 tone2(330, 200);
532 delay(200);
533
534 tone2(262, 200);
535 delay(200);
536 tone2(330, 200);
537 delay(200);
538
539 tone2(392, 400);
540 delay(400);
541
542 tone2(392, 400);
543 delay(400);
544 }
545 }
546
547 // chodza pre vacsieho dreveneho robota
548 uint16_t chor_time[] = {500, 100, 1, 1, 100, 1, 1, 1, 100, 1, 1, 1, 100, 1, 100, 1, 1, 0};
549 uint8_t chor_servo[] = {11, 1, 2, 6, 4, 3, 6, 5, 1, 2, 6, 5, 3, 4, 1, 2, 9, 0};
550 uint8_t chor_val[] = {1, 48, 69, 180, 104, 104, 90, 0, 111, 146, 0, 90, 62, 69, 48, 69, 2, 0};
551 uint8_t chor_len = 18;
552
553 void vpred()
554 {
555 while ((measure_distance() > 30) && !serial_available() && !Serial.available())
556 zatancuj_choreografiu(chor_time, chor_servo, chor_val, chor_len);
557 pipni();
558 reset();
559 }
560
561 void skus_zapisat_choreografiu_do_EEPROM()
562 {
563 serial_print_flash(PSTR("Cislo? [1-3]: "));
564 char odpoved = read_char();
565 if ((odpoved < '1') || (odpoved > '3')) return;
566 serial_println_char(odpoved);
567 uint8_t cislo = odpoved - '0';
568
569 serial_print_flash(PSTR("Zapisat choreografiu do EEPROM c."));
570 serial_print_char(odpoved);
571 serial_print_flash(PSTR("? [Y/n]: "));
572 odpoved = read_char();
573 serial_println_char(odpoved);
574 if (odpoved == 'Y')
575 zapis_choreografiu_do_EEPROM(cislo);
576 }
577
578 void skus_nacitat_choreografiu_z_EEPROM()
579 {
580 serial_print_flash(PSTR("Cislo? [1-3]: "));
581 char odpoved = read_char();
582 if ((odpoved < '1') || (odpoved > '3')) return;
583 serial_println_char(odpoved);
584 uint8_t cislo = odpoved - '0';
585
586 serial_print_flash(PSTR("Precitat choreografiu z EEPROM c."));
587 serial_print_char(odpoved);
588 serial_print_flash(PSTR("? [Y/n]: "));
589 odpoved = read_char();
590 serial_println_char(odpoved);
591 if (odpoved == 'Y')
592 precitaj_choreografiu_z_EEPROM(cislo);
593 }
594
595 void skus_naformatovat_EEPROM_choreografie()
596 {
597 serial_print_flash(PSTR("Formatovat EEPROM choreografii? [Y/n]:"));
598 char odpoved = read_char();
599 serial_println_char(odpoved);
600 if (odpoved == 'Y')
601 naformatuj_EEPROM_choreografie();
602 }
603
604 //EEPROM MAP:
605 // 0: slot number where choreography 3 starts (B3. Real address = B3 x 4)
606 // 1: marker '~' indicates calibration is already stored in EEPROM and will be loaded on startup
607 // '1', '2', '3' indicate the same, but choreography 1,2, or 3 is automatically launched on startup
608 // 2-8: servo calibration (central points to be used instead of default 90)
609 // 9-14: lower limit for direct control for all 6 servos
610 // 15-20: upper limit for direct control for all 6 servos
611 // 21: number of steps in choreography 1 (L1) 0=choreography not in memory
612 // 22: number of steps in choreography 2 (L2) 0=not in memory
613 // 23: number of steps in choreography 3 (L3) 0=not in memory
614 // 24..(L1 x 4 + 23) choreography1 tuplets (uint16,uint8,uint8) x L1
615 // (1024 - L2 x 4)..1023 choreography2 same as above
616 // B3 x 4..(B3 x 4 + L3 x 4 - 1) choreography 3 same as above
617 void zapis_choreografiu_do_EEPROM(int slot)
618 {
619 uint8_t b3 = EEPROM.read(0);
620 uint8_t len1 = EEPROM.read(21);
621 uint8_t len2 = EEPROM.read(22);
622 uint8_t len3 = EEPROM.read(23);
623 uint16_t wp = 65535;
624
625 if ((len1 > CHOREO_LEN) || (len2 > CHOREO_LEN) || (len3 > CHOREO_LEN) || (b3 > 250 - len3) || ((len1 > b3) && (b3 != 0)) || (len3 + b3 > 250 - len2) || (len1 + len2 > 250))
626 b3 = len1 = len2 = len3 = 0;
627
628 if (slot == 1)
629 {
630 if (((ch_len < b3) || (len3 == 0)) && (ch_len + len2 + len3 <= 250))
631 {
632 EEPROM.write(21, ch_len);
633 wp = 24;
634 }
635 }
636 else if (slot == 2)
637 {
638 if ((250 - b3 - len3 > ch_len) && (ch_len + len1 + len3 <= 250))
639 {
640 EEPROM.write(22, ch_len);
641 wp = 1000 - ch_len * 4;
642 }
643 }
644 else if (slot == 3)
645 {
646 if (ch_len + len1 + len2 <= 250)
647 {
648 EEPROM.write(23, ch_len);
649 EEPROM.write(0, (len1 - len2) / 2 + 125);
650 wp = 4 * ((len1 - len2) / 2 + 125);
651 }
652 }
653
654 if (wp == 65535)
655 serial_println_flash(PSTR("not enough space"));
656 else
657 {
658 for (int i = 0; i < ch_len; i++)
659 {
660 EEPROM.write(wp + 4 * i, ch_time[i] & 255);
661 EEPROM.write(wp + 1 + 4 * i, ch_time[i] >> 8);
662 EEPROM.write(wp + 2 + 4 * i, ch_servo[i]);
663 EEPROM.write(wp + 3 + 4 * i, ch_val[i]);
664 }
665 serial_println_flash(PSTR("ok"));
666 }
667 }
668
669 void precitaj_choreografiu_z_EEPROM(uint8_t slot)
670 {
671 uint8_t b3 = EEPROM.read(0);
672 uint8_t len1 = EEPROM.read(21);
673 uint8_t len2 = EEPROM.read(22);
674 uint8_t len3 = EEPROM.read(23);
675 uint16_t rp = 65535;
676 if ((len1 > CHOREO_LEN) || (len2 > CHOREO_LEN) || (len3 > CHOREO_LEN) || (b3 > 250 - len3) || ((len1 > b3) && (b3 != 0)) || (len3 + b3 > 250 - len2) || (len1 + len2 > 250))
677 b3 = len1 = len2 = len3 = 0;
678
679 if (slot == 1)
680 {
681 if (len1 > 0)
682 {
683 rp = 24;
684 ch_len = len1;
685 }
686 }
687 else if (slot == 2)
688 {
689 if (len2 > 0)
690 {
691 ch_len = len2;
692 rp = 1000 - ch_len * 4;
693 }
694 }
695 else if (slot == 3)
696 {
697 if (len3 > 0)
698 {
699 rp = b3 * 4;
700 ch_len = len3;
701 }
702 }
703
704 if (rp == 65535)
705 serial_println_flash(PSTR("couldn't"));
706 else
707 {
708 for (int i = 0; i < ch_len; i++)
709 {
710 ch_time[i] = ((uint16_t)EEPROM.read(rp + 4 * i)) |
711 (((uint16_t)EEPROM.read(rp + 1 + 4 * i)) << 8);
712 ch_servo[i] = EEPROM.read(rp + 2 + 4 * i);
713 ch_val[i] = EEPROM.read(rp + 3 + 4 * i);
714 }
715 serial_println_flash(PSTR("ok"));
716 pipni();
717 }
718 }
719
720 void naformatuj_EEPROM_choreografie()
721 {
722 EEPROM.write(0, 0);
723 EEPROM.write(21, 0);
724 EEPROM.write(22, 0);
725 EEPROM.write(23, 0);
726 serial_println_flash(PSTR("ok"));
727 pipni();
728 }
729
730 void precitaj_kalibraciu_z_EEPROM()
731 {
732 uint8_t value = EEPROM.read(1);
733 if ((value != '~') && (value != '1') && (value != '2') && (value != '3')) return;
734 if (value != '~') auto_start = value - '0';
735 else auto_start = 0;
736 for (int i = 2; i < 8; i++)
737 {
738 int16_t k = EEPROM.read(i);
739 if (k > 127) servo_invertovane[i - 2] = 1;
740 else servo_invertovane[i - 2] = 0;
741 k &= 127;
742 prednastavena_kalibracia[i - 2] = k + (90-63);
743 }
744 for (int i = 0; i < 6; i++)
745 dolny_limit[i] = EEPROM.read(i + 9);
746 for (int i = 0; i < 6; i++)
747 horny_limit[i] = EEPROM.read(i + 15);
748 }
749
750 char read_char()
751 {
752 while (!serial_available() && !Serial.available());
753 if (serial_available()) return serial_read();
754 else return Serial.read();
755 }
756
757 void zapis_kalibraciu_do_EEPROM()
758 {
759 serial_print_flash(PSTR("Naozaj chces zapisat kalibraciu do EEPROM? [Y/n]: "));
760 char odpoved = read_char();
761 serial_println_char(odpoved);
762 if (odpoved == 'Y')
763 {
764 char kalib_state = EEPROM.read(1);
765 if ((kalib_state == '~') || ((kalib_state >= '1') && (kalib_state <= '3')))
766 EEPROM.write(1, kalib_state);
767 else EEPROM.write(1, '~');
768 for (int i = 2; i < 8; i++)
769 {
770 int16_t k = kalib[i - 2] - (90-63);
771 if (k < 0) k = 0;
772 else if (k > 127) k = 127;
773 if (servo_invertovane[i - 2]) k += 128;
774 EEPROM.write(i, (uint8_t)k);
775 }
776 for (int i = 0; i < 6; i++)
777 EEPROM.write(9 + i, dolny_limit[i]);
778 for (int i = 0; i < 6; i++)
779 EEPROM.write(15 + i, horny_limit[i]);
780 serial_println_flash(PSTR("ok"));
781 }
782 }
783
784 void pipni()
785 {
786 tone2( 1568, 50);
787 delay(100);
788 tone2( 1357, 50);
789 }
790
791 void ruky()
792 {
793 uint8_t odloz_spomalenie = spomalenie;
794 spomalenie = 0;
795 nastav_koncatinu(5, 0);
796 nastav_koncatinu(6, 0);
797 delay(1000);
798 nastav_koncatinu(5, 90);
799 nastav_koncatinu(6, 90);
800 spomalenie = odloz_spomalenie;
801 delay(1000);
802 pipni();
803 }
804
805 void ahoj()
806 {
807 tone2( 1568, 50);
808 delay(70);
809 tone2( 1175, 30);
810 delay(50);
811 tone2( 880, 30);
812 delay(50);
813 tone2( 1047, 50);
814 delay(70);
815 tone2( 1245, 30);
816 delay(150);
817 tone2( 1568, 50);
818 delay(100);
819 if (random(10) > 4) tone2( 1357, 50);
820 else tone2( 1047, 50);
821 }
822
823 void nastav_koncatinu(int8_t srv, uint8_t poloha)
824 {
825 int8_t delta;
826 srv--;
827
828 if (servo_invertovane[srv]) poloha = 180 - poloha;
829
830 if ((int16_t)poloha + (int16_t)kalib[srv] - 90 < 0) poloha = 0;
831 else poloha += kalib[srv] - 90;
832
833 if (poloha > 180) poloha = 180;
834
835 if (spomalenie == 0) {
836 stav[srv] = poloha;
837 s[srv].write(stav[srv]);
838 }
839 else {
840 if (stav[srv] < poloha) delta = 1;
841 else delta = -1;
842 while (stav[srv] != poloha)
843 {
844 stav[srv] += delta;
845 s[srv].write(stav[srv]);
846 delay(spomalenie);
847 }
848 }
849 }
850
851 void zobraz_stav()
852 {
853 for (int i = 0; i < 6; i++)
854 {
855 serial_print_flash(PSTR("S")); serial_print_num(i + 1); serial_print_flash(PSTR(": ")); serial_println_num(stav[i] - kalib[i] + 90);
856 }
857 serial_println_flash(PSTR("---"));
858 pipni();
859 }
860
861 void pohyb(int8_t servo)
862 {
863 int8_t srv = (servo > 0) ? servo : -servo;
864 srv--;
865 if (servo_invertovane[srv]) servo = -servo;
866 if (servo > 0)
867 {
868 if (stav[srv] <= horny_limit[srv] - krok) stav[srv] += krok;
869 else stav[srv] = horny_limit[srv];
870 s[srv].write(stav[srv]);
871 }
872 else if (servo < 0)
873 {
874 if (stav[srv] >= dolny_limit[srv] + krok) stav[srv] -= krok;
875 else stav[srv] = dolny_limit[srv];
876 s[srv].write(stav[srv]);
877 }
878 }
879
880 uint8_t pohyb_znakom(char z)
881 {
882 for (int i = 0; i < 12; i++)
883 {
884 if (z == znaky_zmien[i])
885 {
886 int8_t servo = zmeny[i];
887 pohyb(servo);
888 }
889 }
890 }
891
892 void kombinacia1()
893 {
894 pohyb(SERVO_LAVA_NOHA);
895 pohyb(-SERVO_PRAVA_PATA);
896 }
897
898 void kombinacia2()
899 {
900 pohyb(SERVO_PRAVA_NOHA);
901 pohyb(-SERVO_LAVA_PATA);
902 }
903
904 void kombinacia3()
905 {
906 pohyb(SERVO_LAVA_RUKA);
907 pohyb(SERVO_PRAVA_RUKA);
908 }
909
910 void kombinacia4()
911 {
912 pohyb(-SERVO_LAVA_RUKA);
913 pohyb(-SERVO_PRAVA_RUKA);
914 }
915
916 int pohyb_kombinacia(char z)
917 {
918 if (z == '3') kombinacia1();
919 else if (z == '4') kombinacia2();
920 else if (z == '5') kombinacia3();
921 else if (z == '6') kombinacia4();
922 else return 0;
923 return 1;
924 }
925
926 int nacitajCislo()
927 {
928 int num = 0;
929 int z;
930 do {
931 z = read_char();
932 if (z == '#') while (z != 13) z = read_char();
933 } while ((z < '0') || (z > '9'));
934 while ((z >= '0') && (z <= '9'))
935 {
936 num *= 10;
937 num += (z - '0');
938 do {
939 z = read_char();
940 if (z == -1) delayMicroseconds(10);
941 } while (z < 0);
942 }
943 return num;
944 }
945
946 void nacitaj_choreografiu()
947 {
948 ch_len = 0;
949 int tm;
950 do {
951 tm = nacitajCislo();
952 ch_time[ch_len] = tm;
953 ch_servo[ch_len] = nacitajCislo();
954 ch_val[ch_len] = nacitajCislo();
955 ch_len++;
956 if (ch_len == CHOREO_LEN) break;
957 } while (tm > 0);
958 pipni();
959 }
960
961 void vypis_choreografiu()
962 {
963 for (int i = 0; i < ch_len; i++)
964 {
965 serial_print_num(ch_time[i]);
966 serial_print(" ");
967 serial_print_num(ch_servo[i]);
968 serial_print(" ");
969 serial_println_num(ch_val[i]);
970 }
971 serial_println_flash(PSTR("---"));
972 pipni();
973 }
974
975 uint32_t koniec_tanca;
976
977 void zatancuj_choreografiu(uint16_t *ch_time, uint8_t *ch_servo, uint8_t *ch_val, int ch_len )
978 {
979 koniec_tanca = millis() + 3600000;
980 for (int i = 0; i < ch_len - 1; i++)
981 {
982 delay(ch_time[i]);
983 if (millis() > koniec_tanca) break;
984 if (ch_servo[i] < 7) nastav_koncatinu(ch_servo[i], ch_val[i]);
985 else i = specialny_prikaz(i, ch_servo[i], ch_val[i]);
986 if (serial_available() || Serial.available()) break;
987 }
988 pipni();
989 }
990
991 int specialny_prikaz(uint16_t i, uint8_t prikaz, uint8_t argument)
992 {
993 if (prikaz == 8) koniec_tanca = millis() + 1000 * (uint32_t)argument;
994 else if (prikaz == 9) return ((int)argument) - 1;
995 else if (prikaz == 10) spomalenie = argument;
996 else if (prikaz == 11) zahraj_melodiu(argument);
997 else if (prikaz == 12) zvukovy_efekt(argument);
998 return i;
999 }
1000
1001 void reset()
1002 {
1003 for (int i = 0; i < 6; i++)
1004 {
1005 stav[i] = kalib[i];
1006 s[i].write(kalib[i]);
1007 delay(300);
1008 }
1009 pipni();
1010 }
1011
1012 uint8_t nalad_hodnotu_serva(uint8_t servo, uint8_t hodnota, uint8_t min_hodnota, uint8_t max_hodnota)
1013 {
1014 serial_print_flash(PSTR(" (+/-/ENTER): "));
1015 serial_println_num(hodnota);
1016 s[servo].write(hodnota);
1017 char z;
1018 do {
1019 z = read_char();
1020 if ((z == '+') && (hodnota < max_hodnota)) hodnota++;
1021 else if ((z == '-') && (hodnota > min_hodnota)) hodnota--;
1022 if ((z == '+') || (z == '-'))
1023 {
1024 serial_print_num(hodnota); serial_print_char('\r');
1025 s[servo].write(hodnota);
1026 }
1027 } while (z != 13);
1028 return hodnota;
1029 }
1030
1031 void kalibruj()
1032 {
1033 for (int i = 0; i < 6; i++)
1034 {
1035 serial_print_num(i);
1036 kalib[i] = nalad_hodnotu_serva(i, kalib[i], 90-63, 90+63);
1037 serial_print_num(i);
1038 serial_print(": ");
1039 serial_println_num(kalib[i]);
1040 }
1041 for (int i = 0; i < 6; i++) {
1042 serial_print_num(kalib[i]);
1043 serial_print(" ");
1044 }
1045 serial_print_flash(PSTR(" Chyt robota zozadu za telo (ENTER):"));
1046 char z;
1047 do { z = read_char(); } while (z != 13);
1048 serial_println(z);
1049
1050 serial_print_flash(PSTR("*** Nasledujuce koncatiny su lave/prave z pohladu robota.\r\nAk to nesedi, treba prehodit kabliky servo!\r\n"));
1051
1052 for (int i = 0; i < 6; i++) servo_invertovane[i] = 0;
1053
1054 nastav_koncatinu(SERVO_PRAVA_PATA, 0);
1055 serial_print_flash(PSTR("Prava pata: je von alebo dnu? (V/D):"));
1056 do { z = read_char(); } while ((z != 'V') && (z != 'D'));
1057 serial_println_char(z);
1058 nastav_koncatinu(SERVO_PRAVA_PATA, 90);
1059 if (z == 'D') servo_invertovane[SERVO_PRAVA_PATA - 1] = 0;
1060 else servo_invertovane[SERVO_PRAVA_PATA - 1] = 1;
1061
1062 nastav_koncatinu(SERVO_LAVA_PATA, 0);
1063 serial_print_flash(PSTR("Lava pata: je von alebo dnu? (V/D):"));
1064 do { z = read_char(); } while ((z != 'V') && (z != 'D'));
1065 serial_println_char(z);
1066 nastav_koncatinu(SERVO_LAVA_PATA, 90);
1067 if (z == 'V') servo_invertovane[SERVO_LAVA_PATA - 1] = 0;
1068 else servo_invertovane[SERVO_LAVA_PATA - 1] = 1;
1069
1070 nastav_koncatinu(SERVO_PRAVA_NOHA, 0);
1071 serial_print_flash(PSTR("Prava noha: vpredu je pata alebo spicka? (P/S):"));
1072 do { z = read_char(); } while ((z != 'P') && (z != 'S'));
1073 serial_println_char(z);
1074 nastav_koncatinu(SERVO_PRAVA_NOHA, 90);
1075 if (z == 'P') servo_invertovane[SERVO_PRAVA_NOHA - 1] = 1;
1076 else servo_invertovane[SERVO_PRAVA_NOHA - 1] = 0;
1077
1078 nastav_koncatinu(SERVO_LAVA_NOHA, 0);
1079 serial_print_flash(PSTR("Lava noha: vpredu je pata alebo spicka? (P/S):"));
1080 do { z = read_char(); } while ((z != 'P') && (z != 'S'));
1081 serial_println_char(z);
1082 nastav_koncatinu(SERVO_LAVA_NOHA, 90);
1083 if (z == 'S') servo_invertovane[SERVO_LAVA_NOHA - 1] = 1;
1084 else servo_invertovane[SERVO_LAVA_NOHA - 1] = 0;
1085
1086 nastav_koncatinu(SERVO_PRAVA_RUKA, 0);
1087 serial_print_flash(PSTR("Prava ruka: je hore alebo dole? (H/D):"));
1088 do { z = read_char(); } while ((z != 'H') && (z != 'D'));
1089 serial_println_char(z);
1090 nastav_koncatinu(SERVO_PRAVA_RUKA, 90);
1091 if (z == 'H') servo_invertovane[SERVO_PRAVA_RUKA - 1] = 1;
1092 else servo_invertovane[SERVO_PRAVA_RUKA - 1] = 0;
1093
1094 nastav_koncatinu(SERVO_LAVA_RUKA, 0);
1095 serial_print_flash(PSTR("Lava ruka: je hore alebo dole? (H/D):"));
1096 do { z = read_char(); } while ((z != 'H') && (z != 'D'));
1097 serial_println_char(z);
1098 nastav_koncatinu(SERVO_LAVA_RUKA, 90);
1099 if (z == 'D') servo_invertovane[SERVO_PRAVA_RUKA - 1] = 0;
1100 else servo_invertovane[SERVO_PRAVA_RUKA - 1] = 1;
1101
1102 serial_println_flash(PSTR("ok"));
1103 pipni();
1104 }
1105
1106 void nastav_limity()
1107 {
1108 for (int i = 0; i < 6; i++)
1109 {
1110 serial_print_num(i);
1111 serial_print_flash(PSTR("dolny"));
1112 dolny_limit[i] = nalad_hodnotu_serva(i, dolny_limit[i], 0, 180);
1113 serial_print_num(i);
1114 serial_print_flash(PSTR(" dolny: "));
1115 serial_println_num(dolny_limit[i]);
1116 s[i].write(kalib[i]);
1117
1118 serial_print_num(i);
1119 serial_print_flash(PSTR("horny"));
1120 horny_limit[i] = nalad_hodnotu_serva(i, horny_limit[i], 0, 180);
1121 serial_print_num(i);
1122 serial_print_flash(PSTR(" horny: "));
1123 serial_println_num(horny_limit[i]);
1124 s[i].write(kalib[i]);
1125 }
1126 for (int i = 0; i < 6; i++) {
1127 serial_print_num(dolny_limit[i]);
1128 serial_print("-");
1129 serial_print_num(horny_limit[i]);
1130 serial_print(" ");
1131 }
1132 serial_println_flash(PSTR("ok"));
1133 pipni();
1134 }
1135
1136 void vypis_kalibraciu()
1137 {
1138 serial_print_flash(PSTR("stredy: "));
1139 for (int i = 0; i < 6; i++) {
1140 serial_print_num(kalib[i]);
1141 serial_print(" ");
1142 }
1143 serial_println();
1144
1145 serial_print_flash(PSTR("invertovane servo: "));
1146 for (int i = 0; i < 6; i++)
1147 {
1148 serial_print_num(servo_invertovane[i]);
1149 serial_print_char(' ');
1150 }
1151 serial_println();
1152
1153 serial_print_flash(PSTR("dolny limit: "));
1154 for (int i = 0; i < 6; i++) {
1155 serial_print_num(dolny_limit[i]);
1156 serial_print(" ");
1157 }
1158 serial_println();
1159 serial_print_flash(PSTR("horny limit: "));
1160 for (int i = 0; i < 6; i++) {
1161 serial_print_num(horny_limit[i]);
1162 serial_print(" ");
1163 }
1164 serial_println();
1165 }
1166
1167 void nacitaj_kalibraciu()
1168 {
1169 int tm;
1170 for (int i = 0; i < 6; i++)
1171 kalib[i] = nacitajCislo();
1172 vypis_kalibraciu();
1173 serial_println_flash(PSTR("ok"));
1174 pipni();
1175 }
1176
1177 void zvys_krok()
1178 {
1179 if (krok < 180) krok++;
1180 serial_print_flash(PSTR("krok: "));
1181 serial_println_num(krok);
1182 }
1183
1184 void zniz_krok()
1185 {
1186 if (krok > 0) krok--;
1187 serial_print_flash(PSTR("krok: "));
1188 serial_println_num(krok);
1189 }
1190
1191 void zniz_spomalenie()
1192 {
1193 if (spomalenie > 0) spomalenie--;
1194 serial_print_flash(PSTR("spomalenie: "));
1195 serial_println_num(spomalenie);
1196 }
1197
1198 void zvys_spomalenie()
1199 {
1200 if (spomalenie < 100) spomalenie++;
1201 serial_print_flash(PSTR("spomalenie: "));
1202 serial_println_num(spomalenie);
1203 }
1204
1205 // nasleduje softverova implementacia serioveho portu
1206 #define SERIAL_STATE_IDLE 0
1207 #define SERIAL_STATE_RECEIVING 1
1208 #define SERIAL_BUFFER_LENGTH 20
1209
1210 static volatile uint8_t serial_state;
1211 static uint8_t serial_buffer[SERIAL_BUFFER_LENGTH];
1212 static volatile uint8_t serial_buf_wp, serial_buf_rp;
1213
1214 static volatile uint8_t receiving_byte;
1215
1216 static volatile uint32_t time_startbit_noticed;
1217 static volatile uint8_t next_bit_order;
1218 static volatile uint8_t waiting_stop_bit;
1219 static uint16_t one_byte_duration;
1220 static uint16_t one_bit_duration;
1221 static uint16_t one_bit_write_duration;
1222 static uint16_t half_of_one_bit_duration;
1223
1224 void init_serial(uint32_t baud_rate)
1225 {
1226 pinMode(2, INPUT);
1227 pinMode(4, OUTPUT);
1228
1229 serial_state = SERIAL_STATE_IDLE;
1230
1231 one_byte_duration = 9500000 / baud_rate;
1232 one_bit_duration = 1000000 / baud_rate;
1233 one_bit_write_duration = one_bit_duration - 1;
1234 half_of_one_bit_duration = 500000 / baud_rate;
1235
1236 PCMSK2 |= 4; //PCINT18;
1237 PCIFR &= ~4; //PCIF2;
1238 PCICR |= 4; // PCIE2;
1239 }
1240
1241 ISR(PCINT2_vect)
1242 {
1243 uint32_t tm = micros();
1244 if (serial_state == SERIAL_STATE_IDLE)
1245 {
1246 time_startbit_noticed = tm;
1247 serial_state = SERIAL_STATE_RECEIVING;
1248 receiving_byte = 0xFF;
1249 next_bit_order = 0;
1250 }
1251 else if (tm - time_startbit_noticed > one_byte_duration)
1252 {
1253 serial_buffer[serial_buf_wp] = receiving_byte;
1254 serial_buf_wp++;
1255 if (serial_buf_wp == SERIAL_BUFFER_LENGTH) serial_buf_wp = 0;
1256 time_startbit_noticed = tm;
1257 receiving_byte = 0xFF;
1258 next_bit_order = 0;
1259 }
1260 else if (PIND & 4)
1261 {
1262 int8_t new_next_bit_order = (tm - time_startbit_noticed - half_of_one_bit_duration) / one_bit_duration;
1263 while (next_bit_order < new_next_bit_order)
1264 {
1265 receiving_byte &= ~(1 << next_bit_order);
1266 next_bit_order++;
1267 }
1268 if (next_bit_order == 8)
1269 {
1270 serial_buffer[serial_buf_wp] = receiving_byte;
1271 serial_buf_wp++;
1272 if (serial_buf_wp == SERIAL_BUFFER_LENGTH) serial_buf_wp = 0;
1273 serial_state = SERIAL_STATE_IDLE;
1274 }
1275 } else
1276 next_bit_order = (tm - time_startbit_noticed - half_of_one_bit_duration) / one_bit_duration;
1277 }
1278
1279 uint8_t serial_available()
1280 {
1281 cli();
1282 if (serial_buf_rp != serial_buf_wp)
1283 {
1284 sei();
1285 return 1;
1286 }
1287 if (serial_state == SERIAL_STATE_RECEIVING)
1288 {
1289 uint32_t tm = micros();
1290 if (tm - time_startbit_noticed > one_byte_duration)
1291 {
1292 serial_state = SERIAL_STATE_IDLE;
1293 serial_buffer[serial_buf_wp] = receiving_byte;
1294 serial_buf_wp++;
1295 if (serial_buf_wp == SERIAL_BUFFER_LENGTH) serial_buf_wp = 0;
1296 sei();
1297 return 1;
1298 }
1299 }
1300 sei();
1301 return 0;
1302 }
1303
1304 int16_t serial_read()
1305 {
1306 cli();
1307 if (serial_buf_rp != serial_buf_wp)
1308 {
1309 uint8_t ch = serial_buffer[serial_buf_rp];
1310 serial_buf_rp++;
1311 if (serial_buf_rp == SERIAL_BUFFER_LENGTH) serial_buf_rp = 0;
1312 sei();
1313 return ch;
1314 }
1315
1316 if (serial_state == SERIAL_STATE_RECEIVING)
1317 {
1318 uint32_t tm = micros();
1319 if (tm - time_startbit_noticed > one_byte_duration)
1320 {
1321 uint8_t ch = receiving_byte;
1322 serial_state = SERIAL_STATE_IDLE;
1323 sei();
1324 return ch;
1325 }
1326 }
1327 sei();
1328 return -1;
1329 }
1330
1331 void serial_write(uint8_t ch)
1332 {
1333 #ifdef ECHO_BT_TO_USB
1334 Serial.print((char)ch);
1335 #endif
1336 PORTD &= ~16;
1337 delayMicroseconds(one_bit_write_duration);
1338 for (uint8_t i = 0; i < 8; i++)
1339 {
1340 if (ch & 1) PORTD |= 16;
1341 else PORTD &= ~16;
1342 ch >>= 1;
1343 delayMicroseconds(one_bit_write_duration);
1344 }
1345 PORTD |= 16;
1346 delayMicroseconds(one_bit_write_duration);
1347 delayMicroseconds(one_bit_write_duration);
1348 delayMicroseconds(one_bit_write_duration);
1349 delayMicroseconds(one_bit_write_duration);
1350 delayMicroseconds(one_bit_write_duration);
1351 }
1352
1353 uint16_t serial_readln(uint8_t *ln, uint16_t max_length)
1354 {
1355 uint16_t len;
1356 uint16_t ch;
1357 do {
1358 ch = serial_read();
1359 if (ch == 13) continue;
1360 } while (ch == -1);
1361
1362 do {
1363 if ((ch != 13) && (ch != 10) && (ch != -1))
1364 {
1365 *(ln++) = ch;
1366 max_length--;
1367 len++;
1368 }
1369 ch = serial_read();
1370 } while ((ch != 13) && max_length);
1371 *ln = 0;
1372 return len;
1373 }
1374
1375 void serial_print_num(int32_t number)
1376 {
1377 if (number < 0)
1378 {
1379 serial_write('-');
1380 number = -number;
1381 }
1382 int32_t rad = 1;
1383 while (number / rad) rad *= 10;
1384 if (number > 0) rad /= 10;
1385 while (rad)
1386 {
1387 serial_write((char)('0' + (number / rad)));
1388 number -= (number / rad) * rad;
1389 rad /= 10;
1390 }
1391 }
1392
1393 void serial_print_char(char ch)
1394 {
1395 serial_write(ch);
1396 }
1397
1398 void serial_print(const uint8_t *str)
1399 {
1400 while (*str) serial_write(*(str++));
1401 }
1402
1403 void serial_println(const uint8_t *str)
1404 {
1405 serial_print(str);
1406 serial_write(13);
1407 serial_write(10);
1408 }
1409
1410 void serial_print_flash(const uint8_t PROGMEM *str)
1411 {
1412 int ln = strlen_P(str);
1413 for (int i = 0; i < ln; i++)
1414 serial_write(pgm_read_byte(str + i));
1415 }
1416
1417 void serial_println_flash(const uint8_t PROGMEM *str)
1418 {
1419 serial_print_flash(str);
1420 serial_write(13);
1421 serial_write(10);
1422 }
1423
1424 void serial_println_num(int32_t number)
1425 {
1426 serial_print_num(number);
1427 serial_println();
1428 }
1429
1430 void serial_println_char(char ch)
1431 {
1432 serial_write(ch);
1433 serial_println();
1434 }
1435
1436 void serial_println()
1437 {
1438 serial_write(13);
1439 serial_write(10);
1440 }
1441
1442 // nasleduje citanie z utltazvukoveho senzora
1443
1444 static volatile uint32_t pulse_start;
1445 static volatile uint8_t new_distance;
1446
1447 void init_ultrasonic()
1448 {
1449 pinMode(US_ECHO, INPUT);
1450 pinMode(US_TRIG, OUTPUT);
1451
1452 PCMSK0 |= 1; //PCINT0;
1453 PCIFR &= ~1; //PCIF0;
1454 PCICR |= 1; // PCIE0;
1455 }
1456
1457 ISR(PCINT0_vect)
1458 {
1459 if (PINB & 1) pulse_start = micros();
1460 else
1461 {
1462 distance = (int16_t)((micros() - pulse_start) / 58);
1463 new_distance = 1;
1464 }
1465 }
1466
1467 void start_distance_measurement()
1468 {
1469 distance = 10000;
1470 new_distance = 0;
1471 digitalWrite(US_TRIG, HIGH);
1472 delayMicroseconds(10);
1473 digitalWrite(US_TRIG, LOW);
1474 }
1475
1476 void wait_for_distance_measurement_to_complete()
1477 {
1478 uint8_t counter = 0;
1479 while ((counter < 20) && !new_distance)
1480 {
1481 delay(1);
1482 counter++;
1483 }
1484 if (counter == 20)
1485 {
1486 pinMode(US_ECHO, OUTPUT);
1487 digitalWrite(US_ECHO, HIGH);
1488 delayMicroseconds(10);
1489 digitalWrite(US_ECHO, LOW);
1490 pinMode(US_ECHO, INPUT);
1491 delayMicroseconds(5);
1492 distance = 10000;
1493 }
1494 }
1495
1496 int16_t measure_distance()
1497 {
1498 start_distance_measurement();
1499 wait_for_distance_measurement_to_complete();
1500 return distance;
1501 }
1502
1503 //-------------------------------- nasleduje prehravanie melodie a hranie cez timer2 v pozadi
1504 #define SIRENE_PORT PORTB
1505 #define SIRENE_DDR DDRB
1506 #define SIRENE_PIN 4
1507
1508 #define FIS3 2960
1509 #define G3 3136
1510
1511 float octave_4[] = { 2093.00, 2217.46, 2349.32, 2489.02, 2637.02, 2793.83, 2959.96, 3135.96, 3322.44, 3520.00, 3729.31, 3951.07 };
1512
1513 //popcorn
1514 uint16_t dlzka_melodia[] = {0, 386, 26, 281, 217};
1515 const uint8_t melodia1[] PROGMEM = { 252, 50, 149, 49,
1516 28, 31, 35, 40, 49, 99, 38, 49, 99, 40, 49, 99, 35, 49, 99, 31, 49, 99, 35, 49, 99, 28, 49, 99, 49,
1517 28, 31, 35, 40, 49, 99, 38, 49, 99, 40, 49, 99, 35, 49, 99, 31, 49, 99, 35, 49, 99, 28, 49, 99, 149,
1518 40, 49, 99, 42, 49, 99, 43, 49, 99, 42, 49, 99, 43, 49, 99, 40, 49, 99, 42, 49, 99, 40, 49, 99, 42, 49, 99, 38, 49, 99, 40, 49, 99, 38, 49, 99, 40, 49, 99, 36, 49, 99, 40, 49, 99,
1519 28, 31, 35, 40, 49, 99, 38, 49, 99, 40, 49, 99, 35, 49, 99, 31, 49, 99, 35, 49, 99, 28, 49, 99, 49,
1520 28, 31, 35, 40, 49, 99, 38, 49, 99, 40, 49, 99, 35, 49, 99, 31, 49, 99, 35, 49, 99, 28, 49, 99, 149,
1521 40, 49, 99, 42, 49, 99, 43, 49, 99, 42, 49, 99, 43, 49, 99, 40, 49, 99, 42, 49, 99, 40, 49, 99, 42, 49, 99, 38, 49, 99, 40, 49, 99, 38, 49, 99, 40, 49, 99, 42, 49, 99, 43, 49, 99,
1522 49, 35, 38, 43, 47, 49, 99, 45, 49, 99, 47, 49, 99, 43, 49, 99, 38, 49, 99, 43, 49, 99, 35, 49, 99,
1523 49, 35, 38, 43, 47, 49, 99, 45, 49, 99, 47, 49, 99, 43, 49, 99, 38, 49, 99, 43, 49, 99, 35, 49, 99, 149 ,
1524 47, 49, 99, 254, 49, 99, 255, 49, 99, 254, 49, 99, 255, 49, 99, 47, 49, 99, 254, 49, 99, 47, 49, 99, 254, 49, 99, 45, 49, 99, 47, 49, 99, 45, 49, 99, 47, 49, 99, 43, 49, 99, 47, 49, 99,
1525 49, 35, 38, 43, 47, 49, 99, 45, 49, 99, 47, 49, 99, 43, 49, 99, 38, 49, 99, 43, 49, 99, 35, 49, 99,
1526 49, 35, 38, 43, 47, 49, 99, 45, 49, 99, 47, 49, 99, 43, 49, 99, 38, 49, 99, 43, 49, 99, 35, 49, 99, 149 ,
1527 47, 49, 99, 254, 49, 99, 255, 49, 99, 254, 49, 99, 255, 49, 99, 47, 49, 99, 254, 49, 99, 47, 49, 99, 254, 49, 99, 45, 49, 99, 47, 49, 99, 45, 49, 99, 47, 49, 99, 254, 49, 99, 255, 49, 99
1528 };
1529
1530 //kohutik jarabi
1531 const uint8_t melodia2[] PROGMEM = { 252, 150, 119, 121, 173, 174, 124, 124, 124, 123, 171, 173, 123, 123, 123, 121, 169, 171, 121, 121, 121, 123, 171, 169, 119, 119 };
1532
1533 // kankán
1534 const uint8_t melodia3[] PROGMEM = { 252, 100,
1535 251, 1, 184, 1, 32, 126, 149, 251, 1, 184, 1, 32, 126, 149, 251, 1, 184, 1, 32, 126, 251, 1, 184, 1, 32, 126, 251, 1, 184, 1, 32, 126, 251, 1, 184, 1, 32, 126,
1536 64, 71, 71, 73, 71, 69, 69, 73, 74, 78, 81, 78, 78, 76, 251, 1, 184, 1, 32, 126, 78, 68, 68, 78, 76, 69, 69, 73, 73, 71, 73, 71, 85, 83, 85, 83,
1537 64, 71, 71, 73, 71, 69, 69, 73, 74, 78, 81, 78, 78, 76, 251, 1, 184, 1, 32, 126, 78, 68, 68, 78, 76, 69, 69, 73, 73, 71, 73, 71, 71, 69, 119,
1538 135, 131, 128, 126, 75, 76, 78, 80, 81, 76, 80, 76, 81, 76, 80, 76, 81, 76, 80, 76, 81, 76, 80, 76,
1539 251, 2, 11, 3, 16, 19, 251, 1, 4, 3, 16, 19,
1540 251, 1, 4, 3, 16, 19, 251, 1, 4, 3, 16, 19,
1541 251, 1, 4, 3, 16, 19, 251, 1, 4, 3, 16, 19,
1542 251, 1, 4, 3, 16, 19, 251, 1, 4, 3, 16, 19,
1543 174, 88, 91, 90, 88, 143, 143, 93, 95, 90, 91, 138, 138, 88, 91, 90, 88, 86, 86, 85, 83, 81, 79, 78, 76,
1544 174, 88, 91, 90, 88, 143, 143, 93, 95, 90, 91, 138, 138, 88, 91, 90, 88, 86, 93, 89, 90, 136,
1545 64, 71, 71, 73, 71, 69, 69, 73, 74, 78, 81, 78, 78, 76, 251, 1, 184, 1, 32, 126,
1546 78, 76, 126, 78, 76, 126, 78, 76, 126, 78, 76, 126, 78, 76, 126, 78, 76, 126,
1547 78, 76, 78, 76, 78, 76, 78, 76,
1548 131, 119, 119, 119, 169
1549 };
1550
1551 //labutie jazero
1552 const uint8_t melodia4[] PROGMEM = {
1553 252, 220, 66, 69, 73, 69, 66, 69, 73, 69, 66, 69, 73, 69, 66, 69, 73, 69,
1554 185, 78, 80, 81, 83, 251, 5, 39, 3, 8, 81, 251, 5, 39, 3, 8, 81, 251, 5, 39, 3, 8, 78, 81, 78, 73, 81, 178,
1555 99, 83, 81, 80,
1556 185, 78, 80, 81, 83, 251, 5, 39, 3, 8, 81, 251, 5, 39, 3, 8, 81, 251, 5, 39, 3, 8, 78, 81, 78, 73, 81, 178,
1557 149, 128, 130, 131, 133, 85, 86, 251, 6, 32, 3, 8, 86, 135, 86, 88, 251, 6, 224, 3, 8, 88, 136, 88, 90, 251, 7, 184, 3, 8, 90, 85, 81, 80, 78,
1558 130, 131, 133, 85, 86, 251, 6, 32, 3, 8, 86, 135, 86, 88, 251, 6, 224, 3, 8, 88, 136, 88, 90, 251, 7, 73, 3, 8, 86, 133, 86, 91, 251, 7, 184, 3, 8, 87, 251, 7, 184, 3, 8, 85,
1559 185, 78, 80, 81, 83, 251, 5, 39, 3, 8, 81, 251, 5, 39, 3, 8, 81, 251, 5, 39, 3, 8, 78, 81, 78, 73, 81, 178,
1560 99, 83, 81, 80,
1561 185, 78, 80, 81, 83, 251, 5, 39, 3, 8, 81, 251, 5, 39, 3, 8, 81, 251, 5, 39, 3, 8, 78, 81, 78, 73, 81, 178
1562 };
1563
1564 volatile int16_t music_speed = 800 / 16;
1565
1566 volatile PGM_P current_note ;
1567 volatile uint16_t notes_remaining;
1568
1569 void zahraj_melodiu(uint8_t cislo)
1570 {
1571 if (cislo == 0) {
1572 zastav_melodiu();
1573 return;
1574 }
1575
1576 if (cislo == 1) current_note = melodia1;
1577 else if (cislo == 2) current_note = melodia2;
1578 else if (cislo == 3) current_note = melodia3;
1579 else if (cislo == 4) current_note = melodia4;
1580 notes_remaining = dlzka_melodia[cislo];
1581
1582 next_note();
1583 }
1584
1585 void next_note()
1586 {
1587 uint16_t freq, dur;
1588 if (!notes_remaining) return;
1589 otto_translate_tone_flash(&freq, &dur);
1590 tone2(freq, dur);
1591 }
1592
1593 void otto_translate_tone_flash(uint16_t *freq, uint16_t *del)
1594 {
1595 do {
1596 uint8_t n = pgm_read_byte(current_note);
1597 if (n == 251)
1598 {
1599 current_note++;
1600 uint8_t f1 = pgm_read_byte(current_note);
1601 current_note++;
1602 uint8_t f2 = pgm_read_byte(current_note);
1603 current_note++;
1604 uint8_t d1 = pgm_read_byte(current_note);
1605 current_note++;
1606 uint8_t d2 = pgm_read_byte(current_note);
1607 *freq = (f1 << 8) + f2;
1608 *del = (music_speed * 16 * (long)d1) / d2;
1609 notes_remaining -= 4;
1610 }
1611 else if (n == 252)
1612 {
1613 current_note++;
1614 music_speed = pgm_read_byte(current_note);
1615 current_note++;
1616 notes_remaining -= 2;
1617 continue;
1618 }
1619 else if (n == 254)
1620 {
1621 *freq = FIS3;
1622 *del = music_speed;
1623 }
1624 else if (n == 255)
1625 {
1626 *freq = G3;
1627 *del = music_speed;
1628 }
1629 else
1630 {
1631 uint8_t len = n / 50;
1632 *del = music_speed;
1633 while (len--) *del *= 2;
1634 n = n % 50;
1635 if (n != 49)
1636 {
1637 uint8_t octave = (n + 5) / 12;
1638 n = (n + 5) % 12;
1639 float ffreq = octave_4[n];
1640 octave = 4 - octave;
1641 while (octave > 0)
1642 {
1643 ffreq /= 2.0;
1644 octave--;
1645 }
1646 *freq = (uint16_t)ffreq;
1647 }
1648 else *freq = 0;
1649 }
1650 notes_remaining--;
1651 current_note++;
1652 break;
1653 } while (1);
1654 }
1655
1656 static volatile uint8_t tone2_state;
1657 static volatile uint8_t tone2_pause;
1658 static volatile uint32_t tone2_len;
1659
1660 void init_tone2()
1661 {
1662 notes_remaining = 0;
1663 tone2_pause = 0;
1664 TCCR2A = 2;
1665 TCCR2B = 0;
1666 TIMSK2 = 2;
1667 SIRENE_DDR |= (1 << SIRENE_PIN);
1668 }
1669
1670
1671 ISR(TIMER2_COMPA_vect)
1672 {
1673 if (!tone2_pause)
1674 {
1675 if (tone2_state)
1676 {
1677 SIRENE_PORT |= (1 << SIRENE_PIN);
1678 tone2_state = 0;
1679 }
1680 else
1681 {
1682 SIRENE_PORT &= ~(1 << SIRENE_PIN);
1683 tone2_state = 1;
1684 }
1685 }
1686 if ((--tone2_len) == 0)
1687 {
1688 TCCR2B = 0;
1689 tone2_pause = 0;
1690 next_note();
1691 }
1692 }
1693
1694 void tone2(uint16_t freq, uint16_t duration)
1695 {
1696 uint32_t period = ((uint32_t)1000000) / (uint32_t)freq;
1697
1698 if (freq >= 977) // prescaler 32
1699 {
1700 tone2_state = 0;
1701 tone2_len = ((uint32_t)duration * (uint32_t)1000) * 2 / period;
1702 if (tone2_len == 0) tone2_len++;
1703 TCNT2 = 0;
1704 OCR2A = (uint8_t) (250000 / (uint32_t)freq);
1705 TCCR2B = 3;
1706 }
1707 else if (freq >= 488) // prescaler 64
1708 {
1709 tone2_state = 0;
1710 tone2_len = ((uint32_t)duration * (uint32_t)1000) * 2 / period;
1711 if (tone2_len == 0) tone2_len++;
1712 TCNT2 = 0;
1713 OCR2A = (uint8_t) (125000 / (uint32_t)freq);
1714 TCCR2B = 4;
1715 }
1716 else if (freq >= 244) // prescaler 128
1717 {
1718 tone2_state = 0;
1719 tone2_len = ((uint32_t)duration * (uint32_t)1000) * 2 / period;
1720 if (tone2_len == 0) tone2_len++;
1721 TCNT2 = 0;
1722 OCR2A = (uint8_t) (62500 / (uint32_t)freq);
1723 TCCR2B = 5;
1724 }
1725 else if (freq >= 122) //prescaler 256
1726 {
1727 tone2_state = 0;
1728 tone2_len = ((uint32_t)duration * (uint32_t)1000) * 2 / period;
1729 if (tone2_len == 0) tone2_len++;
1730 TCNT2 = 0;
1731 OCR2A = (uint8_t) (31250 / (uint32_t)freq);
1732 TCCR2B = 6;
1733 }
1734 else if (freq >= 30) //prescaler 1024
1735 {
1736 tone2_state = 0;
1737 tone2_len = ((uint32_t)duration * (uint32_t)1000) * 2 / period;
1738 if (tone2_len == 0) tone2_len++;
1739 TCNT2 = 0;
1740 OCR2A = (uint8_t) (7813 / (uint32_t)freq);
1741 TCCR2B = 7;
1742 }
1743 else if (freq == 0)
1744 {
1745 tone2_pause = 1;
1746 tone2_state = 0;
1747 period = 1000000 / 500;
1748 tone2_len = ((uint32_t)duration * (uint32_t)1000) * 2 / period;
1749 TCNT2 = 0;
1750 OCR2A = (uint8_t) (125000 / (uint32_t)500);
1751 TCCR2B = 4;
1752 }
1753 else
1754 {
1755 TCCR2B = 0;
1756 }
1757 }
1758
1759 void zastav_melodiu()
1760 {
1761 notes_remaining = 0;
1762 }