[039] Co to jest shield? cz. 2
Czas oprogramować współpracę z płytką przekaźników, czyli shieldem z poprzedniego artykułu. Będziemy nimi sterować za pomocą pokładowej klawiaturki płytki edukacyjnej TME-EDU-ARD-2. I tu klops: adresy klawiatury to 4, 5, 6, 7, 8 a przekaźników – 4, 5, 6, 7. Mamy zatem konflikt adresów. Nakładkę polutowano na stałe, ale na szczęście na płytce edukacyjnej mam możliwość krosowania portów.
Przerzucę zatem klawiaturę pod adresy: 9, 10, 11 i 12, tam gdzie pierwotnie siedziały ledy, których używać w tym projekcie nie będę. Do tego potrzebne mi będą przewody z gniazdkami na goldpiny. Pora na program. I teraz powiem pewną herezję: delay nie jest zły. Jest nawet bardzo dobry, ale wówczas tylko, gdy nie interesuje nas filozofia i niekończące się dyskusje na peryferiach internetu, a po prostu chcemy zrobić sobie na przykład prosty sterownik akwarium. Akwarium to nie rakieta kosmiczna i takie Arduino naprawdę zdąży tu ze wszystkim.
Nie będę tutaj przedstawiał całego urządzenia, a tylko moduł odpowiedzialny za włączanie takich odbiorników jak na przykład pompka, filtr i dwie lampki. Wiadomą rzeczą jest, że po rozbudowaniu układu o jakiś zegar i sterownik czasowy i tak potrzeba panelu z możliwości ręcznego włączenia i wyłączenia poszczególnych urządzeń. Praktycznie zawsze w takich wypadkach używamy prostej klawiaturki dołączonej do sterownika, a takie klawiaturki mają swoje wady, choćby niestabilne stany podczas ich wciskania. Na temat radzenia sobie z tym pisałem już kiedyś, lecz w takich sytuacjach, gdy zupełnie nie musimy się z niczym spieszyć, istnieje jedna, prosta metoda: po każdym zatwierdzeniu włączenia czy puszczenia przycisku po prostu ignorujemy go, nie zaglądając tam przez jakiś czas. Gdy jest taka potrzeba, można wtedy robić coś innego, ale nie tutaj – toż rybki od tego szybciej pływać nie będą.
const byte opoznienie = 100; // Opóźnienie po wciśnięciu pstryczków.
const byte pstryczek1 = 9; // Port klawiatury.
const byte pstryczek2 = 10;
const byte pstryczek3 = 11;
const byte pstryczek4 = 12;
const byte przekaznik1 = 4; // Port przekaźników.
const byte przekaznik2 = 5;
const byte przekaznik3 = 6;
const byte przekaznik4 = 7;
bool przelacznik1 = false; // Przełączniki.
bool przelacznik2 = false;
bool przelacznik3 = false;
bool przelacznik4 = false;
void setup() {
pinMode(pstryczek1, INPUT_PULLUP); // Deklaruj porty pstryczków jako wejścia podciągnięte wewnętrznie do wysokiego stanu.
pinMode(pstryczek2, INPUT_PULLUP);
pinMode(pstryczek3, INPUT_PULLUP);
pinMode(pstryczek4, INPUT_PULLUP);
pinMode(przekaznik1, OUTPUT); // Deklaruj porty przekaźników jako wyjścia.
pinMode(przekaznik2, OUTPUT);
pinMode(przekaznik3, OUTPUT);
pinMode(przekaznik4, OUTPUT);
}
void loop() {
if (digitalRead(pstryczek1) == HIGH) { // Jeśli wciśnięto pstryczek, to...
przelacznik1 = !przelacznik1; // Zaneguj stan przełącznika,
digitalWrite(przekaznik1, przelacznik1); // Wyślij na przekaźnik jego stan,
delay(opoznienie); // Zaczekaj chwilę,
while (digitalRead(pstryczek1) == HIGH) {} // Czekaj na puszczenie pstryczka,
delay(opoznienie); // Zaczekaj chwilę.
}
if (digitalRead(pstryczek2) == HIGH) {
przelacznik2 = !przelacznik2;
digitalWrite(przekaznik2, przelacznik2);
delay(opoznienie);
while (digitalRead(pstryczek2) == HIGH) {}
delay(opoznienie);
}
if (digitalRead(pstryczek3) == HIGH) {
przelacznik3 = !przelacznik3;
digitalWrite(przekaznik3, przelacznik3);
delay(opoznienie);
while (digitalRead(pstryczek3) == HIGH) {}
delay(opoznienie);
}
if (digitalRead(pstryczek4) == HIGH) {
przelacznik4 = !przelacznik4;
digitalWrite(przekaznik4, przelacznik4);
delay(opoznienie);
while (digitalRead(pstryczek4) == HIGH) {}
delay(opoznienie);
}
}
Przeanalizujmy sobie zatem zasadniczą część programu, bo wstęp jest już chyba zrozumiały dla każdego.
if (digitalRead(pstryczek1) == HIGH) {
przelacznik1 = !przelacznik1;
Po wykryciu wciśnięcia przycisku pstryczek n negujemy wartość jednobitowej zmiennej o nazwie przelacznik n. Ona reprezentuje stan przekaźnika. Skoro tak, to musimy zaraz potem uaktualnić jego stan zgodnie z tą zmienną.
digitalWrite(przekaznik1, przelacznik1);
W tym czasie nasz paluch dopiero co zaczął dociskać przycisk, więc jego stan rzeczywisty jest jeszcze niestabilny. Ale to nic, teraz poczekamy sobie trochę.
delay(opoznienie);
Ustaliłem wcześniej wartość tego czekania na 100 ms – jeszcze niedużo, by czuć było jakieś opóźnienia, a dla stabilności całości wystarczająco w sam raz. Gdy minie ów czas, sprawdzimy, czy paluch nadal będzie dociskać pstryczek. Dopóki tak jest, nic nie zmienimy.
while (digitalRead(pstryczek1) == HIGH) {}
Jeśli jednak docisk zniknie, znowu poczekamy chwilę, by w kolejnym rozdaniu, które nadejdzie bardzo szybko, na wynik nie miały wpływu niestabilności pojawiające się zaraz po zwolnieniu pstryczka.
delay(opoznienie);
Gdy chwila owa minie, można przejść do obsługi następnego przekaźnika i tak do końca, a potem z powrotem na początek pętli. Program jest nieelegancki, do tego ma cztery procedury, które z pewnością można by wrzucić do tablicy, ale po prostu działa i to działa niezawodnie. No właśnie, do pełni niezawodności brakuje tu watchdoga. O tym co to jest i jak tymi przekaźnikami sterować przez telefon, napiszę wkrótce.