Pavouk Hiwonder

Nedaří se vám s projektem a nenašli jste vhodné místo, kde se zeptat? Napište sem.
Pravidla fóra
Tohle subfórum je určeno pro konzultaci ucelených nápadů, popřípadě řešení komplexnějších projektů, které opravdu není možné rozdělit na menší části.
Většinu problémů jde rozdělit na menší a ptát se na ně v konkrétních subfórech.
Odpovědět
luger
Příspěvky: 146
Registrován: 30 dub 2023, 11:06
Reputation: 0

Re: Pavouk Hiwonder

Příspěvek od luger » 14 bře 2024, 09:48

Díky gilhad, takto teoreticky to chápu, ale myslel jsem si, že díky této funkci se neustále kontrolují vnitřní hodiny a nezávisle běží další program a neustále se hodiny kontrolují. Takže běží "něco" ale jakmile se dosáhne nějakého daného času (millis+300) tak se zkontroluje příslušná podmínka. To je snad podstata funkce millis. Nebo ne ?

Uživatelský avatar
Diego
Příspěvky: 169
Registrován: 23 črc 2017, 09:43
Reputation: 0
Kontaktovat uživatele:

Re: Pavouk Hiwonder

Příspěvek od Diego » 14 bře 2024, 15:32

Podminka se ti sama nezkontroluje. Musis ji pravidelne testovat aby si zjistil kdy mas provest dany podprogram. Millis ti pouze rekne kolik ubehlo casu, ale musis se ji sam zeptat a sam si otestovat podminky.
https://arze.cz - ARduino Zapojení Elektronika

luger
Příspěvky: 146
Registrován: 30 dub 2023, 11:06
Reputation: 0

Re: Pavouk Hiwonder

Příspěvek od luger » 14 bře 2024, 17:03

