Skocz do zawartości

Kurs Arduino II - #5 - klawiatura, własny system alarmowy


Komentator

Pomocna odpowiedź

html_mig_img
Podczas wykonywania ćwiczeń z tej części kursu Arduino sprawdzimy jak w praktyce najwygodniej podłączyć do naszego urządzenia klawiaturę.Korzystając z wszystkich omówionych do tej pory elementów zbudujemy centralkę alarmową, której głównym mózgiem będzie oczywiście Arduino.

UWAGA, to tylko wstęp! Dalsza część artykułu dostępna jest na blogu.

Przeczytaj całość »

Poniżej znajdują się komentarze powiązane z tym wpisem.

Link do komentarza
Share on other sites

Trochę cicho tu, więc na dobry początek wklejam moje 'wypociny'. Dodane dźwięki uzbrajania i podawania pinu + przycisk resetu.

#define BUZZER 11
#define KONTAKTRON 10
#define PIR 1
#define ukryty 12

#include <Keypad.h> //biblioteka od klawiatury
#include <Adafruit_NeoPixel.h> //biblioteka od linijki LED

const byte ROWS = 4; // ile wierszy
const byte COLS = 4; //ile kolumn

byte rowPins[ROWS] = {5, 4, 3, 2}; //piny wierszy
byte colPins[COLS] = {6, 7, 8, 9}; //piny kolumn

char keys[ROWS][COLS] = { //mapowanie klawiatury
 {'1','2','3','A'},
 {'4','5','6','B'},
 {'7','8','9','C'},
 {'*','0','#','D'}
};

Keypad klawiatura = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS ); //inicjalizacja klawiatury
Adafruit_NeoPixel linijka = Adafruit_NeoPixel(8, A0, NEO_GRB + NEO_KHZ800); //konfiguracja linijki LED

volatile int stanAlarmu = 1;
int pinAlarmuPozycja = 1;
char pinCyfra1 = '1';
char pinCyfra2 = '2';
char pinCyfra3 = '3';
char pinCyfra4 = '4';

void setup() {
 pinMode(BUZZER, OUTPUT);
 pinMode(KONTAKTRON, INPUT_PULLUP);
 pinMode(PIR, INPUT_PULLUP);
 pinMode(ukryty, INPUT_PULLUP);

 linijka.begin(); //inicjalizacja linijki
 linijka.show(); 
}

