Licznik na przerwaniach

Wczoraj zamieściłem wpis “Najszybszy projekt na świecie”, w którym opisałem jak zbudować licznik do orbitreka. Michał poprosił w komentarzach, bym w celach edukacyjnych pokazał jak napisać taki licznik na przerwaniach.

Przerwanie – sygnał z urządzenia peryferyjnego, który powoduje zatrzymanie programu głównego i uruchomienie funkcji obsługującej przerwanie.

W Arduino wejścia przerwań są w pinach cyfrowych 2 i 3. W UNO przerwanie 0 jest w pinie 2, a przerwanie 1 w pinie 3. W Leonardo jest odwrotnie :-.

Do obsługi przerwań służy funkcja “attachInterrupt”

attachInterrupt(int, func, mode);

  • int – numer przerwania 0 lub 1 w zależności od pinu
  • func – nazwa fukcji obsługującej przerwanie
  • mode – ustala kiedy przerwanie ma być wywołane:
    LOW – kiedy na pinie jest stan niski;
    CHANGE – kiedy zmienia się stan;
    RISING – kiedy zmienia się stan z LOW na HIGH;
    FALLING – kiedy zmienia się stan z HIGH na LOW.

Program licznika z użyciem przerwania będzie wyglądał tak:

word steps;

void setup()
{
  Serial.begin(9600);
  pinMode(2, INPUT_PULLUP);
  attachInterrupt(0, onStep, FALLING);
}

void loop()
{
}

void onStep()
{
  static unsigned long lastTime;
  unsigned long timeNow = millis();
  if (timeNow - lastTime < 50)
    return;
    
  steps++;
  Serial.println(steps);
  lastTime = timeNow;
}

Ustawiłem przerwanie nr 0 (pin 2 w UNO). Ma ono wywoływać funkcję “onStep”. Wywołanie nastąpi gdy stan na pinie zmieni się z HIGH na LOW.

Funkcja “onStep” zaczyna się od fragmentu eliminującego drgania styków.
Gdy włącznik (u nas kontaktron) zwiera styki, to przez ułamek sekundy one drgają. Te drgania mogą spowodować, że wywoła się kilka przerwań i funkcja zaliczy kilka kroków.
Dlatego początek sprawia, że pierwsze przerwanie będzie zaliczone, a każde kolejne przez 50 ms zostanie zignorowane jako drgania styków i nie zaliczy kroku.

Liczba kroków przechowywana jest jak poprzednio w zmiennej globalnej “steps”.

W funkcji “loop” możesz napisać dowolny fragment programu. Gdy pojawi się impuls na pinie 2, program w “loop” zostanie przerwany i wykonana zostanie funkcja “onStep”. Po jej zakończeniu program w “loop” zacznie pracę tam gdzie skończył.

Fragment eliminujący drgania styków działa tak:

Zmienna typu static przechowuje wartość nawet po wyjściu z funkcji. Na początku ma wartość 0. Po ponownym uruchomieniu funkcji będzie miała wartość taką, jaka była w niej ostatnio zapisana.
W tej zmiennej (“lastTime”) zapisany jest czas ostatniego wywołania przerwania.

W zmiennej “timeNow” zapisany jest aktualny czas,

Po odjęciu timeNow od lastTime uzyskujemy czas jaki upłynął w milisekundach od ostatniego przerwania.
Jeśli jest on mniejszy niż 50 ms, to wychodzimy z funkcji (return).

Jeśli czas jest większy niż 50 ms, zaliczany jest krok, wysyłany do Monitora portu szeregowego i zapisywany jest nowy czas ostatniego przerwania w zmiennej “lastTime”.

sprae

Leave a Reply

Your email address will not be published.

This site uses Akismet to reduce spam. Learn how your comment data is processed.