Skocz do zawartości
MS_

Zliczanie obrotów z turbinki w spirometrze z wykrywaniem kierunku obrotu

Pomocna odpowiedź

Napisano (edytowany)

Witam,

mam pytanie odnośnie programu pisanego pod Arduino Uno. Ogólnie moim celem jest zliczanie obrotów małej turbinki znajdującej się w ustniku

od spirometru. Mam układ (z wzmacniaczem operacyjnym w układzie komparatora), który wykorzystuje 2 diody na podczerwień oraz 2 fotodiody

i na wyjściu pod wpływem dmuchania w ustnik i obrotu turbiny podaje 2 przebiegi prostokątne przesunięte w fazie o 90 st. I chciałabym aby na podstawie analizy tych przebiegów, które podam na wejściu arduino był moim licznikiem impulsów, który będzie jednocześnie rozróżniał czy turbina obraca się w prawo czy w lewo (na podstawie tego, jak impulsy są przesunięte względem siebie, czyli który jest pierwszy a który drugi).

Program udało mi się napisać (tzn. kompiluje się), ale na pewno nie jest idealny (jestem raczej początkująca jeśli chodzi o arduino co zapewne widać 

po moim programie ;)). Bardzo zależy mi, żeby zrozumieć i samej poprawić program, jeśli są w nim błędy lub niedociągnięcia.

Byłabym bardzo wdzięczna za wszelkie rady i uwagi!

PS: Starałam się jak najdokładniej przekazać w komentarzach kodu mój tok rozumowania. Jeśli coś jest niejasne lub po prostu zupełnie bezsensownie

zamieszczone, dawajcie znać, będę wyjaśniać, co mną kierowało 😄


 

word steps;         // zmienna zliczająca wszystke impulsy
unsigned long t2;   //czas, w którym został zliczony ostatni narastający impuls podany na pin2
unsigned long t3;   //czas, w którym został zliczony ostatni narastający impuls podany na pin3
boolean state;      // stan opisujący czy dany impuls został już zliczony jako obrót w prawo lub lewo (state = 1) czy                           //jeszcze nie (state = 0)

unsigned long r = 0;  //zmienna zliczająca wszystkie impulsy świadczące o obrocie w prawo
unsigned long l = 0;  // zmienna zliczająca wszystkie impulsy świadczące o obrocie w lewo


void setup() {
  


Serial.begin(115200);
pinMode(2, INPUT_PULLUP);   //pod pin 2 podłączam pierwszy impuls ze wzmacniacza
pinMode(3, INPUT_PULLUP);   //pod pin 3 podłączam drugi impuls ze wzmacniacza

digitalWrite(2,LOW);        //ustawiam początko0wy stan pinu 2 jako LOW
digitalWrite(3,LOW);        //ustawiam początkowy stan pinu 3 jako LOW


attachInterrupt(0, onStep, RISING);     /*przerwanie gdy w pinie 2 (w Arduino Uno pin0) zostanie wykryte zbocze wzrastające                                          sygnału --> przekierowanie do funkcji onStep*/
attachInterrupt(1, onStep2, RISING);    /*przerwanie gdy w pinie 3 (w Arduino Uno pin1) zostanie wykryte zbocze                                                     wzrastające sygnału --> przekierowanie do funkcji onStep2*/

state = 0;   //ustawiam stan początkowy state na 0

}

void loop() 
{
 if ( (digitalRead(3) == HIGH)&& (digitalRead(2) == HIGH)&& (t2<t3) && (state == 0)){     
   
   /*Porównuję kolejność impulsów gdy obydwa są w stanie HIGH. Wtedy sprawdzam czy najpier narosło 
    zbocze impulsu z pinu 2 (wtedy t2<t3) czy z pinu3 (wtedy t2>t3). Jeśli state wynosi 0, co oznacza, 
    że ten obrót w prawo lub lewo nie został jeszcze zliczony, odpowiednio r lub l zostaje zwiększone o 1.
    State wynosi 1 dopóki nie będzie narastał kolejny impuls i wtedy znów otrzyma wartość 0.*/
    r++;
    state = 1;
 }

  if ( (digitalRead(3) == HIGH)&& (digitalRead(2) == HIGH)&& (t2>t3) && (state == 0)){
    l++; 
    state = 1;
 }
 }



void onStep(){                           //ten fragment kodu nie jest mój, zapożyczony z forum           
  static unsigned long lastTime;        //czas, w którym po raz ostatni zarejestrowano impuls
  unsigned long timeNow = millis();     //pobranie obecnego czasu
  if (timeNow - lastTime < 50)         //ochrona przed drganiem styków 
    return;
    
  steps++;
  Serial.println(steps);
  lastTime = timeNow;
  t2 = timeNow;                       //W zmiennej t2 zapisuję informację o czasie ostatniego impulsu podanego na pin2
  state = 0;                          //state zmienia się na 0, co umożliwia zwiększenie zmiennej r lub l
}

void onStep2(){                     //funkcja analogiczna do onStep, ale dla impulsu podanego na pin3. Jedyna różnica to 	                                     //brak steps++, ponieważ podczas 1 obrotu
                                    //powstają dwa sygnały, więc zwiększenie state o 1, odpowiada obecnie 1 obrotowi.

  static unsigned long lastTime2;
  unsigned long timeNow = millis();
  if (timeNow - lastTime2 < 50)
    return;
 
  lastTime2 = timeNow;
  t3 = timeNow;
  state = 0;
}

 

 

