poniedziałek, 18 września 2017

Biblioteki BUTTON raz jeszcze

Znalezione obrazy dla zapytania przycisk"Tyle wiesz ile sprawdzisz w praktyce" Trawestując nieco słowa W. Szymborskiej (nie przypuszczałem, że takie postacie będą wspominane na tym blogu) muszę mocno zmienić swoje wcześniej wyrażone opinie. Dotyczą one bibliotek typu BUTTON omawianych dawno temu. Niestety zwyczajnie się pomyliłem i muszę swoich faworytów wrzucić do kosza. Obsługa przycisków w pętli głównej jest nieporozumieniem. Tylko przerwanie lub  pooling. Ja wybieram pooling ze względu na kompatybilność z innym głównymi bibliotekami w moich projektach - BLYNKiem i TIMERSem. Dziś więc o możliwościach i zastosowaniu biblioteki OneBUTTON
Praca na grzybosuszarką nieco się opóźnia a tu zaraz sezon na podgrzybki. Trudno. Musiałem rozwiązać najpierw dwa ujawnione problemy - zawieszanie się biblioteki BLYNK przy braku połączenia z serwerem i fatalne działanie standardowej biblioteki BUTTON.
Pierwszy problem był poważny - utrata sieci lub niedostępność serwera BLYNK praktycznie unieruchamiała mi program grzybosuszarki. Pal sześć gdy nie mogłem jej przez to uruchomić. Ale potrafiła mi się zawiesić w stanie "grzania" i nic poza resetem nie mogło jej z tego stanu wyprowadzić. Na końcu wpisu będzie link do mojej wydzielonej biblioteki BLYNK nie wstrzymującej obiegu pętli głównej programu. Szczegóły rozwiązania  powyższego problemu będą opisane na portalu BLYNK.pl.

Tu zaś poznęcamy się nieco nad bibliotekami BUTTON które pomogą mi w łatwiejszym sterowaniu grzybosuszarką dysponującą tylko jednym fizycznym przyciskiem SONOFFa.
Przyzwyczaiłem się do przyjazności bibliotek działających w poolingu a dokładniej bibliotek używających procedur typu Callback function types.
Na czym polega cały myk takich procedur.
Kiedy chcemy wywołać funkcje zależne od zmiennej (gdy x=0 > wywołanie funkcji0() gdy x=1 to wywołanie funkcji1()) najczęściej stosujemy rozgałęzienie if lub case

 if (x == 0)
  funkcja0 ();
else if (x == 1)
  funkcja1 ();
else if itd.......

switch (x)
  {
  case 0: funkcja0 (); break;
  case 1: funkcja1 (); break;
  ........ itd
  }

a pięknie byłoby to zrobić coś jakby tak

funkcja'x' ();

Piękne i proste ale ..... nie działa.
Wymyślono więc Callback function types ze użyciem wskaźników. Kiedyś wrócimy do tego tematu bo znakomicie upraszcza wywołanie funkcji i zwiększa czytelność programu

To bardzo wygodna i przejrzysta forma zarządzania funkcjami. Jak to działa? Główną procedurę biblioteki umieszcza się w pętli loop(). Kontroluje ona wszelkie funkcje biblioteki a w momencie wstąpienia zdarzenia określonego przez użytkownika sama wywołuje zdefiniowaną w setup() procedurę. To ciekawa metoda zdejmująca z programisty konieczność śledzenia zdarzeń i określania zachowania programu po ich wystąpieniach. W początkowym okresie nauki programowania istnieje naturalna tendencja umieszczania całego programu w pętli głównej z użyciem if lub case. Z czasem przyjazność mechanizmu poolingu sprawia, w procedurze loop() znajduje się tylko kilka odwołań do głównych funkcji programu powiązanych ze zdarzeniami (pojawienie się sygnałów na wejściach procesora, zdarzenia czasowe itd.). Cały program jest natomiast rozproszony po procedurach obsługi zdarzeń.
Przy małych programach pierwszy sposób programowania wydaje się prostszy ale większe łatwiej daje się opanować drugą metodą. Nie dotykałem jeszcze trzeciego sposobu programowania z użyciem przerwań - jest to sprzętowa odmiana poolingu gdzie program obsługi zdarzenia jest wywoływany przez sam mikroprocesor a nie kod programu. To bardzo szybki sposób obsługi zdarzeń ale wymagający sporych umiejętności programowania i bardzo trudny do analizy w przypadku wystąpienia błędów w programie.
Pozostaniemy więc na razie przy poolingu.
Generalna struktura programów z poolingiem wygląda mniej więcej tak


deklaracja > nasza.procedura 
setup(){
deklaracja > nasza.procedura.zdarzenie_1(program_obsługi_zdarzenia_1)
deklaracja > nasza.procedura.zdarzenie_2(program_obsługi_zdarzenia_2)
.............
}
loop()
{
pooling > nasza.procedura
}
void program_obsługi_zdarzenia_1()
{............}
void program_obsługi_zdarzenia_2()
{............}

Wracając do bibliotek typu BUTTON znalazłem kilka

Nie ma tego dużo ale od razu spodobała mi się pierwsza biblioteka OneBUTTON i nią przeanalizujemy dokładniej. Na stronie autora jest pięknie opisana cała procedura . Biblioteka jest bardzo prosta i obsługuje zasadniczo trzy zdarzenia

  • click()
  • dubleclick()
  • press()  - długie naciśnięcie
Deklaracja wstępna

#include "OneButton.h"  // gdy biblioteka zainstalowana w katalogu /libraries z projektami
OneButton mybutton1(pin, activelow); //mybutton1 - nazwa przypisana dla przycisku nr 1 pin -port mikroprocesora activelow - true/false odwrócona logika przycisku 0 = naciśnięty

Dowiązanie procedur obsługi zdarzeń do typów zdarzeń

setup()
{
mybutton1.attachClick(osluga_click1); //deklaracja wywołania programu gdy click
mybutton1.attachDoubleClick(obsluga_doubleclick1); // gdy dubleclick
mybutton1.attachLongPressStart(obsluga_longPressStart1); //gdy naciśnięto przycisk długo
mybutton1.attachLongPressStop(obsluga_longPressStop1); //gdy zwolniono przycisk długo
mybutton1.attachDuringLongPress(obsluga_longPress1); //wywoływana za każdym obrotem pętli loop() gdy trzymany jest przycisk w stanie ON
}

Program główny

loop()
{
mybutton1.tick();
}

Deklaracje procedur obsługi zdarzeń poza pętlami setup() i loop()
void obsluga_click1() { ...........}
void obsluga_dubleclick1() { ...........}
.........
void obsluga_longPress1() {..........}

Dodatkowo jest możliwość zmiany ustawień domyślnych biblioteki

setup()
{
mybutton1.setDebounceTicks(80); // opóźnienie na drganie styków domyśle 50 msek
mybutton1.setClickTicks(400) // opóźnienie po którym jest click domyślne 600 msek
mybutton1.setPressTicks(2000)//  opóźnienie dla długiego naciśniecia domyślne 1000 msek
}

Jest jeszcze procedura isLongPressed(), która zwraca 1 gdy jest długie naciśnięcie klawisza.
To na razie tyle o biblotece OneBUTTON.

I tą biblioteką zabawimy się przy grzybosuszarce więc cd powinien jednak nastąpić.

98

Brak komentarzy:

Publikowanie komentarza