środa, 2 listopada 2016

[28] Arduino - Klawiatura membranowa

Ten post chciałbym poświęcić na przygotowanie programu obsługującego klawiaturę membranową w formacie 4x4, która posiada 16 klawiszy. Jej wygląd przedstawiłem poniżej na rysunku 1. 

Rys. 1. Klawiatura matrycowa [elektroda.pl]

Poniżej przedstawię programy, które zostały oparte o bibliotekę Keypad.

Jeśli chodzi o podłączenie to wiersze są podpięte do pinów 2, 3, 4, 5 natomiast kolumny do pinów 6,  7, 8, 9.

Sama obsługa jest w zasadzie dosyć prosta, skanuje się kolumny bądź linie w poszukiwaniu stanu wysokiego. Gdy zostanie on znaleziony, przeszukiwane są znowu kolumny lub wiersze, w zależności co było pierwsze. Gdy zostanie wykryty stan wysoki to wciśnięty jest przycisk na przecięciu obu linii.

Program biblioteka Keypad


Na samym początku należy zdeklarować ilość wierszy oraz kolumn:

  1. #include <Keypad.h>
  2. const byte Wiersze = 4;
  3. const byte Kolumny = 4;
  4. byte Piny_Wiersze[Wiersze] = {2, 3, 4, 5};
  5. byte Piny_Kolumny[Kolumny] = {6, 7, 8, 9};

Kolejnym etapem jest odpowiednie zmapowanie klawiszy, dla przesyłania ich prze UART;

  1. char keys[Wiersze][Kolumny] = { {'1','2','3','A'},
  2.                                 {'4','5','6','B'},
  3.                                 {'7','8','9','C'},
  4.                                 {'*','0','#','D'}   };

Teraz kolejnym elementem jest włączenie biblioteki poprzez odpowiednie zainicjalizowanie zmiennej strukturalnej przygotowanymi danymi:

Keypad Membran_Klaw = Keypad( makeKeymap(keys), Piny_Wiersze, Piny_Kolumny, Wiersze, Kolumny );

Dalsza część programu zależy głównie od naszej wyobraźni i tego co finalnie chcemy przekazać. Ja przygotuje dwa różne programy jeden z nich będzie wyświetlał to co aktualnie zostało kliknięte. Drugi natomiast będzie oczekiwał na serię znaków zakończonych #. Jeśli będzie ona poprawna to nastąpi "odblokowanie" zamka. Czyli prosty zamek z szyfrem:

Pierwszy program jak już wspomniałem wcześniej będzie miał za zadanie wyświetlanie znaków oraz zliczania ilości wciśniętych klawiszy:

  1. uint16_t Licznik_Wcis = 0;
  2. void setup()
  3. {
  4.   Serial.begin(9600); //Transmisja po uarcie
  5. }
  6. void loop()
  7. {
  8.   char jaki_klawisz = Membran_Klaw.getKey();
  9.   if (jaki_klawisz)
  10.   {
  11.     Licznik_Wcis++;
  12.     Serial.println("Klawisz: ");
  13.     Serial.println(jaki_klawisz);
  14.     Serial.print("Wcisniecie numer: ");
  15.     Serial.println(Licznik_Wcis);
  16.   }
  17. }

Do tego programu można jeszcze dołożyć buzzer, sterowany albo bezpośrednio z nogi, lub z tranzystora. Ja podłączyłem buzzer pod pin 10, który jest sterowany sygnałem PWM. Po kliknięciu wywoływany jest na nim dźwięk. Co pozwala na dużo łatwiejszą identyfikacje czy dany klawisz został rzeczywiście wciśnięty.

  1. #include <Keypad.h>
  2. const byte Wiersze = 4;
  3. const byte Kolumny = 4;
  4. byte Piny_Wiersze[Wiersze] = {2, 3, 4, 5};
  5. byte Piny_Kolumny[Kolumny] = {6, 7, 8, 9};
  6. char keys[Wiersze][Kolumny] = { {'1','2','3','A'},
  7.                                 {'4','5','6','B'},
  8.                                 {'7','8','9','C'},
  9.                                 {'*','0','#','D'}   };
  10. Keypad Membran_Klaw = Keypad( makeKeymap(keys), Piny_Wiersze, Piny_Kolumny, Wiersze, Kolumny );
  11. uint16_t Licznik_Wcis = 0;
  12. void setup()
  13. {
  14.   Serial.begin(9600); //Transmisja po uarcie
  15.   pinMode(10, OUTPUT); //10 jako wyjście do generowania PWM
  16. }
  17. void loop()
  18. {
  19.   char jaki_klawisz = Membran_Klaw.getKey();
  20.   if (jaki_klawisz)
  21.   {
  22.     analogWrite(10, 184);
  23.     delay(200);
  24.     analogWrite(10, 0);
  25.     Licznik_Wcis++;
  26.     Serial.print(jaki_klawisz);
  27.     Serial.print(" ");
  28.     Serial.print("Wcisniecie numer: ");
  29.     Serial.println(Licznik_Wcis);
  30.   }
  31. }