void loop() {
 char klawisz = 0; //zmienna do przetrzymywania znakow z klawiatury
 int i = 0; //zmienna pomocnicza do pętli

 switch(stanAlarmu) { //Wykonywania akcji odpowiedniej dla danego stanu
   case 1:
     //Czuwanie
     linijka.setPixelColor(0, linijka.Color(0, 15, 0)); //Dioda nr 1 świeci na zielono
     linijka.show();

     klawisz = klawiatura.getKey();
     if (klawisz == 'A') { //Czy zubroic alarm?
       tone(BUZZER, 800);
       delay(100);
       tone(BUZZER, 900);
       delay(100);
       noTone(BUZZER);
       for (i = 1; i < 8; i++) {
         linijka.setPixelColor(i, linijka.Color(0, 0, 15)); //Dioda nr i świeci na niebiesko
         linijka.show();
         delay(710);
       } // wykonanie tej petli zajmie okolo 5 sekund

        for (i = 1; i < 8; i++) {
         linijka.setPixelColor(i, linijka.Color(15, 0, 0)); //Dioda nr i świeci na czerwono
         linijka.show();
         delay(710);
       } // wykonanie tej petli zajmie okolo 5 sekund     

       wylaczDiody();
       tone(BUZZER, 900);
       delay(100);
       tone(BUZZER, 800);
       delay(100);
       noTone(BUZZER);
       stanAlarmu = 2;
     }

   break;

   case 2:
     //Monitorowanie
     linijka.setPixelColor(7, linijka.Color(15, 0, 0)); //Dioda nr 8 świeci na czerwono
     linijka.show();
     delay(50);
     linijka.setPixelColor(7, linijka.Color(0, 0, 0)); //Dioda nr 8 wylaczona
     linijka.show();
     delay(50);

     if (digitalRead(PIR) == HIGH) {
       stanAlarmu = 4; //Natychmiast uruchamiamy alarm
     } else if (digitalRead(KONTAKTRON) == HIGH) {
       stanAlarmu = 3; //Szansa na rozbrojenie
     }

   break;

   case 3:
     //Rozbrajanie
     klawisz = klawiatura.getKey();
     if (klawisz) {
       //Czy kolejna podana cyfra jest poprawna?
       if (pinAlarmuPozycja == 1 && klawisz == pinCyfra1) { //Jesli sprawdzamy 1 pozycje PINu
         pinAlarmuPozycja++; //Cyfra poprawna, mozna sprawdzic na kolejna
         tone(BUZZER, 1000, 50);
       } else if (pinAlarmuPozycja == 2 && klawisz == pinCyfra2) { //Jesli sprawdzamy 2 pozycje PINu
         pinAlarmuPozycja++; //Cyfra poprawna, mozna sprawdzic na kolejna  
         tone(BUZZER, 1050, 50);       
       } else if (pinAlarmuPozycja == 3 && klawisz == pinCyfra3) { //Jesli sprawdzamy 3 pozycje PINu
         pinAlarmuPozycja++; //Cyfra poprawna, mozna sprawdzic na kolejna   
         tone(BUZZER, 1100, 50);     
       } else if (pinAlarmuPozycja == 4 && klawisz == pinCyfra4) { //Jesli sprawdzamy 4 pozycje PINu
         tone(BUZZER, 1150, 50);
         delay(50);
           stanAlarmu = 1; //Wszystkie 4 cyfry kodu sa poprawne      
       } else {
          stanAlarmu = 4; //Blad w kodzie PIN - wlacz alarm
       }
     }
   break;

   case 4:
     //Sygnalizacja alarmu
     if (digitalRead(ukryty) == LOW){
       stanAlarmu = 1;
     }
     int i = 0;
      uint32_t kolor = 0;
      for (i = 0; i < 8; i++) {
       if (i < 4) {
        linijka.setPixelColor(i, linijka.Color(255, 0, 0)); //Dioda nr i świeci na wybrany kolor
        tone(BUZZER, 3500, 100);
       } else {
        linijka.setPixelColor(i, linijka.Color(0, 0, 255)); //Dioda nr i świeci na wybrany kolor  
        tone(BUZZER, 3000, 100);   
       }
       linijka.show(); 
       delay(100);
     }
    linijka.clear(); 
   break;
  }
}

void wylaczDiody() {
 int i = 0;
 for (i = 0; i < 8; i++){
   linijka.setPixelColor(i, linijka.Color(0, 0, 0)); //Dioda nr 1 wylaczona    
 }
 linijka.show();
}

Jeszcze nie jestem z tego zadowolony, (1) bo przycisk resetu zrobiony na 'zwykłym' if-ie i trzeba przytrzymać go ze 3 sek zanim zadziała. Chociaż ma to sens (przypadkowe wciśnięcie nie wyłączy alarmu) to chciałbym to opóźnienie zrobić świadomie.

(2) Miałem wizję na 'bipy' klawiatury - https://create.arduino.cc/editor/leepa79/3d7c8b56-96e3-4e83-8d55-c82ddad7bd28/preview

Chciałem w sekcji 'Rozbrajanie' użyć tego zamiast 'tone (BUZZER...' - na dole programu wrzuciłem tę część z linku jako void bipy() i oczywiście zamiast tego tone chciałem przywołać te bipy z tego. Teraz sobie myślę, czy po void bipy() nie miałem dać jakiegoś opóźnienia, ale po ostatnich lekcjach mam wrażenie, że tych delay-ów już teraz mam zbyt dużo 😉

Film wrzucę wieczorem i zachęcam do komentowania, bo jak pisałem podczas kursu Arduino I - te komentarze są uzupełnieniem tych kursów. Dużo ciekawych rozwiązań znalazłem właśnie w komentarzach pod kursami. Pozdrawiam.

Link do komentarza
Share on other sites

leepa79, do resetu wykorzystaj przerwania opisana w poprzednim artykule 🙂 Wtedy nie będzie trzeba trzymać przycisku przez 3 sekundy. Wystarczy jego krótkie dotknięcie, a alarm wyłączy się przy najbliższej możliwej okazji 🙂

Kwestię opóźnień można sprawdzić i przetestować. Oczywiście można tym sobie sporo zaszkodzić, ale z drugiej strony np. opóźnienie o 50 ms (lub podobne wartości) nie powinno zaszkodzić. Ważne, aby nie wpaść w pułapkę krótkich opóźnień. Tzn., pozornie program będzie zatrzymywał się np. na 50 ms, a w praktyce wyjdzie, że takich krótkich przerw podczas jednego obiegu pętli programu jest 100. Wtedy korzystając pozornie z małych opóźnień zamrażamy sobie program na 5 sekund 🙂

Link do komentarza
Share on other sites

Zarejestruj się lub zaloguj, aby ukryć tę reklamę.
Zarejestruj się lub zaloguj, aby ukryć tę reklamę.

jlcpcb.jpg

jlcpcb.jpg

Produkcja i montaż PCB - wybierz sprawdzone PCBWay!
   • Darmowe płytki dla studentów i projektów non-profit
   • Tylko 5$ za 10 prototypów PCB w 24 godziny
   • Usługa projektowania PCB na zlecenie
   • Montaż PCB od 30$ + bezpłatna dostawa i szablony
   • Darmowe narzędzie do podglądu plików Gerber
Zobacz również » Film z fabryki PCBWay

Poprawione

#define BUZZER 11
#define KONTAKTRON 10
#define PIR 12
#define ukryty 2

#include <Keypad.h> //biblioteka od klawiatury
#include <Adafruit_NeoPixel.h> //biblioteka od linijki LED

const byte ROWS = 4; // ile wierszy
const byte COLS = 4; //ile kolumn

byte rowPins[ROWS] = {5, 4, 3, 1}; //piny wierszy
byte colPins[COLS] = {6, 7, 8, 9}; //piny kolumn

char keys[ROWS][COLS] = { //mapowanie klawiatury
 {'1','2','3','A'},
 {'4','5','6','B'},
 {'7','8','9','C'},
 {'*','0','#','D'}
};

Keypad klawiatura = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS ); //inicjalizacja klawiatury
Adafruit_NeoPixel linijka = Adafruit_NeoPixel(8, A0, NEO_GRB + NEO_KHZ800); //konfiguracja linijki LED

volatile int stanAlarmu = 1;
int pinAlarmuPozycja = 1;
char pinCyfra1 = '1';
char pinCyfra2 = '2';
char pinCyfra3 = '3';
char pinCyfra4 = '4';

void setup() {
 pinMode(BUZZER, OUTPUT);
 pinMode(KONTAKTRON, INPUT_PULLUP);
 pinMode(PIR, INPUT_PULLUP);
 pinMode(ukryty, INPUT_PULLUP);

 linijka.begin(); //inicjalizacja linijki
 linijka.show(); 

 attachInterrupt(digitalPinToInterrupt(ukryty), stanAlarmu = 5, RISING);
}

