Fórum témák
» Több friss téma |
A klónok CH340 Soros-USB illesztőjének drivere (Letöltés)
Bedobtam a gemininek a kódodat. Szerintem próbáld ki te is. Elég lényegre törő megoldási javaslatokat kaptam. A soros port kezelés időzítési hibái és a delay használata okozhat ilyen sleepeket. Ha gondolod mellékelem a teljes választ, de nem akarom feleslegesen szaporítani a szót.
Idézet: „Íme néhány megfigyelés és lehetséges ok a másodperc ugrására, valamint javaslatok a javításra: delay() használata a loop() függvényben: A kód több helyen is használja a delay() függvényt (pl. a pont villogtatásánál, az animációnál, a colorWipe, rainbow stb. függvényekben). A delay() blokkolja a program futását a megadott ideig. Ez azt jelenti, hogy amíg egy delay() lefut, az Arduino nem tudja olvasni az RTC-t vagy frissíteni a kijelzőt. Ha ezek a késleltetések elég hosszúak vagy gyakoriak, az befolyásolhatja az időmérés pontosságát és a másodperc léptetésének ütemét. Javaslat: Próbáld meg elkerülni a hosszú delay() hívásokat a loop() függvényben. Helyette használj nem blokkoló technikákat, például a millis() függvényt az időzítéshez. Így a program továbbra is futhat és rendszeresen ellenőrizheti az időt az RTC-ről, miközben más feladatokat is elvégez. Soros port olvasása (Serial.available() és Serial.readStringUntil()): A soros portról érkező adatok olvasása a loop() függvényben történik. Ha lassan érkeznek az adatok, vagy ha a Serial.readStringUntil() függvény hosszabb ideig vár a befejező karakterre (.), az szintén blokkolhatja a programot, és befolyásolhatja az időzítést. Javaslat: Gondold át, hogy mennyire kritikus az azonnali adatfogadás a soros porton. Ha nem feltétlenül szükséges, hogy minden karakter azonnal feldolgozásra kerüljön, érdemes lehet pufferelni az érkező adatokat, és csak bizonyos időközönként feldolgozni őket, vagy nem blokkoló módon olvasni a soros portot. Neopixel frissítések: A Neopixel LED-ek frissítése is időigényes lehet, különösen ha sok pixel van. Bár a kódban csak 7 pixel van vezérelve csatornánként, a sok show() hívás egymás után (különböző pixelekre) a yaz() és más függvényekben összeadódhat. Javaslat: Minimalizáld a show() hívások számát. Ha több pixel állapotát is megváltoztatod, érdemes lehet az összes változtatást elvégezni, majd egyszerre meghívni a show() függvényt az összes pixel frissítéséhez. GameOfThrones() függvény: Ez a függvény több másodpercig blokkolja a program futását a tone() és delay() hívásokkal. Amíg ez a függvény fut, az idő nem frissül a kijelzőn, és ha a függvény befejeződésekor az RTC éppen átlép egy másodpercet, az ugrásnak tűnhet. Javaslat: Ha a pontos időmegjelenítés kritikus, akkor a GameOfThrones() függvényt is érdemes lehet nem blokkoló módon megvalósítani, vagy ritkábban futtatni, vagy ha fut, akkor is rendszeresen frissíteni a kijelzőn az aktuális időt (bár ez a zenei effektus szempontjából nem biztos, hogy ideális). A másodperc kijelzése: A másodpercet a d4 és d5 változók tárolják, és a yaz() függvény frissíti a kijelzőt. A loop() függvényben az idő lekérdezése (t = rtc.getTime() ![]() Javaslat: Érdemes lehet egy dedikált időzítőt használni a másodperc kijelzésének frissítéséhez. Például a millis() függvény segítségével ellenőrizheted, hogy eltelt-e 1000 milliszekundum az utolsó frissítés óta, és csak akkor frissítsd a d4, d5 változókat és hívd meg a yaz() függvényt. Konkrét lépések a hibakereséshez: Kommenteld ki a delay(500) sort a pont villogtatásánál a loop() elején, és figyeld meg, hogy a másodperc ugrása továbbra is jelentkezik-e. Kommenteld ki a soros porttal kapcsolatos kódrészeket (if(Serial.available()) { ... }) ideiglenesen, hogy kizárd annak hatását. Ha a hiba továbbra is fennáll, próbáld meg a GameOfThrones() függvényt kikommentelni. Adj hozzá soros portra kiíratást a másodpercről a loop() függvényben minden iterációban, hogy lásd, a belső időváltozó (t.sec) ugrik-e, vagy csak a kijelzőn látható a probléma. Például: Serial.println(t.sec);. Ez segíthet eldönteni, hogy az RTC olvasásával vagy a kijelzéssel van-e a gond. Vizsgáld meg a yaz() függvényt. Bár nem tűnik közvetlenül hibásnak az időfrissítés szempontjából, ha más, időigényes műveletek is lennének benne, azok is okozhatnának problémát. A legvalószínűbb ok a sok delay() használata, ami megakadályozza a programot abban, hogy rendszeresen és pontosan olvassa az RTC-t és frissítse a kijelzőt. A nem blokkoló programozási technikák alkalmazása valószínűleg megoldja a problémát. Ha elvégzed a fenti lépéseket és megosztod a tapasztalataidat, tovább tudunk segíteni a hiba pontosabb beazonosításában!”
Belenéztem. Honnan szerezted az alapot? Jó nagy benne a káosz.
Vannak benne NOTE_ konstansok: eredetileg ez zenélt is? De most nem zenél, ugye? Mit kellene csinálnia? Ha nem jön a serialon semmi, akkor két LED villog egyszerre? A loop 322-340. sora erre utal, a look többi része nem aktiválódik sejtésem szerint. Én is a delay-re gyanakszom, delay alapú időzítéssel nem lesz pontos az 1 másodperced hosszú távon. Ha valahonnan vetted a programot, akkor én úgy csinálnám, hogy fordítva indulnék el: egy minimál programból indulnék ki, és onnan építgetném fel a funkciókat, nem egy "kész" programot próbálnék gyúrni. Abból lehet tanulni, ebből nagyon nehéz. Nagyjából ebben a sorredben haladnék: Blinky alap program - a beépített LED-del Egyetlen Adafruit_NeoPixel, ami együtt villog a LED-del delay helyett millis() alapú időzítés, hogy a periódusok fázisa ne mászkáljon időben. a millis alapú időzítés rtc-hez való szinkronizálása A konkrét érték kiírása LED villogtatás helyett RTC beállítás funkció megvalósítása Serial-on keresztül Az alap programodból ki lehet másolni a releváns részeket mindig egyből kipróbálva, és csak azt átemelve, ami valóban kell is. Nem minden a legjobban van megvalósítva, például nem használnék String osztályt az input kezelésére, de nem ez a legfontosabb kérdés, és ha működik akkor tulajdonképpen jó így.
Ebből is látszik, hogy mennyire "használható" az AI.
Csak belekukkantottam a programba, kapcsolási rajz nincs. Ha minden igaz, DS3231 az RTC. Ha annak az 1 Hz-es kimenete nincs használva, akkor soha nem lesz jó, amennyiben másodperc kijelzés is kell. Az RTC és a kontroller soha nem fognak tökéletes szinkronban futni. Akkor kell kiolvasni az időt a DS3231-ből, amikor az jelez, hogy frisstve van (SQW kimenet, lefutó él). Ha a kiolvasási periódus rövidebb a kelleténél, előfordulhat, hogy kétszer ugyan azt az időt olvasod ki. Ha a hosszabb, akkor meg látszólag kimaradnak másodpercek. Nincs mese, az RTC-hez kell szinkronizálni a programot.
Szia!
Én is épp erre gondoltam, mikor olvastam a kódot. Egy katyvasz az egész, de delay()-t használ. Már láttam, hogy ebből gond lehet, főleg serial-al együtt. Egyből a milis() jutott eszembe, azonban ha van RTC akkor annak a kimenete lehet interrupt-ot generáló jel. Ezt kell alapból használni szerintem. A kérdezőnek: -Többen javasolták, hogy lépésről lépésre haladj. Én is ezt tenném. Ha van RTC, akkor elsőként azt nézném meg, hogyan lehet usb-n keresztül beállítani. Utána az RTC-vel másodperces kimenetére interrupt, ami egy LED-et villogtat. -Ezután a megfelelő változókkal az időmérés. -USB-n kijelezném az időt és figyelném. -Ha ez megvan, akkor jöhet a kijelzés. Ha nincs RTC akkor sem delay, sem millis, hanem timer interruptra 1Hz-re beállítva, ami nem lesz pontos az tuti, de jobb, mint a delay.... A timer-t belőném igen pontosra esetleg, azaz a timer kezdeti értékét addig változtatnám, míg a szkópon tökéletes 1Hz nem lenne. De még azt sem. 100Hz-et, vagy nagyobbat állítanék be, és akkor minden 100. interrupt jelentene 1 másodpercet. Így a hiba csökkenthető lenne valamivel. De RTC az igazi.
És nem kell minden esetben az RTC-t lekérdezni, ha van neki 1Hz kimenete. Az elején, a main loop előtt meg lehet tenni természetesen, meg mikor beállításra kerül az RTC. Onnantól az 1Hz bőven elég, mert az Arduino számolja az időt.
De persze lehet tévedek, mert az RTC-n nincs ilyen kimenet. Régen foglalkoztam ilyen RTC-vel. Ha nem így van, akkor bocs.
Oszcilloszkóp pontos időmérésre nem alkalmas. Ha egy 1Mhz-s kvarc téved 10 hz-t az is naponta 1 másodperc hiba. És annak többszörösét sem szúrod ki szemre. Én mikor pontosabb időalap kellett ( és még nem volt tömegével RTC), fogtam egy léptetős (pontos) kvarc órát, és az egyik tekercsvég helyén kijövő jel szintillesztése után egy stabil 0.5hz időalapot kaptam. A következő, kevésbé pontos eszköz, az egy órakvarc egy trimmer potival, és egy osztóval, hogy feldolgozható legyen. Utána a mikrovezérlő saját belső órajele jött, de mivel a megszakítások is néha néha 1-2 órajelet eltolódnak nem igazán kézben tartható, durván pontatlan. ( és a trimmer sem segít rajta.)
Ok, már értem miért nem jó a szkóp erre. RTC kell ide!
![]() Be kell vallanom elsőre nem esett le miért nem jó az oszcilloszkóp ebben az esetben.
Az RTC lekérdezése az emberi felfogóképességhez képest még mindig gyors. Pár ezredmásodperc lekérdezni az RTC szerinti időt. (100kHz a default I2C buszsebesség, és pártíz bit az üzenetváltás mérete.) Tehát még pollozva - folyamatosan kérdezgetve - is lehet használható órát csinálni belőle.
A kijelzést én nem tenném interruptba, mert sokáig tartanak a LED csíkok parancsai, és nem jó olyan sokáig interrupt kontextusban lenni. Persze gondos tervezéssel ez nem feltétlen baj, de egyszerűbb ha nem csinálunk interrupt kontextusból hosszan tartó dolgokat. A hozzászólás módosítva: 8:50
|
Bejelentkezés
Hirdetés |