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