Edytowano przez MS_

Udostępnij ten post


Link to post
Share on other sites
(edytowany)

Dzięki wielkie! 🙂 Udało mi się już w miarę stworzyć to, co chciałam. A czy wie ktoś może czy w programie Arduino da się zamienić liczby dziesiętne na binarne, ale w taki sposób, aby nie były jedynie wyświetlane na monitorze jako binarne (tak jak działa funkcja println(wartość, BIN)) tylko, żeby faktycznie podawały na wyjściu liczbę w formacie binarnym? Korzystałam z powyższej funkcji i niestety dane wyjściowe podawał do innego programu w formacie ASCII 😞

Edytowano przez MS_

Udostępnij ten post


Link to post
Share on other sites

Nie bardzo wiem o co Ci chodzi... wewnętrznie wszystkie liczby w Arduino są przechowywane jako binarne, na jakim wyjściu to się ma pokazać (serial?), jaki dokładnie ma być ten binarny format... do pojedynczej 8-bitowej liczby wystarczy Serial.write(liczba), nie trzeba tu nic zamieniać, patrz https://www.arduino.cc/reference/en/language/functions/communication/serial/write

Jeśli mają to być jakieś serie liczb, to musi być jakiś protokół określający co która liczba oznacza.

 

Udostępnij ten post


Link to post
Share on other sites

Ok, wcześniej stosowałam "print" i musiały być w takim razie dziesiętne... Wydaje mi się, że już wszystko rozumiem, bardzo Ci dziękuję!

Udostępnij ten post


Link to post
Share on other sites
2 minuty temu, MS_ napisał:

stosowałam "print" i musiały być w takim razie dziesiętne

po prostu print zamienia wewnętrzną binarną postać liczby na jej dziesiętną (lub szesnastkową, lub dwójkową) reprezentację czytelną dla człowieka. Praktycznie nigdy nie używa się dziesiętnej reprezentacji liczb (z wyjątkiem bardzo specyficznych przypadków, ale tu akurat taki przypadek nie zachodzi).

Udostępnij ten post


Link to post
Share on other sites
(edytowany)
#define PinA 2  
#define PinB 3  

unsigned long time = 0; 

byte num = 0;
byte num2 = 0;


byte S =0;
byte L = 0;

void setup()
{
  Serial.begin(115200);

  pinMode(PinA,INPUT); 
  pinMode(PinB,INPUT); 

  attachInterrupt(0, blinkA, LOW);  
  attachInterrupt(1, blinkB, LOW);  

  time = millis(); 
}

void loop()
{
  while (num != L)
  {
    num = L;
    num2 = S;
    
    Serial.write(num);
    Serial.write(num2);
  }
}

void blinkA()
{ 
  if ((millis() - time) > 3) 
    
        L ++; 
  time = millis();

  if (((millis() - time) > 3) && L==0)
        
        S ++;
  time = millis();

}

void blinkB()
{
  if ((millis() - time) > 3)  
        L--;
    time = millis();

  if (((millis() - time) > 3) && L==255)
        S --;
    time = millis();
}

 

Ciąg dalszy mojej pracy... Jest to licznik, który zlicza kolejne obroty turbiny w ustniku. Chciałabym, aby ilość obrotów była zliczana na dwóch bajtach - starszym (S) i młodszym (L). Młodszy bajt zwiększa się poprawnie - po przeskoczeniu 255 wskakuje znów na 0 (to oczywiście jest ok) natomiast starszy nie zwiększa się (jest cały czas równy nadanej mu wartości początkowej)... Czy ktoś mógłby mnie naprowadzić, co jest nie tak w kodzie? 

Pozdrawiam 🙂

/EDIT: Przed chwilką mnie olśniło, tuż po napisaniu posta, mimo, że siedziałam nad tym kodem naprawdę długo... 😉

Błąd dotyczył pętli blinkA/blinkB z powieloną linijką time=millis(). Aktualnie licznik działa poprawnie, ale jeśli ktoś

z Was dostrzeże w nim jakiś błąd/pomysł na ulepszenie, to oczywiście chętnie przyjmę każdą radę 🙂

 

 

Edytowano przez MS_

Udostępnij ten post


Link to post
Share on other sites

Dołącz do dyskusji, napisz odpowiedź!

Jeśli masz już konto to zaloguj się teraz, aby opublikować wiadomość jako Ty. Możesz też napisać teraz i zarejestrować się później.
Uwaga: wgrywanie zdjęć i załączników dostępne jest po zalogowaniu!

Gość
Dołącz do dyskusji! Kliknij i zacznij pisać...

×   Wklejony jako tekst z formatowaniem.   Przywróć formatowanie

  Dozwolonych jest tylko 75 emoji.

×   Twój link będzie automatycznie osadzony.   Wyświetlać jako link

×   Twoja poprzednia zawartość została przywrócona.   Wyczyść edytor

×   Nie możesz wkleić zdjęć bezpośrednio. Prześlij lub wstaw obrazy z adresu URL.


×
×
  • Utwórz nowe...