Używam Arduino Uno do wysyłania informacji o czasie i napięciu przez port szeregowy do Pythona w celu wykreślenia. Wydaje się jednak, że odstępy czasu między kolejnymi znacznikami czasu z czasem się zwiększają, co wpływa na moje planowanie. Jest to szczególnie prawdziwe, gdy szybkość transmisji jest ustawiona na 9600, gdzie moje początkowe różnice czasowe mogą wynosić 1320 i wzrastają do 16400 po stosunkowo krótkim czasie. Gdy ta szybkość jest ustawiona na maksymalnie 115200 bps, zmiana jest wolniejsza i mniej zauważalna, od około 1340 do 1500 nawet po stosunkowo długim okresie wysyłania. Wszystkie czasy podawane są w mikrosekundach.
Chciałbym wiedzieć, czy mogę zmniejszyć lub wyeliminować ten efekt, a jeśli nie rozumiem, dlaczego on istnieje. Czytałem już o przerwaniach i opóźnieniach powodujących to, ale nie w pełni doceniam złożoność elektroniki i chciałbym wiedzieć:
- Czy mogę uzyskać większą precyzję pomiaru czasu?
- Co powoduje tę zmianę czasu?
Oto, co obecnie mam:
#include <eHealth.h>
extern volatile unsigned long timer0_overflow_count;
float fanalog0;
int analog0;
unsigned long time;
byte serialByte;
void setup() {
Serial.begin(9600);
}
void loop() {
while (Serial.available()>0){
serialByte=Serial.read();
if (serialByte=='S'){
while(1){
fanalog0=eHealth.getECG();
// Use the timer0 => 1 tick every 4 us
time=(timer0_overflow_count << 8) + TCNT0;
// Microseconds conversion.
time=(time*4);
//Print in a file for simulation
//Serial.print(time);
//Serial.print(" ");
Serial.print(fanalog0,5);
Serial.print("\n");
if (Serial.available()>0){
serialByte=Serial.read();
if (serialByte=='F') break;
}
}
}
}
}
źródło
eHealth.getECG()
zrobić? Czy to połączenie zawsze trwa tyle samo?Odpowiedzi:
Użyj timera i ISR (procedura obsługi przerwań), aby zwiększyć dokładność pomiaru czasu.
Spójrz na moje 1ms czasowe przerwanie Proof of Concept . Chodzi o to, aby mieć dość dokładny „puls” 1 ms w systemie, który można wykorzystać do wywołania innych zdarzeń. W PoC służy do mrugania diody LED przy częstotliwości ½Hz, ale ma dostęp do nowych zmiennych
millisecondCounter
isecondCounter
umożliwia wyzwalanie zdarzeń w głównej pętli w dowolnych (ale dokładnie taktowanych) momentach.źródło
loop()
), ta wartość jest modyfikowana przez ISR. Może się zdarzyć, żeloop()
odczyta złą wartość (w trakcie modyfikacji przez ISR). Zamieściłem na Twój temat komentarz na Twoim blogu.loop()
: moja próbka właśnie otrzymała wartość milisekund, porównaj ją z poprzednią wartością odczytu i jeśli różnica> 0 (inna niż zerowanie licznika na 0), wyświetl komunikat.Mogę wymyślić kilka rzeczy, które mogą wpłynąć na „spójność” szeregów czasowych zapisu:
może to być najbardziej oczywista rzecz do przemyślenia, ale w rzeczywistości im więcej drukujesz, tym więcej czasu zajmie ci to.
Rozwiązanie: wydrukuj formatuj ciąg na ciąg o znanej długości.
w systemie Unix można uzyskać dostęp do portu szeregowego w sposób buforowany lub niebuforowany. Używanie buforowanego sposobu przez długi czas może sprawić, że będzie on nieco wolniejszy w miarę zapełniania się bufora, zwykle dzieje się tak, gdy dane przychodzą szybciej niż je czytasz…
Rozwiązanie: użyj niebuforowanej linii szeregowej ( np . : w systemie Darwin / OSX
/dev/cu.usbmodemXXX
zamiast/dev/tty.usbmodemXXX
)wygląda na to, że używasz przerwań TC, a AVR mają priorytety w sposobie obsługi przerwań, nie znam kolejności pierwszeństwa dla Atmega328 i nie jest to jedna z najlepiej udokumentowanych funkcji, więc nie wiem jak bezpieczne jest TC0 w porównaniu z przerwaniem UART.
Rozwiązanie: poszukaj dalej w dokumentacji / arkuszu danych dotyczących priorytetów przerwania i w razie potrzeby zmień licznik czasu; i / lub wykonaj test bez uruchamiania drugiego timera.
niektóre sterowniki muszą uśredniać lub wykonywać pewne operacje w stosunku do poprzednich wartości, więc im więcej wartości zmierzysz, tym dłuższy jest bufor i im dłużej trwa obliczanie wartości, aż do osiągnięcia maksymalnego rozmiaru bufora.
Rozwiązanie: spójrz na kod źródłowy używanej biblioteki i zoptymalizuj go, usuń obliczenia, jeśli takie istnieją, lub weź pod uwagę rosnący czas przetwarzania.
ale jeśli naprawdę chcesz zoptymalizować wyjście szeregowe z arduino, powinieneś unikać korzystania z narzutu arduino… Ale jest o wiele mniej elegancki i wygodny w użyciu.
Jestem prawie pewien, że brakuje mi innych punktów, ale to pierwsze rzeczy, które sprawdziłem przed dalszym kopaniem.
HTH
źródło
Twój kod zawiera czas trwania danych wyjściowych w kolejnych pomiarach. Zatem w zależności od długości wyniku będziesz mierzyć różne czasy. Można to naprawić, formując na wyjście o stałej długości.
Kolejną kwestią jest to, że UNO ma bardzo słabą podstawę czasową. Spójrz tutaj, aby porównać różne typy Arduino z odniesieniem czasowym DCF77.
Wniosek: jeśli potrzebujesz precyzyjnego pomiaru czasu, kup Arduino z kryształem lub wybierz RTC. Mogę bardzo polecić RTC DS3231 / DS3232, ponieważ zazwyczaj osiągają one dokładność 2 ppm po wyjęciu z pudełka.
źródło