poniedziałek, 15 sierpnia 2016

Arduino biblioteki - cd... obsługa Button

Pierwsze "poważne" programy chodzą  można więc zacząć małe porządki.
Z wrodzonego lenistwa i przyjętej filozofii klocków LEGO dobrze byłoby zastosować gotowe procedury w co najmniej dwu przypadkach
  • sprawdzania klawisza lub ogólniej - zmiany stanu na porcie 
  • odliczania czasu, lub wykonywania procedur w określonych interwałach
Jak zwykle w przypadku Arduino Internet oferuje nam całą gamę bibliotek do wyboru. Coś trzeba wybrać

Biblioteki typu Button

Podstawową funkcją bibliotek obsługującą przyciski jest zabezpieczenie programu przed błędnym odczytem wynikającym z drgań styków.

Program może interpretować wielokrotne naciśnięcie klawisza mimo jednokrotnego jego naciśnięcia. Kiedyś załatwiało się ten problem kondensatorem podpiętym do przycisku lub przerzutnikiem RS. Dziś programowo po pierwszym wykryciu zmiany trzeba odczekać pewien czas (ok 50 ms) aż styki się uspokoją i wtedy odczytać powtórnie stan przycisku. Jeśli jest przeciwny do stanu sprzed pierwszego odczytu przycisk uznaje się za naciśnięty/zwolniony.

Bibliotek typu Button jest naprawdę sporo
Do testów wybralem
  1. Button autor Alexander Brevig 
  2. Button autor Jack Christensen z 2012r
  3. Onebutton autor Matthias Hertel - ostatnia poprawka 2015
  4. Pushbutton - Pololu Corporation. - 2013

 Button autor Alexander Brevig

Opis biblioteki z przykładami tu>>>>>>  ale w przykładach dużo błędów
 
 //Deklaracja dla biblioteki BUTTON.h
#include <Button.h>
Button przycisk = Button(A5, BUTTON_PULLUP_INTERNAL);
//lub z ustawieniem czasu opóźnienia na drganie styków - bez tego domyślnie jest 20 ms
Button przycisk = Button(A5, BUTTON_PULLUP_INTERNAL, true, 50);Zamiast BUTTON_PULLUP_INTERNAL
można deklarować BUTTON_PULLUP ( gdy przycisk przyłączony do GND a zewnętrzny R do Vcc - aktywne zero)
lub BUTTON_PULLDOWN (gdy przycisk do Vcc a zewnętrzny R do GND - aktywne 1)

nazwa "przycisk" to dowolna nazwa funkcji której przypisujemy klasę Button
jeśli chcemy zadeklarować więcej przycisków musimy przypisać kolejne nazwy funkcji np. przycisk1 itd.

podstawowy program reagujący stan bieżący przycisku
void setup(){
  }
void loop(){
  if(przycisk.isPressed()){
    //rób coś gdy naciśnięty
  }else{
    /rób coś gdy nie naciśnięty
  }
}