void loop() {
 char klawisz = 0; //zmienna do przetrzymywania znakow z klawiatury
 int i = 0; //zmienna pomocnicza do pętli

 switch(stanAlarmu) { //Wykonywania akcji odpowiedniej dla danego stanu
   case 1:
     //Czuwanie
     linijka.setPixelColor(0, linijka.Color(0, 15, 0)); //Dioda nr 1 świeci na zielono
     linijka.show();

     klawisz = klawiatura.getKey();
     if (klawisz == 'A') { //Czy zubroic alarm?
       tone(BUZZER, 800);
       delay(100);
       tone(BUZZER, 900);
       delay(100);
       noTone(BUZZER);
       for (i = 1; i < 8; i++) {
         linijka.setPixelColor(i, linijka.Color(0, 0, 15)); //Dioda nr i świeci na niebiesko
         linijka.show();
         delay(710);
       } // wykonanie tej petli zajmie okolo 5 sekund

        for (i = 1; i < 8; i++) {
         linijka.setPixelColor(i, linijka.Color(15, 0, 0)); //Dioda nr i świeci na czerwono
         linijka.show();
         delay(710);
       } // wykonanie tej petli zajmie okolo 5 sekund     

       wylaczDiody();
       tone(BUZZER, 900);
       delay(100);
       tone(BUZZER, 800);
       delay(100);
       noTone(BUZZER);
       stanAlarmu = 2;
     }

   break;

   case 2:
     //Monitorowanie
     linijka.setPixelColor(7, linijka.Color(15, 0, 0)); //Dioda nr 8 świeci na czerwono
     linijka.show();
     delay(50);
     linijka.setPixelColor(7, linijka.Color(0, 0, 0)); //Dioda nr 8 wylaczona
     linijka.show();
     delay(50);

     if (digitalRead(PIR) == HIGH) {
       stanAlarmu = 4; //Natychmiast uruchamiamy alarm
     } else if (digitalRead(KONTAKTRON) == HIGH) {
       stanAlarmu = 3; //Szansa na rozbrojenie
     }

   break;

   case 3:
     //Rozbrajanie
     klawisz = klawiatura.getKey();
     if (klawisz) {
       //Czy kolejna podana cyfra jest poprawna?
       if (pinAlarmuPozycja == 1 && klawisz == pinCyfra1) { //Jesli sprawdzamy 1 pozycje PINu
         pinAlarmuPozycja++; //Cyfra poprawna, mozna sprawdzic na kolejna
         tone(BUZZER, 1000, 50);
       } else if (pinAlarmuPozycja == 2 && klawisz == pinCyfra2) { //Jesli sprawdzamy 2 pozycje PINu
         pinAlarmuPozycja++; //Cyfra poprawna, mozna sprawdzic na kolejna  
         tone(BUZZER, 1050, 50);       
       } else if (pinAlarmuPozycja == 3 && klawisz == pinCyfra3) { //Jesli sprawdzamy 3 pozycje PINu
         pinAlarmuPozycja++; //Cyfra poprawna, mozna sprawdzic na kolejna   
         tone(BUZZER, 1100, 50);     
       } else if (pinAlarmuPozycja == 4 && klawisz == pinCyfra4) { //Jesli sprawdzamy 4 pozycje PINu
         tone(BUZZER, 1150, 50);
         delay(50);
           stanAlarmu = 1; //Wszystkie 4 cyfry kodu sa poprawne      
       } else {
          stanAlarmu = 4; //Blad w kodzie PIN - wlacz alarm
       }
     }
   break;

   case 4:
     //Sygnalizacja alarmu

      for (i = 0; i < 8; i++) {
       if (i < 4) {
        linijka.setPixelColor(i, linijka.Color(255, 0, 0)); //Dioda nr i świeci na wybrany kolor
        tone(BUZZER, 3500, 100);
       } else {
        linijka.setPixelColor(i, linijka.Color(0, 0, 255)); //Dioda nr i świeci na wybrany kolor  
        tone(BUZZER, 3000, 100);   
       }
       linijka.show(); 
       delay(100);
     }
    linijka.clear(); 
   break;

   case 5:
   //Wylaczenie alarmu
   stanAlarmu = 1;
   break;
  }
}

void wylaczDiody() {
 int i = 0;
 for (i = 0; i < 8; i++){
   linijka.setPixelColor(i, linijka.Color(0, 0, 0)); //Dioda nr 1 wylaczona    
 }
 linijka.show();
}

Ciekawa rzecz się wydarzyła kiedy dodałem przerwanie bez tego "case 5" (a w poleceniu dałem stanAlarmu = 1) 🙂

  • Lubię! 1
Link do komentarza
Share on other sites

Mam problem z przerwaniem. W momencie gdy dodaje taki element kodu w całym programie występują błędy

attachInterrupt(digitalPinToInterrupt(2), wylA, RISING);

, a wylA to

void wylA() {
 stanAlarmu = 1;
 wylaczDiody();
 noTone(BUZZER);
}

. Problem znika po usunięciu przerwania z kodu. Co robię źle?

Link do komentarza
Share on other sites

Treker, błędy są różne, może zacznę od tego, że działam na programie z systemu alarmowego(z kursu) dodałem już dźwięki i teraz chciałem dodać przerwanie, ale gdy dodam te linijkę kodu program zaczyna się dziwnie zachowywać tzn. czasami podczas uzbrajania nie wszystkie diody świecą się jak powinny, czasem nie ma dźwięku, alarm od razu po uzbrojeniu wyje, a czasem wyje tylko przez krotki czas i się zawiesza (diody i dźwięk), parę razy się zdarzyło że podczas zbrojenia alarmu się sam rozbroił.

Chciałem mieć podłączony zwykły przycisk z kursu 1, ale próbując dowiedzieć się gdzie jest błąd okazało się, że samo dodanie kodu powoduje błędy w programie nawet gdy pin jest nie podłączony.

Link do komentarza
Share on other sites

