Licznik czasu impulsów

Masz problem, z którym nie możesz sobie poradzić? Pisz śmiało!
ODPOWIEDZ
cqcx
Młodszy majsterkowicz
Posty: 4
Rejestracja: 19 gru 2013, 12:17

Licznik czasu impulsów

Post autor: cqcx » 19 gru 2013, 12:30

Witam, na początku chciałbym zaznaczyć, że dopiero rozpoczynam swoją przygodę z Arduino więc proszę o wyrozumiałość.
Napisałem kod który zlicza czas pomiędzy impulsami z generatora analogowego:

Kod: Zaznacz cały

unsigned long start, fin, elap;
int st = 0;
int pin = 13;
//long *pin_state = 0;

void setup()
{
  pinMode(pin, INPUT);
  Serial.begin(9600);
  
  start = micros();
}
void loop()
{
   int pin_state = digitalRead(pin);
   
if (pin_state == 1 & st == 0)
{
    fin = micros();
    elap = fin - start;
    start = micros();
    Serial.println(elap);
    st = 1;
      
}
if (pin_state == 0 & st == 1)
{
   st = 0;
}
}
co działa nie najgorzej aż do podkręcenia generatora do około 100Hz wówczas wyniki kreują się na poziomie około 10000us. Pierwsza rzecz którą zauważyłem to taka, że pojawiają się wahania odczytu na poziomie do 16us. Druga rzecz to taka, że po podkręceniu generatora na wyższą częstotliwość wyniki zaczynają się rozbiegać po kilka ms.

Dodatkowo zauważyłem że jakakolwiek zmiana baud rate z 9600 zamienia wyniki w println na śmieci, nie wiem czy to jest normalne gdyż chciałbym takie wyniki wysyłać do komputera przez ten właśnie port w celu dalszej obróbki.

Pytanie czy da się to jakoś zoptymalizować tak aby wyniki były stabilniejsze?

Używam Arduino Uno.

Co miesiąc do wygrania nagrody o wartości ponad 1600 zł!


Awatar użytkownika
wojtekizk
Starszy majsterkowicz
Posty: 311
Rejestracja: 19 lis 2013, 10:54
Lokalizacja: Bydgoszcz

Re: Licznik czasu impulsów

Post autor: wojtekizk » 19 gru 2013, 13:18

Cześć... zacznijmy od tego:

Kod: Zaznacz cały

if (pin_state == 0 & st == 1)
... czy na pewno robisz tu działania iloczynu na bitach czy może ma być warunek AND ?
... bo jeśli ma być AND to w C piszemy podwójny znak &&
po drugie jeśli w Serialu zmieniasz 9600 na inne to także zmień to we właściwościach COMa w Menadżerze Urządzeń.
cqcx
Młodszy majsterkowicz
Posty: 4
Rejestracja: 19 gru 2013, 12:17

Re: Licznik czasu impulsów

Post autor: cqcx » 19 gru 2013, 13:53

Oczywiście w kodzie powinno być && zamiast & (chodzi o AND), zmieniałem ten kod już tyle razy i nie zwróciłem uwagi wklejając go tutaj.

Zmieniłem w ustawieniach COM prędkość na 38400 i w kodzie tak samo i w wynikach pojawia się:

Õ¡ÿ¥¥…¥¥…%¥…¥…%¥%¥¥¥%¥¥…
Awatar użytkownika
wojtekizk
Starszy majsterkowicz
Posty: 311
Rejestracja: 19 lis 2013, 10:54
Lokalizacja: Bydgoszcz

Re: Licznik czasu impulsów

Post autor: wojtekizk » 19 gru 2013, 14:06

daj w loopie delay(tu dowolna wartość od 2-20 np.) czyli delay(10); To jest potrzebne przy serialu niestety. Zobacz czy pomogło.
To tytułem samej poprawności kodu. Teraz moje pytanko? Po co mierzyć czas między impulsami generatora skoro znasz jego częstotliwość, skoro t=1/f ?
W swoim programiku podpinasz generator do pinu cyfrowego i pętli czytasz stan tego wejścia? Przy wzroście f rozbieżność będzie murowana. Mimo że AVR to procki w architekturze RISC to i tak nie będą nadążały :-)
... i jeszcze coś ... na pinie 13 masz "pokładowego" LEDA może lepiej czytać gdzie indziej?
cqcx
Młodszy majsterkowicz
Posty: 4
Rejestracja: 19 gru 2013, 12:17

Re: Licznik czasu impulsów

Post autor: cqcx » 19 gru 2013, 14:33

Niestety wprowadzenie delay nic nie zmieniło, zmieniają się tylko znaki w "śmieciach".

Generator jest tylko wzorcem do pomiarów, będzie to pomiar prędkości elementów wirujących za pomocą tachometru laserowego a dokładniej czas każdego z 500-1000 obrotów (w mikrosekundach). Takie czasy przedstawione na wykresie pokażą stabilność prędkości obrotowej która jest bardzo ważna. Docelowo będzie to pomiar w kilku punktach naraz oraz sprawdzanie rozbieżności pomiędzy nimi. Krótko mówiąc chcę dokładnie zmierzyć czas pomiędzy jednym impulsem HIGH a kolejnym.

Próbowałem pomiarów na innych pinach niestety wyniki są takie same. Zastanawia mnie również dlaczego przy około 200Hz pojawia się tak duża rozbieżność wyników (ok 3ms).
Awatar użytkownika
Maxik
Starszy majsterkowicz
Posty: 405
Rejestracja: 6 lip 2012, 18:27
Lokalizacja: Gdańsk
Kontakt:

Re: Licznik czasu impulsów

Post autor: Maxik » 19 gru 2013, 15:17

Spróbuj z wbudowaną funkcją pulseIn, pozwala ona mierzyć czas trwania impulsu na wybranym pinie, zarówno stanu niskiego, jak i wysokiego: http://arduino.cc/en/Reference/PulseIn
cqcx
Młodszy majsterkowicz
Posty: 4
Rejestracja: 19 gru 2013, 12:17

Re: Licznik czasu impulsów

Post autor: cqcx » 19 gru 2013, 16:21

Wielkie dzięki funkcja pulseIn() działa super, właśnie czegoś takiego szukałem.

Nadal jednak mam problem z przyspieszeniem komunikacji szeregowej powyżej 9600 o ile jest to w ogóle możliwe, ale może okazać się to kluczowe przy przesyłaniu danych z taką częstotliwością. Póki co spróbuję wykorzystać jakiś buffor i przesyłać wyniki w paczkach a później je obrabiać.

Zmieniony kod wygląda tak:

Kod: Zaznacz cały

const int pin = 7;
volatile unsigned long tm;

void setup()
{
  
  Serial.begin(9600);
   
}
void loop()
{
  noInterrupts();
  tm = pulseIn(pin, LOW);
  interrupts();
  
  Serial.println(tm);
  
}
ODPOWIEDZ

Strony partnerskie: