Warto poczytać: https://www.arduino.cc/en/Reference/AttachInterrupt
oraz zapamiętać:
Płytka |
Piny cyfrowe pod które możemy podpiąć przerwania |
Uno, Nano, Mini, other 328-based |
2, 3 |
Mega, Mega2560, MegaADK |
2, 3, 18, 19, 20, 21 |
Micro, Leonardo, other 32u4-based |
0, 1, 2, 3, 7 |
Zero |
wszystkie, za wyjątkiem 4 |
MKR1000 Rev.1 0 |
0, 1, 4, 5, 6, 7, 8, 9, A1, A2 |
Due |
wszystkie |
oraz ,,zdarzenia”, podczas których uaktywni się funkcja przypisana pod dane przerwanie: LOW, CHANGE, RISING, FALLING (HIGH – tylko płytka Due). Krótko: funkcja „podpięta” do przerwania wywoła się wówczas, gdy na tym pinie (tym = zdefiniowanym podczas attachInterrupt) zajdzie konkretne „zdarzenie”, np. LOW. Oczywiście taka funkcja ma być szybka: ustalenie flagi, sterowanie napięciem na pinach – digitalWrite – ale nie delay(ileś-tam).
Przykład: Arduino + przycisk do błyskania diodą #13. Hardware: przycisk (mikroswicz podłączamy do GND a drugą nóżką do pinu #2 w Arduino).
#define PIN 2
bool stan=false;
void setup() {
pinMode(13, OUTPUT);
digitalWrite(13, 0);
pinMode(PIN, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(PIN), blysk, LOW);
}
void loop() {
delay(10000);
}
void blysk(){
stan=!stan;
digitalWrite(13, stan);
}
Gdy nic nie wiemy o przerwaniach, to przyglądając się funkcji loop() można by powiedzieć, że program NIC NIE ROBI! Tylko czeka 10s, a potem znowu czeka 10s, i tak w kółko… Więc skąd się bierze błyskanie diody #13 w momencie klikania przycisku? Otóż wywołanie delay() zatrzymuje działanie programu, ale przerwania ciągle działają. Skoro więc „podpięliśmy” naszą funkcję (o nazwie blysk()) do przerwania, to właśnie ona się wywoła (gdy stan pinu #2 zmieni się na LOW – to wszystko zostało powiedziane w funkcji setup()). Właśnie taki mechanizm wykorzystałem do wykrycia kolizji przez zderzak naszego pojazdu – pisałem o tym w poprzednim poście. UWAGA: powyższy program działa dość dynamicznie, „nerwowo” reagując na wciśnięcie przycisku – oczywiście jest to zjawisko drgania styków (ang. bouncing), o czym mówiliśmy na naszych poprzednich spotkaniach (tutaj, dla przejrzystości kodu nic z tym nie robię, brak jest debouncing-u).
Dodatkowo: zliczanie obrotów koła.
podłączyliśmy czujnik optyczny odbiciowy TCRT5000 do obudowy silniczka, a następnie wewnątrz koła umieściliśmy białą kartkę z czarną krechą. Czytamy wartości rejestrowane przez czujnik ale nie na Serial monitorze, ale GRAFICZNIE, za pomocą Processinga.
Widzimy wyraźnie moment, gdy czujka mija czarną kreskę. Widać też, że piki zdecydowanie różnią się od „tła”, choć często mają różną wartość w maksimum. Łatwo wykombinować prosty algorytm (czy skuteczny? niedługo się o tym przekonamy) liczący szybkość obrotową koła:
- zapisujemy t1, czyli czas pojawienia się maksimum (funkcja millis())
- czekamy na kolejne maksimum, gdy je złapiemy to
- zapisujemy t2, czyli czas pojawienia się kolejnego maksimum- wówczas różnica czasów t2 i t1 daje właśnie czas jednego, pełnego obrotu.
Pewnie „diabeł tkwi w szczegółach” ale powinno działać. Jak powiedziałem na zajęciach – więcej kresek (ale z umiarem! powiedzmy 4 na początek) powinny zwiększyć rozdzielczość zliczania liczby obrotów koła.
Będziemy to programować na kolejnych zajęciach…