Zakurek, po pierwsze proponowałbym podłączyć jednak przycisk, pozostawianie wiszącego wejścia na pewno nie działa korzystanie na układ, nie masz wtedy również szansy sprawdzenia, czy działa on poprawnie. Biorąc pod uwagę, że przycisk będzie ściągał wejście do masy, to na początku warto zacząć od wyzwalania przerwania zboczem opadającym.

Proponowałbym zacząć debugować program np. od dodania funkcji włączającą zwykłego LED'a (np. tego z pinu 13) wewnątrz przerwania. Dzięki temu będziesz widział, czy na pewno jest to kwestia przerwania.

Link do komentarza
Share on other sites

Witam

Chciałem zapytać, czy planowana jest dalsza kontynuacja tego kursu. Pytam dlatego, że zaczęte są nowe kursy (Budowy robotów, Elektroniki cyfrowej), a od 2 miesięcy nie pojawia się żaden artykuł. Szkoda byłoby tak to zamknąć, bo kurs jest dosyć ciekawy

Pozdrawiam

Link do komentarza
Share on other sites

Kamol, tak, z całą pewnością tak. Mam świadomość, że regularność publikacji w tym kursie jest daleka od ideału i sam nad tym ubolewam. Stąd nawet jedno z postanowień noworocznych, aby właśnie się za niego dobrze zabrać i przyspieszyć... Na ten moment mam w planach kolejną część w następnym tygodniu.

Link do komentarza
Share on other sites

W ramach aktualizacji: niestety nie udało mi się dotrzymać zadeklarowanego terminu, dwa następne odcinki kursu są praktycznie gotowe, ale potrzebuję jeszcze chwilę, aby całość "ułożyć" tak, abym nie miał już żadnych wątpliwości. Dodałem w 1 artykule aktualizacje na temat terminów publikacji: kolejna część pojawi się najpóźniej 1 lutego, a następna 8 lutego. Planuję przyspieszyć na tyle, aby zakończyć temat tego kursu w lutym. Jeszcze raz przepraszam za brak wcześniejszych informacji i z góry dziękuję za zrozumienie.

Link do komentarza
Share on other sites

Mam pytanie, tworzę większy projekt i brakuje mi miejsc w Arduino na podłączenie wyświetlacza i klawiatury razem. Czy jest na to jakieś rozwiązanie? Czy dało by się podłączyć klawiaturę pod wejścia analogowe ? Z góry dziękuje za odpowiedź 🙂

Link do komentarza
Share on other sites

Seveneq, tak, jest dużo możliwości 🙂

Wariant pierwszy to wybranie większego Arduino, ale oczywiście w przypadku UNO też da się podłączyć więcej rzeczy. Hasło klucz to ekspander portów - element ten znalazł się przykładowo na naszej płytce do kursu budowy robotów (Kurs budowy robotów – #2 – sterownik robota, czujniki). Zarówno klawiaturę, jak i wyświetlacz da się podłączyć przez taki ekspander.

W przypadku klawiatury można jeszcze skorzystać z wiadomości na temat dzielników napięcia: http://playground.arduino.cc/Code/OneWireKeyPad

Link do komentarza
Share on other sites

Witam,
Ze zdjęć w projekcie ciężko (wg mnie) się doczytać wieć chciałbym poprosić o schemat Fritzing do w.w. projektu na stronie Forbota.

Z góry

Bardzo dziękuję

SpectrumPL

Link do komentarza
Share on other sites

Dołącz do dyskusji, napisz odpowiedź!

Jeśli masz już konto to zaloguj się teraz, aby opublikować wiadomość jako Ty. Możesz też napisać teraz i zarejestrować się później.
Uwaga: wgrywanie zdjęć i załączników dostępne jest po zalogowaniu!

Anonim
Dołącz do dyskusji! Kliknij i zacznij pisać...

×   Wklejony jako tekst z formatowaniem.   Przywróć formatowanie

  Dozwolonych jest tylko 75 emoji.

×   Twój link będzie automatycznie osadzony.   Wyświetlać jako link

×   Twoja poprzednia zawartość została przywrócona.   Wyczyść edytor

×   Nie możesz wkleić zdjęć bezpośrednio. Prześlij lub wstaw obrazy z adresu URL.

×
×
  • Utwórz nowe...

Ważne informacje

Ta strona używa ciasteczek (cookies), dzięki którym może działać lepiej. Więcej na ten temat znajdziesz w Polityce Prywatności.