stejně jsem z toho magor :( už jen to "vrací počet milisekund" - jak vrací ? co vrací ? tzn. že se čas odčítá ? To nejde nějak vyjádřit normálně česky ?

Uživatelský avatar
gilhad
Příspěvky: 788
Registrován: 07 bře 2018, 11:22
Reputation: 0

Re: Pavouk Hiwonder

Příspěvek od gilhad » 14 bře 2024, 21:07

říká se, že funkce při zavolání vrací nějakou hodnotu, znamená to, že když tu funkci zavoláš, tak se něco někde nějak spočítá a pozjišťuje a až ta funkce skončí, tak se ta pozjišťovaná hodnota použije v tom výrazu, kde je to volání té funkce.

Například když si nastavíš D8 pin jako vstupní s pullupem a dáš na něj tlačítko proti zemi (běžné zapojení tlačítek), tak pokud to tlačítko nebude zmáčknuté, tak ti digitalRead(8) vrátí HIGH, protože na pinu 8 je 5V. V programu to vypadá nějak takhle

if ( digitalRead(8) == HIGH ) {
// dělej co je potřeba při nezmáčknutém tlačítku
};

Zatímco pokud bys to tláčítko zmáčknul a držel a výpočet tam mezitím doběhnul, tak funkce digitalRead zjistí, že je na tlačítku 0V a tak by vrátila LOW a protože LOW není HIGH, tak by se ty věci v podmíněné části neprováděly.

----

Kdesi uvnitř v Arduinu je cosi, co každou milisekundu přičte jedničku k hodnotě nějaké vnitřní proměnné. (Je to HW časovač a SW interrupt, ale to je fuk.)
Kdykoli zavoláš funkci millis, tak ti vrátí hodnotu této proměnné. (Podobně jako ti třeba digitalRead(8) vrátí hodnotu na pinu 8, jestli je HIGH nebo LOW.)
Jinými slovy, pokud je v programu napsané například

timer=millis();

a výpočet se na tu řádku dostane 17 milisekund po zapnutí Arduina, tak volání millis() vrátí hodnotu 17 a ta se uloží do proměnné timer.

Pokud někde bude napsáno, jako v tom tvojem příkladu,

timer = millis() + 500;

a výpočet na to místo přijde třeba 123 milisekund po spuštění Arduina, tak se do proměnné timer vloží 123+500, tedy 623, bez ohledu co v ní bylo předtím.

Pokud se o 100 milisekund později dostaneš na začátek loop(), a pocitadlo je zrovna nula, tak nevoláš PIR() - protože nula není >=5 - a skočíš do funkce sonar().
Tam narazíš na řádku

if (timer > millis()) return;

Jelikož timer je 623 a millis() je zrovna 223 (o 100 víc než těch 123 z předchozího příkladu), tak je timer větší, vrátíš se do loop(), tam už nic víc není, takže loop() skončí, Arduino si provede nějaké svoje zákulisní čachry (a dejme tomu, že mu zaberou celou milisekundu) a spustí loop() znovu.

pocitadlo se nezměnilo, takže se PIR() opět nevolá, sonar() se znovu volá a teď porovnáváš 623 s hodnotou 224 a pořád je to větší, tak se ze sonar zase vyskočí, loop skončí, Arduino si udělá zákulisní čachry a znovu zavolá loop.

Pokud mu ty čachry budou trvat pokaždé milisekundu, tak se to bude dít stále dokola, jen se millis() bude pokaždé zvětšovat o jedna a tak budeš těch 623 postupně porovnávat s 225, 226, 227 ... 622 a bude se to jen naprázdno točit dokola. (Pokud by ty čachry proběhly někdy rychleji, tak to holt proběhne víckrát se stejnou hodnotou millis().)

Až se po nějaké době marného snažení stane, že millis() vrátí těch kýžených 623 a nebo víc (asi tak po 623 milisekundách od startu ) a tak se ze sonar nevyskočí hned na začátku, ale budou se postupně vykonávat další řádky.

Takže se možná nastaví timer na další hodnotu, možná se i nastaví pocitadlo ...

Uživatelský avatar
kiRRow
Příspěvky: 1170
Registrován: 07 kvě 2019, 07:03
Reputation: 0
Bydliště: Opava

Re: Pavouk Hiwonder

Příspěvek od kiRRow » 15 bře 2024, 15:36

jednoduše ... hned na začátku loopu si ulož millis() do proměnné a veškeré další volání millis() nahraď tou proměnnou
unsigned long currentMillis;
loop(){
currentMillis = millis();
...
timer = currentMillis + 500;
...
if (timer > currentMillis) return;

luger
Příspěvky: 146
Registrován: 30 dub 2023, 11:06
Reputation: 0

Re: Pavouk Hiwonder

Příspěvek od luger » 15 bře 2024, 20:46

Díky pánové, pomalu se do toho dostávám. Abych mé dotazy vysvětlil - uvedený program je originál firemní pro tohoto pavouka, jen jsem ho doplnil o kontrolu PIR a počítání kroků a některé další drobné úpravy. V těch podmínkách se skáče sem a tam a pořád se vrací časy a jsem z toho jelen takže prozatím to tak nechám. Jen jsem chtěl pochopit logiku proč tvůrce použil právě tuto metodu.
Trochu odbočím od programování. Dnes jsem nainstaloval novou lipol baterku 4200 mA (původní měla jen 2200 mA) takže jsem musel předělat kabeláž napájení. Taky se mi, zatím provizorně, podařilo vyřešit zakrytování a uchycení ESP32 CAM , využívám to jen jako kameru s wifi přenosem obrazu do mobilu nebo PC. Ještě tam musím doplnit přísvit.

peterple
Příspěvky: 156
Registrován: 22 zář 2021, 20:20
Reputation: 0

Re: Pavouk Hiwonder

Příspěvek od peterple » 16 bře 2024, 07:53

Tak ako to napísal kiRRow, tak to nerob. Je tam chyba ako hrom.
Najprv čo je chybne. Majme tento kód

Kód: Vybrat vše

unsigned long currentMillis;
loop(){
currentMillis = millis();
...
timer = currentMillis + 500;
...
if (timer > currentMillis) return;
...	toto by sa malo vykonať raz za 500ms ale vykoná sa opakovane po dobu 300ms raz za 47 dní.
V tomto kóde sa vždy vrátiš späť a iba raz za 47 dní budeš asi 300ms vykonávať to čo sa bude nachádzať za tým testom if. A teraz že preco?
Tak ako to je napísané do currentMillis dáš vždy na začiatku aktuálny čas v milisekundách. Potom k nemu pripočítaš 500. To znamená že
timer je vždy viacej ako currentMillis a teda sa vždy vrátiš späť a ten kód za testom sa zdá že sa nikdy nevykoná.

Ale on sa vykoná. Predstavme si že ubehlo 4 294 967 000ms. Ak teraz k tomu číslu pripočítame 500 výsledok bude 204. To preto lebo premenné sú unsigned int a tie majú v arduino architektúre 32 bitov. Pripočítaním hodnoty 500 dôjde k pretečeniu. Práve od tohoto okamihu teda podmienka už splnená nie je (204 je menšie ako 4 294 967 000) a preto sa návrat nekoná a preto sa ten kód za if vykoná. A bude sa vykonávať znova znova pretože loop sa volá znova a znova. Ak čas pokročí o 1 ms na 4 294 967 001 tak situácia je stále rovnaká. Opäť dojde k pretečeniu a opäť sa ten kód vykonáva znova a znova. Takto to bude až pokým čas nedoplynie k hodnote 4 294 967 295. Tam sa ten fenomén pretečenia ešte samozrejme prejaví, ale následne aj funkcii millis pretečie počítadlo milisekund na hodnotu 0 a ďalších 47 dní sa nebude nič diať.

Samozrejeme oprava sa zdá byť jednoduchá len si dajte pozor aby to nedopadlo chybne práve na konci toho meraného intervalu. Internet je plný kódov ako robiť s millis, asi tak polovica to má zle, tak bacha na to. Napríklad gilhad to robí podľa tej prvej polovice (teda chybne)

Uživatelský avatar
gilhad
Příspěvky: 788
Registrován: 07 bře 2018, 11:22
Reputation: 0

Re: Pavouk Hiwonder

Příspěvek od gilhad » 16 bře 2024, 10:49

Gilhad to ve svých programech používá správně, ve tvaru

Kód: Vybrat vše

 if (currentMillis - previousMillis >= interval) {
podle https://docs.arduino.cc/built-in-exampl ... houtDelay/, https://www.gammon.com.au/millis a dalších

Ale když vysvětluje, jak funguje nějaký program, tak ukázky cituje z toho komentovaného programu, nikoli z toho, jak by to psal on, kdyby to snad někdy psal (zcela jinak) :twisted:

luger
Příspěvky: 146
Registrován: 30 dub 2023, 11:06
Reputation: 0

Re: Pavouk Hiwonder

Příspěvek od luger » 16 bře 2024, 11:30

Vstoupím do diskuze. Gilhad by to napsal jinak? To mě zajímá. Samozřejmě co se týče pavouka protože to můžu okamžitě odzkoušet.
Jestli jsem to správně pochopil tak ta funkce millis se tam používá proto aby se každý určitý čas kontrolovala daná podmínka. Nešlo by to třeba jednodušeji ? Servo controler přece jede nezávisle na běhu programu dokud mu nedám další příkaz. Mé první autonomní vozítko jezdí skvěle a perfektně reaguje na všechny možné podněty a žádný millis nepoužívám - viz : https://www.youtube.com/watch?v=-3IDsoFa1ME

Uživatelský avatar
kiRRow
Příspěvky: 1170
Registrován: 07 kvě 2019, 07:03
Reputation: 0
Bydliště: Opava

Re: Pavouk Hiwonder

Příspěvek od kiRRow » 16 bře 2024, 13:14

Pán má samozřejmě pravdu, ale tento problém se projeví až když bude pavouk více jak měsíc nepřetržitě zapnutý a jen občas. Protože i když přeteče timer, tak nakonec přeteče i millis() a po několika cyklech se to srovná, ale škobrtne to ...

Při programování, hlavně když se člověk učí, nebo jen něco testuje, je až skoro na škodu psát rovnou totálně optimalizovaný kód. Tohle je "nemoc" programátorů...
Takže má cenu teď řešit něco, co nastane za 30++ dní, když mám problémy s tím co se děje právě teď ?

Odpovědět

Kdo je online

Uživatelé prohlížející si toto fórum: Žádní registrovaní uživatelé a 47 hostů