Kony píše: ↑29 bře 2021, 09:33
A co myslim tou poznamkou, ze se to po chvilce rozjede ta synchronizace ???
Lze to teda nejak osetrit ?
Kdyz mam dva pocitace (Arduina, nebo herni, to je celkem fuk) a kazdy dela neco jineho (a tedy tim stravi jinou dobu) a pak dam obema delay(neco_stejneho), aby pockaly a pak se zase potkaly ve stejnem case, tak se drive nebo pozdeji v tom case proste rozejdou.
Pritom to nemusi byt hned (a vetsinou nebyva), ale ta chyba se muze postupne kumulovat a pak se budes divit, proc ti to (napriklad) priblizne kazdeho 2.5 dne udela nejaky nesmysl - a bude se to blbe ladit, protoze to ladeni ti to bude taky ovlivnovat.
Tady napriklad vysilac jen vysila, prijimac prijima a dela dalsi veci (vypisuje vystup) - to neni moc velky rozdil v case a bude to nejakou dobu prochazet, protoze prijimac prijima na pozadi a plni si buffer a pak to z nej taha. Ale v kazdem pruchodu ten prijimac zacne prijimat o neco pozdeji nez v predchozim a to zpozdeni se bude kumulovat. (Kdybys na kazdy dal jeste LEDku, co se rozsviti, na zacatku loop a pred delay zhasne, tak na prijimaci ta LED bude blikat o maly fous pomaleji, cili po spusteni budou okometricky blikat ve stejnou chvili, po nejake dobe ta na prijimaci uz bude oproti te na vysilaci kus pozadu a postupne se to bude zhorsovat.)
Taky je ten rozdil jeste maly, ale pokud na tom budes stavet neco dalsiho, tak celkem ochotne naroste (treba budes vypisovat ne na Serial, ale na nejake LCD a u nekterych (zvlast nekterych I2C, kde se neprenaci jen ta pismena, ale i vsechny ovladaci signaly mezi nimi, kazdy ve zvlastnim a potvrzenem balicku) ten vypis je relativne pomaly), nebo tam budes ta data zapisovat na SD kartu, kdyz jich bude dost, nebo cokoli jineho. A pak ten rozdil poroste rychleji.
Ze zacatku to nevadi - buffer se naplni, prijimac ho po (cim dal delsi) chvili precte a zpracuje a vypada to OK. Ale buffer je maly a kdyz vnem bude nejen aktualni zprava, ale i ta predchozi a ta pred ni a ... tak po chvili proste narazi na tu svou velikost a bud pretece (a prijdes o data a dalsi cteni ti da neco zmrseneho a nekompletniho), nebo se zastavi a bude cekat na vyprazdneni (a ignorovat nove prichozi zpravy) - a opet podle zakona schvalnosti (delka bufferu neni dobre delitelna delkou zpravy) se to stane uprostred zpravy, konec se zahodi, a pokud se to sejde obzvlast dobre, tak zacnes cist behem prijmu dalsi zpravy, takze zacatek se vyignoruje a pak se tam budou nacitat nejake fragmenty, podle toho, jak se ten buffer bude uvolnovat.
A o nekolik prectenych zprav pozdeji najednou dostanes naprostou haluz a chimeru, kde nebude sedet ani delka zpravy, ani format, ani data nebudou davat smysl.
A protoze nijak nekontrolujes, co vlastne prijimas, tak budes pracovat s naprosto "nahodnymi" daty a nebudes o tom vedet, dokud ti to nezacne delat nekde jinde dalsi haluze - "rozsypany caj" na displaji je jeste to nejmin skodlive - klidne ti binarni polozka pohlavi 0=muz 1=zena najednou bude obsahovat hodnotu 52 a az budes pri scitani do pole soucty[pohlavi] pricitat jednicku, ze jako dalsi kus, tak se to pricte k nahodne polozce v pameti - at uz nejakemu cislu, nebo retezci (obzvlast hezke, pokud to bude zrovna znak konce retezce a po zapocitani "attack chopper" se zmeni v obycejny znak), nebo taky navratova adresa nejake funkce - a pak ti vypocet doslova zabloudi nahodne kamkoli.
----
Proto moje reseni voli jinou strategii
- vysilac vysila kdykoli ho napadne (asi tak kazdou sekundu a kousek), ale ne prilis moc casto, takze prijimac ma sanci to zpracovat.
- prijimac se nepokousi uhodnout, kdy bude vysilac vysilat priste, ale proste ceka, dokud nedorazi nejaka data a pak je zacne zpracovavat.
- - cili pokud bys ve vysilaci ten delay(1000) prepsal treba na delay(500), nebo delay(2000), tak to prijimac nepostrehne a bude i nadale data zpracovavat spravne a vcas. (to je ten
while (0==Serial.available()) {delay(1);}; // cekam, az neco dorazi - a jeste lepsi by bylo tam dat jeden takovyhle pred kazde cteni ve tvaru
while (sizeof(aaa)>Serial.available()) {delay(1);}; // cekam, az dorazi dost bytu pro cteni aaa nebo tak neco )
----
Navic tak nejak nemam rad prikaz
delay(), ktery blokuje procesor a neumozni ten cas vyuzit na neco lepsiho, takze bezne spis nechavam behem "cekani" loop volne cyklovat, aby se daly cist senzory/tlacitka, zpracovavat jine veci a tak podobne.
Jasne ze v takovemto jednoucelovem programu (posilam "Hello" furt dokola a nic jineho) to je celkem fuk, ale takovy program je stejne k nicemu (lepe receno to vetsinou je uvodni pokus k vetsimu projektu, co toho bude delat vic a pak uz to najednou naopak ma smysl resit). Takze bych to odesilani taky resil spis takto ( viz
https://www.arduino.cc/en/Tutorial/Buil ... thoutDelay ) :
Kód: Vybrat vše
unsigned long cekani_interval = 1000UL; // UL znamena Unsigned Long konstantu a resi podivne problemy s prevody na int a zpet
// jeden z nasledujicich dvou radku:
unsigned long cekani_od = 0UL; // a poprve se to spusti "cekani_interval" od startu arduina
unsigned long cekani_od = ~cekani_interval; // "sprosty trik" jak posunout zacatek pred nulu o interval a jednicku navrch - takze se to spusti hned, protoze uz v nule "je pozde" - viz https://cs.wikipedia.org/wiki/Dvojkov%C3%BD_dopln%C4%9Bk
void loop() {
unsigned long ted = millis(); // ulozim aktualni cas, at mam nasledne vsude stejny
if (ted - cekani_od >= cekani_interval) { // kdyz jsem cekal uz dost dlouho, tak musim neco udelat
cekani_od = ted; // dalsi zacatek cekani
int a = 12345;
SendSomething(&a,sizeof(a));
float b=12.345;
SendSomething(&b,sizeof(b));
};
}
s vyhodou, ze mnohem lepe dodrzim ten dany interval, protoze odesilam, zatimco interval uz bezi, ale odesilani je v tom bloku, tak se dokonci i kdyby ten interval byl moc kratky (pak by se vysilalo porad, protoze se to rychleji nestiha)
----
Timto zpusobem muzu mit v loop posilani dat, cteni tlacitek, debouncing, cteni cidel, vypocty a kdovi co dalsiho jeste, a navzajem se to ovlinuje minimalne a nerusi se to a procesor toho stihne mnohem vic "naraz" - a pokud uz je vse hotovo, tak je jedno, zda cykluje beznadejne zavreny v delay, nebo zda porad prochazi loop a kouka, jestli neni nahodou neco pripravene konat.
A jasne ze tohle hraje roli az u trosku vetsi projektu (ktere treba na stisknuti jednoho tlacitka poslou na klavesnici jeden retezec a na stisknuti druheho retezec druhy
http://micro-corner.gilhad.cz/blog/Ardu ... ouse3.html , nebo celorocne ctou, reguluji a zaznamenavaji teplotu v akvarku), ale neni to zase tolik prace navic a je lepsi si zvyknout delat to spravne uz od zacatku, nez se zacit preucovat ve chvili, kdy program presahne 100 radek, nebo ma delat veci dve misto jen jedne