Program numer dwa ma część główną niezmienną, Poniżej przedstawię część z funkcją setup oraz pętlą loop wraz z odpowiednio przygotowaną funkcją sprawdzającą wynik:

W tym programie wpisywanie należy rozpocząć od przyciśnięcia klawisza #. Następnie podawany jest kod składający się z czterech cyfr pomieszanych ze znakami (kod: 83C1). Po jego wpisaniu odpowiednio zdefiniowana akcja zostaje wywołana. W moim przypadku będzie to wyświetlanie napisu Otwarte oraz pojedyncze pipnięcie buzzera. 

  1. #include <Keypad.h>
  2. const byte Wiersze = 4;
  3. const byte Kolumny = 4;
  4. byte Piny_Wiersze[Wiersze] = {2, 3, 4, 5};
  5. byte Piny_Kolumny[Kolumny] = {6, 7, 8, 9};
  6. char keys[Wiersze][Kolumny] = { {'1','2','3','A'},
  7.                                 {'4','5','6','B'},
  8.                                 {'7','8','9','C'},
  9.                                 {'*','0','#','D'}   };
  10. Keypad Membran_Klaw = Keypad( makeKeymap(keys), Piny_Wiersze, Piny_Kolumny, Wiersze, Kolumny );
  11. uint16_t Licznik_Wcis = 0;
  12. uint8_t Licznik_do_kodu = 0;
  13. uint8_t Zle_Wcisniecia = 0;
  14. const char Pin1 = '8';
  15. const char Pin2 = '3';
  16. const char Pin3 = 'C';
  17. const char Pin4 = '1';
  18. void setup()
  19. {
  20.   Serial.begin(9600); //Transmisja po uarcie
  21.   pinMode(10, OUTPUT); //10 jako wyjście do generowania PWM
  22. }
  23. void loop()
  24. {
  25.   char jaki_klawisz = Membran_Klaw.getKey();
  26.   if (jaki_klawisz)
  27.   {
  28.     if(Licznik_do_kodu == 0 && jaki_klawisz == '#')
  29.     {
  30.       Serial.println(Licznik_do_kodu);
  31.       Licznik_do_kodu++;
  32.     }
  33.     else if(Licznik_do_kodu == 1 && jaki_klawisz == Pin1)
  34.     {
  35.       Serial.println(Licznik_do_kodu);
  36.       Licznik_do_kodu++;
  37.     }
  38.     else if(Licznik_do_kodu == 2 && jaki_klawisz == Pin2)
  39.     {
  40.       Serial.println(Licznik_do_kodu);
  41.       Licznik_do_kodu++;
  42.     }
  43.     else if(Licznik_do_kodu == 3 && jaki_klawisz == Pin3)
  44.     {
  45.       Serial.println(Licznik_do_kodu);
  46.       Licznik_do_kodu++;
  47.     }
  48.     else if(Licznik_do_kodu == 4 && jaki_klawisz == Pin4)
  49.     {
  50.       Serial.println(Licznik_do_kodu);
  51.       Licznik_do_kodu++;
  52.       if(Licznik_do_kodu == 5)
  53.       {
  54.         Serial.println("Kod Poprawny");
  55.         analogWrite(10, 150);
  56.         delay(200);
  57.         analogWrite(10, 0);
  58.       }
  59.     }
  60.     else
  61.     {
  62.       Licznik_do_kodu = 0;
  63.       Zle_Wcisniecia++;
  64.            
  65.       analogWrite(10, 200);
  66.       delay(200);
  67.       analogWrite(10, 0);
  68.        
  69.       if(Zle_Wcisniecia == 2)
  70.       {
  71.         Serial.println("Zly kod ALARM!");
  72.         analogWrite(10, 100);
  73.         delay(5000);
  74.         analogWrite(10, 0);
  75.       }
  76.     }
  77.   }
  78. }