program reagujący (raz) na zmianę stanu przycisku
void loop(){
  if(przycisk.stateChanged()){
//zrób coś gdy zaszła zmiana z przycisk nienaciśnięty > naciśnięty lub naciśnięty > nienaciśnięty
  }

program reagujący (raz) na naciśnięcie przycisku
void loop(){
  if(przycisk.uniquePress()){
//zrób coś gdy zaszła zmiana z przycisk nienaciśnięty > naciśnięty
  }

program reagujący na naciśnięcie przycisku dłużej niż 1000
void loop(){
  if(przycisk.held(1000)){
//zrób coś gdy przycisk  naciśnięty dłużej niż 1000 ms
  }
ale dla takiego programu
void loop()
{
     if (button.held(2000))
  {
    Serial.println("hold 2000");
  }


Serial.println("przerwa");
   if (button.held(1000))
  {
    Serial.println("hold 1000");
  }
}
  program przy naciśniętym stale przycisku wejdzie tylko w krótszą czasowo if  i tylko raz i nigdy nie wejdzie do if z 2000

program reagujący na naciśnięcie przycisku dłużej niż 1000 i dłużej niż 2000 ms

void loop()
{
   if (button.heldFor(2000))
  {
    Serial.println("hold 2000");
  }
  Serial.println("przerwa");
  delay (200);
   if (button.heldFor(1000))
  {
    Serial.println("hold 1000");
  }
}

program wchodzi do obydwu if po czasie naciśnięcia 1000 lub 2000 ms za każdym razem gdy przycisk jest wciąż naciśnięty

nie bardzo działa mi funkcja  "przycisk.wasPressed()" - muszę jeszcze nad tym popracować
  button.isPressed();
  if (button.stateChanged())
  {
    if (button.wasPressed())
    {
      handleButtonPressEvent();
    }
    else
    {
      Serial.println("release");
      Serial.println("click");
    }
  }
Można też wywoływać cyklicznie funkcję badającą co dzieje się z przyciskiem
void loop(){
  przycisk.process();
}

funkcja to wywoła zadeklarowane podprogramy gdy zajdą następujące zdarzenia

 przycisk.pressHandler(onPress);
wywołaj funkcję onPress() gdy wykryto naciśnięcie przycisku
 przycisk.releaseHandler(onRelease);
wywołaj funkcję onRelease() gdy wykryto zwolnienie przycisku
przycisk.holdHandler(onHold, 1000); 
wywołaj funkcję onHold() gdy wykryto naciśnięcie przycisku dłużej niż1000 ms
przycisk.clickHandler(onClick)
wywołaj funkcję onClick() gdy wykryto naciśnięcie i zwolnienie przycisku

Moim zdaniem funkcja przycisk.wasPressed() powinna dzialać podobnie do przycisk.clickHandler()
a nie działa .

Funkcja przycisk.presses() zwraca liczbę naciśnięć przycisku (nie wiem jak się to resetuje?)
Funkcja przycisk.holdTime() zwraca czas naciskania przycisku

W bibliotece jest jeszcze funkcja
    void setHoldThreshold(unsigned int holdTime);

ale nie wiem co oznacza

Wnioski

Biblioteka wypełnia  potrzeby obsługi przycisku. Jest w miarę przejrzysta i przyjazna do stosowania ale do wyjaśnienia są dwie funkcje. Klasy Button

 Button autor Jack Christensen z 2012r

Opis biblioteki tu>>>>>
Bardzo prosta wręcz uproszczona biblioteka ale praktycznie wyczerpująca potrzeby obsługi przycisku pod warunkiem szybkiej obsługi w pętli głównej procedury
myButton.read();
Procedura ustawia flagi w zależności od zdarzeń generowanych przez przycisk.
Deklaracja klasy

Button(pin, puEnable, invert, dbTime)
 
gdzie pin- oczywiste, puEneble - PULLUP rezystor załączony jeśli wartość true, inwert aktywne 0 jeśli true, dbTime - zwłoka na drgania styków

isPressed() and isReleased()  w konstrukcji   if ( myButton.isPressed ) {zrób}
 
wasPressed() and wasReleased() flagi są ustawiane na podstawie dwu ostatnich odczytów
jeśli się różnią to flaga jest ustawiana odpowiednio

pressedFor(ms) and releasedFor(ms) - ustawiona gdy przycisk był naciśnięty/ zwolniony 
przez xxx ms
 
lastChange() zwraca czas od ostatniej zmiany stanu klawisza
unsigned long lastChange = myButton.lastChange();
 
Wnioski
Bardzo podoba mi się ta biblioteka a wszystkie przykłady działają dobrze

Uwaga - bibliotekę zainstalowałem w katalogu "Arduino\moje projekty\libraries" po uprzednim przeniesieniu z niego drugiej biblioteki Button bo się zakłócały.

 Onebutton autor Matthias Hertel

 Biblioteka do obsługi naciśnięcia, kliknięcia i podwójnego kliknięcia
 na razie sobie odpuszczę


Pushbutton - Pololu Corporation.

 Po przeczytaniu zawartości Pushbutton.h  też sobie odpuszczę nic co by mnie zainteresowało

Tak więc zwycięzcą zostaje najprostsza biblioteka Button.h autorstwa Jack Christensen z 2012r
Zobczymy jak sobie da radę w działaniu

cdn.....

4 komentarze:

  1. hej mam pytanie jako laik....
    mam kod do zmiany kanałów MIDI
    a chciałbym zmieniać UP-jednym switchem, DOWN-drugim...POMOZESZ? ;)
    #include
    #include
    #include
    #include
    #include

    MIDI_CREATE_INSTANCE(HardwareSerial,Serial, midiOut); // create a MIDI object called midiOut

    void setup() {
    Serial.begin(31250); // setup serial for MIDI
    pinMode(8, INPUT_PULLUP); //Przycisk jako wejście
    pinMode(9, INPUT_PULLUP); //Przycisk jako wejście
    }

    void loop()
    {
    if (digitalRead(8) == LOW) { //Jeśli przycisk wciśnięty
    midiOut.sendProgramChange(3, 01); // kanał 4
    delay(500);}

    {
    if (digitalRead(9) == LOW) { //Jeśli przycisk wciśnięty
    midiOut.sendProgramChange(22, 01); // kanał 23
    delay(500);}

    }
    }

    OdpowiedzUsuń
  2. jeśli chodziło ci o coś takiego
    int kanal = 1;
    void loop()
    {
    if (digitalRead(8) == LOW) { //Jeśli przycisk wciśnięty
    kanal++;
    midiOut.sendProgramChange(kanal, 01); // kanał 4
    delay(500);}

    {
    if (digitalRead(9) == LOW) { //Jeśli przycisk wciśnięty
    kanal--;
    midiOut.sendProgramChange(kanal, 01); // kanał 23
    delay(500);}
    }
    }
    jeśli nie - musisz dokładniej wyjaśnić w czym problem

    OdpowiedzUsuń
  3. A czy jest jakaś opcja aby przy tych bibliotekach zamiast pinów arduino urzyć pinów ekspandera PCF8574 ??

    OdpowiedzUsuń