Jen ze zajímavostí jsem měřil přesnost časování Arduina. Je jasné, že pro získání přesného času je nutné použít RTC modul, ale jak to ve skutečnosti funguje s příkazem delay(), nebo s časováním pomocí millis()? Měření jsem prováděl přibližně, jako referenci jsem bral normální počítač.
Článek si můžete prohlédnout na mém webu, konkrétně zde: https://www.mylms.cz/text-presnost-caso ... i-arduina/
Přesnost časování pomocí Arduina
Pravidla fóra
Toto subfórum slouží k řešení obecných otázek kolem programování (konstrukce, knihovny, alokace paměti, ...)
Toto subfórum slouží k řešení obecných otázek kolem programování (konstrukce, knihovny, alokace paměti, ...)
Re: Přesnost časování pomocí Arduina
Můj příspěvek k měření přesnosti časování Arduina.
Pro testy jsem použil čínský klon Arduina Nano s nějakým NONAME rezonátorem.
Fotka: http://www.astromik.org/forum/nano-rezonator.jpg
Vycházím z toho, že procesor očekává jako zdroj základního kmitočtu 16MHz krystal.
Od této frekvence se pak odvíjí veškeré časování.
Když samotný krystal kmitá rychleji (vyšší frekvencí), procesor nemá žádnou možnost zjistit, že frekvence neodpovídá 16MHz, a proto jsou všechny funkce millis() i delay() zrychlené (trvají kratší dobu, než by měly).
Při mojí metodě zkoumání přesnosti časování jsem tedy zkusil přesně změřit kmitočet, na kterém 16MHz krystal opravdu kmitá.
Protože není možné měřit krystal přímo (jakékoliv kapacitní zatížení krystalu hýbe výrazně s frekvencí), napsal jsem program, který tuto základní frekvenci vydělí přesně 256 a pošle ji na samostatný pin (D3)
Je to v podstatě jen klasické nastavení PWM signálu pomocí registrů v ATmega328.
Ideálně bych tedy na pinu D3 očekával frekvenci 16000000 / 256 = 62500 Hz
(číslo 256 je rozlišení PWM střídy)
Frekvenci jsem pak měřil metodou porovnávání dvou frekvencí na osciloskopu (Lissajousovy obrazce).
Teorie například tady: http://vyuka.hradebni.cz/mod/resource/v ... ue&id=9712
Jeden kanál osciloskopu byl zapojen na pin D3 v Arduinu, a druhý byl připojený k velmi přesnému nastavitelnému generátoru.
Nastavováním frekvence generátoru byl hledán stav, kdy se obrazec ustálí.
Čím je rozdíl frekvencí vyšší, tím rychleji se obrazec na osciloskopu pohybuje.
Na přiloženém videu je vidět, že frekvence na pinu D3 je 62536 Hz.
Video: https://youtu.be/CbTdadjba6Y
Když se tato frekvence vynásobí 256, je výsledkem skutečná frekvence krystalu.
62536 * 256 = 16009216 Hz
Rozdíl mezi ideální a skutečnou frekvencí krystalu je tedy "plus" 9216 Hz.
Převedeno na procenta je to odchylka ( 9216 / 16000000 ) * 100 = + 0.0576 %
Pokud by tato chyba byla konstantní (ve skutečnosti je závislá i na teplotě), projevila by se v časovači chybou 1s asi za 29 minut.
Výpočet:
1 / 0.000576 = 1736s = 29 minut
Pro testy jsem použil čínský klon Arduina Nano s nějakým NONAME rezonátorem.
Fotka: http://www.astromik.org/forum/nano-rezonator.jpg
Vycházím z toho, že procesor očekává jako zdroj základního kmitočtu 16MHz krystal.
Od této frekvence se pak odvíjí veškeré časování.
Když samotný krystal kmitá rychleji (vyšší frekvencí), procesor nemá žádnou možnost zjistit, že frekvence neodpovídá 16MHz, a proto jsou všechny funkce millis() i delay() zrychlené (trvají kratší dobu, než by měly).
Při mojí metodě zkoumání přesnosti časování jsem tedy zkusil přesně změřit kmitočet, na kterém 16MHz krystal opravdu kmitá.
Protože není možné měřit krystal přímo (jakékoliv kapacitní zatížení krystalu hýbe výrazně s frekvencí), napsal jsem program, který tuto základní frekvenci vydělí přesně 256 a pošle ji na samostatný pin (D3)
Je to v podstatě jen klasické nastavení PWM signálu pomocí registrů v ATmega328.
Kód: Vybrat vše
void setup(void)
{
pinMode(3,OUTPUT); // pin D3 na vystup
TCCR2A = 0b00100011; // nastaveni PWM: "Clear OC0B on Compare Match" a zaroven "Fast PWM"
TCCR2B = 0b00000001; // prescaler = 1x (frekvence = 16000000/256 = 62.5kHz)
OCR2B = 127; // 50% strida na pinu D3
}
void loop(void)
{
}
Ideálně bych tedy na pinu D3 očekával frekvenci 16000000 / 256 = 62500 Hz
(číslo 256 je rozlišení PWM střídy)
Frekvenci jsem pak měřil metodou porovnávání dvou frekvencí na osciloskopu (Lissajousovy obrazce).
Teorie například tady: http://vyuka.hradebni.cz/mod/resource/v ... ue&id=9712
Jeden kanál osciloskopu byl zapojen na pin D3 v Arduinu, a druhý byl připojený k velmi přesnému nastavitelnému generátoru.
Nastavováním frekvence generátoru byl hledán stav, kdy se obrazec ustálí.
Čím je rozdíl frekvencí vyšší, tím rychleji se obrazec na osciloskopu pohybuje.
Na přiloženém videu je vidět, že frekvence na pinu D3 je 62536 Hz.
Video: https://youtu.be/CbTdadjba6Y
Když se tato frekvence vynásobí 256, je výsledkem skutečná frekvence krystalu.
62536 * 256 = 16009216 Hz
Rozdíl mezi ideální a skutečnou frekvencí krystalu je tedy "plus" 9216 Hz.
Převedeno na procenta je to odchylka ( 9216 / 16000000 ) * 100 = + 0.0576 %
Pokud by tato chyba byla konstantní (ve skutečnosti je závislá i na teplotě), projevila by se v časovači chybou 1s asi za 29 minut.
Výpočet:
1 / 0.000576 = 1736s = 29 minut
Re: Přesnost časování pomocí Arduina
Jak sam pises, problem je v tom, ze krome delay(1000) ten program taky neco dela a cim vic toho dela, tim vic se ti rozchazi ten cas.petan píše: ↑05 bře 2018, 09:17Jen ze zajímavostí jsem měřil přesnost časování Arduina. Je jasné, že pro získání přesného času je nutné použít RTC modul, ale jak to ve skutečnosti funguje s příkazem delay(), nebo s časováním pomocí millis()? Měření jsem prováděl přibližně, jako referenci jsem bral normální počítač.
Článek si můžete prohlédnout na mém webu, konkrétně zde: https://www.mylms.cz/text-presnost-caso ... i-arduina/
Ve skutecnosti potrebujes uplne jiny pristup, kdy sse podivas, kolik je prave ted a kolik bude za 1 sekundu (nebo jak dlouho chces cekat, pak provedes veskerou cinnost, co potrebujes (ty vypisy a tak) a pak uz jen cekas zbytek te doby.
https://www.baldengineer.com/arduino-ho ... illis.html
https://www.baldengineer.com/millis-tutorial.html
Pokud to chces jeste pravidelneji, tak misto
Kód: Vybrat vše
previousMillis = currentMillis;
vhodne pro absolutni casovani a treba nastenne hodiny)
Re: Přesnost časování pomocí Arduina
No, výzkum jsem na to nedělal, ale myslím, že se program bude chovat úplně stejně.
Když si do proměnné uložím čas posledního provedení a pak porovnávám s časem + posune, tak je to podobné jako když si uložím dobu příštího provedení a porovnávám s aktuálním časem.
Rozdíl by mohl být jenom při porovnání aktuálního času s proměnou, do které se přičítá konstanta. A porovnání aktuálního času a již předpřipravené proměnné.
Podobně to jde vidět u mě v programu na grafu. Přesně to koresponduje s tím, co napsal AtroMiK. Krystal má o něco větší frekvenci, takže se Arduino předbíhá. Záleží samozřejmě na stavbě programu (každý příkaz jinak dlouho trvá, lze použít jiný přístup ke kódu, ...)
Když si do proměnné uložím čas posledního provedení a pak porovnávám s časem + posune, tak je to podobné jako když si uložím dobu příštího provedení a porovnávám s aktuálním časem.
Rozdíl by mohl být jenom při porovnání aktuálního času s proměnou, do které se přičítá konstanta. A porovnání aktuálního času a již předpřipravené proměnné.
Podobně to jde vidět u mě v programu na grafu. Přesně to koresponduje s tím, co napsal AtroMiK. Krystal má o něco větší frekvenci, takže se Arduino předbíhá. Záleží samozřejmě na stavbě programu (každý příkaz jinak dlouho trvá, lze použít jiný přístup ke kódu, ...)
Kdo je online
Uživatelé prohlížející si toto fórum: Žádní registrovaní uživatelé a 17 hostů