Używam Arduino do rejestrowania niektórych danych. W moim szkicu Arduino również użyłem tej millis()
funkcji, dzięki czemu mogę śledzić czas, w którym pobierana jest każda mierzona wartość. Zauważyłem jednak, że czas nie jest prawidłowy. Na przykład 30 sekund w prawdziwym życiu pojawia się tylko jako 10 sekund (wymyślony przykład).
Czy mam rację mówiąc, że funkcja opóźnienia Arduino wpływa na czas używania millis()
? Innymi słowy, załóżmy, że mam opóźnienie 50 ms, czy to oznacza, że millis()
funkcja zatrzymuje się również na ten czas, a następnie trwa i tak dalej na czas połączenia? Zauważyłem to, kiedy próbowałem wykreślić jakieś dane i stwierdziłem, że częstotliwość pików w moich danych była zbyt częsta, biorąc pod uwagę upływający czas. Więc chcę wiedzieć, czy to jest przyczyna tego niedopasowania czasowego, a jeśli tak, to jak to naprawić, aby zachować czas każdej próbki?
Aby podać kontekst, oto mój szkic:
#include <eHealth.h>
unsigned long time;
// The setup routine runs once when you press reset:
void setup() {
Serial.begin(9600);
}
// The loop routine runs over and over again forever:
void loop() {
float ECG = eHealth.getECG();
time = millis();
Serial.print(time);
Serial.print(" ");
Serial.print(ECG, 5);
Serial.println("");
delay(50);
}
źródło
millis()
są oparte na przerwie, więcdelay()
nie powinny na to wpływać.Odpowiedzi:
millis()
jest sterowany przerwaniami, więcdelay()
nie wpłynie na to, przynajmniej nie na płycie ATmega.Nie oznacza to również, że
millis()
jest to całkowicie dokładne. Każdy tyknięcie timera nie jest dokładnie 1 ms, ale 1,024 ms. Ten błąd stopniowo narasta do momentu dokonania korekty. Można to zobaczyć w implementacji procedury obsługi przerwań TIMER0_OVF (timer 0 overflow).Innym źródłem niedokładności jest sam oscylator / kryształ, który nie jest dokładnie 16 MHz. Jest jednak dość blisko i dopóki temperatura nie zmienia się za bardzo, jest względnie stabilna.
Powyższe oznacza, że możesz mieć około 1 miliona czasu podczas używania
millis()
. To nie brzmi jak twój problem.Innym potencjalnym problemem może być to, co
getECG()
się dzieje - może być bardzo powolne.analogRead()
jest wolny, ale nie tak wolny, aby wpływał na taką pętlę.Innym problemem, jaki widziałem, jest to, że ludzie zmieniają częstotliwość zegara, ale nie zmieniają poprawnie board.txt. Oznacza to, że stałe użyte w
millis()
implementacji są niepoprawne, a czasy są nieprawidłowe.Jeśli rzeczywiście chcesz odczytywać wartości co 50 ms, o wiele lepszym sposobem realizacji tego jest wykonanie następujących czynności
Naprawdę musielibyśmy zobaczyć otrzymywane znaczniki czasu. Jeśli faktycznie widzisz 30s jako 10s, oznacza to, że jest coś jeszcze w pracy.
źródło
Jeśli przerwania są wyłączone na jakikolwiek znaczący ułamek
eHealth.getECG()
czasu trwania połączenia,millis()
liczba może pozostać w tyle. W przeciwnym raziemillis()
powinien zwrócić znacznie dokładniejszy czas niż trzykrotnie opisane błędy.Powiedziałeś, że próbkowany sygnał ma wyższą częstotliwość niż się spodziewałeś, co może się zdarzyć, jeśli częstotliwość próbkowania będzie niższa niż zamierzałeś. Czy zakładasz częstotliwość próbkowania 20 Hz? Twoja pętla może zająć nieco więcej niż 50 ms, co można zobaczyć w drukowanych czasach, ale te powinny nadal śledzić czas zegara. Jeśli nie uwzględniłeś tego, ale zakładałeś 50 ms / próbkę, zobaczysz pozorne przyspieszenie danych.
Jeśli to nie jest problem, następnym krokiem byłoby przełączenie wyjścia, gdy jesteś w
loop()
środku, i zmierzenie częstotliwości wynikowej fali prostokątnej za pomocą miernika częstotliwości (niektóre niedrogie DVM mogą to zrobić) lub zakresu. Zrób to samo z pustymloop()
. Pierwszy eksperyment będzie twoją rzeczywistą częstotliwością próbkowania lub interwałem; drugi powie ci, czymillis()
(tj. częstotliwość timera0) jest taka, jakiej się spodziewałeś.źródło
To samo tutaj. Mogę dodać, że jeśli przerwy są wyłączone, mierzony czas to „czas rzeczywisty”. W każdym razie nie rozumiem, dlaczego to opóźnienie, ponieważ jeśli pętla trwa zbyt długo, i tak millis () powinna zwracać wartości w czasie rzeczywistym (tylko z większą odległością między każdą wartością)
źródło