Po przyciśnięciu 4 przycisków w odpowiedniej kolejności załącza się LED

Masz problem z Arduino? Tutaj możesz szukać pomocy.
ODPOWIEDZ
tomikwr
Młodszy majsterkowicz
Posty: 8
Rejestracja: 23 sie 2015, 18:35

Po przyciśnięciu 4 przycisków w odpowiedniej kolejności załącza się LED

Post autor: tomikwr » 19 maja 2018, 00:08

Witam

Jak zrobić, aby po przyciśnięciu 4 przycisków w odpowiedniej kolejności (np. 1,3,2,4) zaświeciła się dioda?
Mówiąc obrazowo: przyciskam i trzymam przycisk 1, następnie 3, 2 i dopiero wciśnięcie 4 zapala LED. Natomiast przyciśnięcie w innej kolejności nie robi nic.

Poniższy kod działa, ale brakuje tej kolejności przyciskania ;) Naprowadzicie mnie jakoś na trop, żebym mógł to rozbudować?
Wykorzystałbym gotowe projekty zrealizowane na bibliotekach Keypad oraz Password, ale tam znowu jest problem taki, że każdy przycisk musi dostać tylko jeden impuls a nie może być cały czas przyciśnięty.

Kod: Zaznacz cały

const int buttonPin1 = 9;
const int buttonPin2 = 8; 
const int buttonPin3 = 7;
const int buttonPin4 = 6;

void setup() {

  pinMode(buttonPin1, INPUT);
  pinMode(buttonPin2, INPUT);
  pinMode(buttonPin3, INPUT);
  pinMode(buttonPin4, INPUT);
  pinMode(LED_BUILTIN, OUTPUT);

}

void loop() {

  int buttonState1 = digitalRead(buttonPin1);
  int buttonState2 = digitalRead(buttonPin2);
  int buttonState3 = digitalRead(buttonPin3);
  int buttonState4 = digitalRead(buttonPin4);
  
  if (buttonState1 == HIGH && buttonState2 == HIGH && buttonState3 == HIGH && buttonState4 == HIGH ) {

    digitalWrite(LED_BUILTIN, HIGH);
   
  }

  delay(300);
}

Co miesiąc do wygrania nagrody o wartości ponad 1600 zł!


Awatar użytkownika
ethanak
Złota rączka
Posty: 768
Rejestracja: 21 lis 2015, 14:41
Kontakt:

Re: Po przyciśnięciu 4 przycisków w odpowiedniej kolejności załącza się LED

Post autor: ethanak » 19 maja 2018, 09:02

Jest parę możliwości.
1) Potraktuj puszczenie klawisza jako oddzielny kod - wtedy pewnie będziesz mógł skorzystać z gotowców.
2) Potraktuj puszczenie klawisza jako zmianę stanu (program przechodzi w stan oczekiwania na puszczenie wszystkich klawiszy i dopiero potem wraca do stanu początkowego oczekiwania na pierwszy klawisz).

Pamiętaj, że masz wykryć wciśnięcie klawisza, a nie tylko jego stan (czyli porównać stan bieżący ze stanem z poprzedniego obrotu pętli).
Pisze człowiek ambitnie, a tu przychodzi prostak i wszystko rozumie.
To jest ewidentna bezczelność!
kaczakat
Młodszy majsterkowicz
Posty: 25
Rejestracja: 8 wrz 2017, 15:01

Re: Po przyciśnięciu 4 przycisków w odpowiedniej kolejności załącza się LED

Post autor: kaczakat » 19 maja 2018, 09:09

Witam
Naucz się odmierzać upływ czasu w programie funkcją millis() i micros(). Co 5ms sprawdzaj stan przycisku, gdy jakiś będzie wciśnięty to zliczaj mu czas wciśnięcia, jak puszczony to zeruj jego licznik. W pętli ma nie być delay() - przykłady blinkwithoutdelay, jest na kursie Arduino Forbot, idt.
LED ma się zaświecić gdy liczniki klawiszy ułożą się tak, że l1>L2&&L2>L3&&L3>L4 czy jak tam ma być.
W normalnym życiu sprawdzamy sekwencję przycisków - nie musisz trzymać 4 przycisków pinu, tylko jaką liczbę wbiłeś. Jak jakiś wciśnięty to rozpocznij odliczanie timeout do zakończenia, czyli na wciśnięcie 4 przycisków daj ludkowi 4x5s, a faktycznie na naciśnięcie każdego kolejnego kolejne 5s. Do każdego wciśniętego przycisku przypisuj wagę, jeśli jest to pierwszy to x1000, drugi x100, trzeci x10, czwarty x1 (czy tam w świecie cyfrowym analogicznie potęgi liczby 2). Uzyskana liczba ma się zgadzać z zakładaną sekwencją. Jeśli upłynie timeout to resetuj liczbę do 0 i zacznij budować liczbę od nowa.
Wątpię by zamieszczony kod mógł działać naprawdę prawidłowo. Jeśli w czasie trwania tego "zamrożenia" delay(300) zostanie wciśnięty przycisk, program tego nie zauważy.
tomikwr
Młodszy majsterkowicz
Posty: 8
Rejestracja: 23 sie 2015, 18:35

Re: Po przyciśnięciu 4 przycisków w odpowiedniej kolejności załącza się LED

Post autor: tomikwr » 19 maja 2018, 17:25

Dzięki za odpowiedzi. A da się przerobić poniższy kod, aby nie trzeba było za każdym razem naciskać * jak się wpisze poprawny kod w celu potwierdzenia, tylko żeby od razu załączała się dioda? Czyli przyciskam kolejno 1,2,3 i dioda świeci. Tak samo jeśli chodzi o reset - zły wpisany kod, automatycznie resetuje zamiast naciskania # ?

Kod: Zaznacz cały

#include <Password.h>
#include <Keypad.h>

Password password = Password( "123" );

const byte ROWS = 4; // Four rows
const byte COLS = 4; //  columns
// Define the Keymap
char keys[ROWS][COLS] = {
  {'1','2','3','4'}
  
};

byte rowPins[ROWS] = { 9,8,7,6 };// Connect keypad ROW0, ROW1, ROW2 and ROW3 to these Arduino pins.
byte colPins[COLS] = { 5,4,3,2 };// Connect keypad COL0, COL1 and COL2 to these Arduino pins.


// Create the Keypad
Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );

void setup(){

  Serial.begin(9600);
  keypad.addEventListener(keypadEvent); //add an event listener for this keypad
}

void loop(){
  keypad.getKey();
}

//take care of some special events
void keypadEvent(KeypadEvent eKey){
  switch (keypad.getState()){
    case PRESSED:
	Serial.print("Pressed: ");
	Serial.println(eKey);
	switch (eKey){
	  case '*': sprawdzHaslo(); break;
	  case '#': password.reset(); break;
	  default: password.append(eKey);
     }
  }
}

void sprawdzHaslo(){
  if (password.evaluate()){
    Serial.println("Haslo poprawne");
    digitalWrite(LED_BUILTIN, HIGH);

    
    //Add code to run if it works
  }else{
    password.reset();
    Serial.println("BŁĄD");
   
    
    //add code to run if it did not work
  }
}
uzi18
Majsterkowicz
Posty: 107
Rejestracja: 10 maja 2018, 05:06

Re: Po przyciśnięciu 4 przycisków w odpowiedniej kolejności załącza się LED

Post autor: uzi18 » 19 maja 2018, 17:55

Oczywiście ze sie da.

Wysłane z mojego MI MAX przy użyciu Tapatalka

Awatar użytkownika
ethanak
Złota rączka
Posty: 768
Rejestracja: 21 lis 2015, 14:41
Kontakt:

Re: Po przyciśnięciu 4 przycisków w odpowiedniej kolejności załącza się LED

Post autor: ethanak » 19 maja 2018, 18:06

Zacznij może od prawidłowego zadeklarowania tablicy keys (wszystkie komórki muszą być zainicjalizowane), potem pogadamy.
Pisze człowiek ambitnie, a tu przychodzi prostak i wszystko rozumie.
To jest ewidentna bezczelność!
tomikwr
Młodszy majsterkowicz
Posty: 8
Rejestracja: 23 sie 2015, 18:35

Re: Po przyciśnięciu 4 przycisków w odpowiedniej kolejności załącza się LED

Post autor: tomikwr » 19 maja 2018, 20:37

ethanak pisze:
19 maja 2018, 18:06
Zacznij może od prawidłowego zadeklarowania tablicy keys (wszystkie komórki muszą być zainicjalizowane), potem pogadamy.
Poprawiłem kod. Nie używam w tym kodzie całej klawiatury 4x4 tylko 4 przyciski.

Kod: Zaznacz cały

#include <Password.h>
#include <Keypad.h>

Password password = Password( "123" );

const byte ROWS = 1;
const byte COLS = 4;
// Define the Keymap
char keys[ROWS][COLS] = {
  {'1','2','3','4'}
  };

byte rowPins[ROWS] = { 9 };
byte colPins[COLS] = { 5,4,3,2 };

Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );

void setup(){

  Serial.begin(9600);
  keypad.addEventListener(keypadEvent); //add an event listener for this keypad
}

void loop(){
  keypad.getKey();
}

void keypadEvent(KeypadEvent eKey){
  switch (keypad.getState()){
    case PRESSED:
	Serial.print("Przycisk: ");
	Serial.println(eKey);
	switch (eKey){
	  case '4': checkPassword(); break;
	  case '#': password.reset(); break;
	  default: password.append(eKey);
     }
  }
}

void checkPassword(){
  if (password.evaluate()){
    Serial.println("SUKCES");

  }else{
    Serial.println("BŁĄD");
    
  }
}
Awatar użytkownika
ethanak
Złota rączka
Posty: 768
Rejestracja: 21 lis 2015, 14:41
Kontakt:

Re: Po przyciśnięciu 4 przycisków w odpowiedniej kolejności załącza się LED

Post autor: ethanak » 20 maja 2018, 05:35

tomikwr pisze:
19 maja 2018, 20:37
Nie używam w tym kodzie całej klawiatury 4x4 tylko 4 przyciski.
Ty nie używasz, ale osoba która wpisuje kod o tym nie wie i może nacisnąć '5'. Jesteś na 100% pewien, że biblioteka Password prawidłowo zareaguje jeśli zamiast znaku dostanie '\0'? Czytałeś kod biblioteki?
Poza tym dzisiaj klucz masz zaszyty w kodzie - jutro będziesz chciał trzymać w eepromie, pojutrze dostać po wifi z jednostki centralnej... za każdym razem będziesz skrzętnie sprawdzał których to klawiszy tak naprawdę używasz? Bajty w kodzie źródłowym oszczędzasz czy co?
Pisze człowiek ambitnie, a tu przychodzi prostak i wszystko rozumie.
To jest ewidentna bezczelność!
tomikwr
Młodszy majsterkowicz
Posty: 8
Rejestracja: 23 sie 2015, 18:35

Re: Po przyciśnięciu 4 przycisków w odpowiedniej kolejności załącza się LED

Post autor: tomikwr » 20 maja 2018, 08:45

ethanak pisze:
20 maja 2018, 05:35
tomikwr pisze:
19 maja 2018, 20:37
Nie używam w tym kodzie całej klawiatury 4x4 tylko 4 przyciski.
Ty nie używasz, ale osoba która wpisuje kod o tym nie wie i może nacisnąć '5'. Jesteś na 100% pewien, że biblioteka Password prawidłowo zareaguje jeśli zamiast znaku dostanie '\0'? Czytałeś kod biblioteki?
Poza tym dzisiaj klucz masz zaszyty w kodzie - jutro będziesz chciał trzymać w eepromie, pojutrze dostać po wifi z jednostki centralnej... za każdym razem będziesz skrzętnie sprawdzał których to klawiszy tak naprawdę używasz? Bajty w kodzie źródłowym oszczędzasz czy co?
ethanak Pisałem w poprzednim poście, że do tego projektu będą podłączone tylko 4 buttony a nie cała klawiatura 4x4, więc po co mam definiować w kodzie pozostałe? Także nikt ani nic nie przyciśnie mi innych znaków, bo ich tam nie będzie ;) Dlatego chcę przerobić to tak, aby nie potrzeba było naciskać dodatkowych przycisków w celu zatwierdzenia lub kasowania.
Awatar użytkownika
ethanak
Złota rączka
Posty: 768
Rejestracja: 21 lis 2015, 14:41
Kontakt:

Re: Po przyciśnięciu 4 przycisków w odpowiedniej kolejności załącza się LED

Post autor: ethanak » 20 maja 2018, 10:37

OK dobra, zasugerowałem się poprzednim kodem.
Jedno z rozwiązań:
a) Za każdym razem po naciśnięciu przycisku wywołujesz password.append(key) i sprawdzasz, czy hasło jest prawidłowe przez evaluate(). Jeśli tak, to password.reset() (czyli przygotowujesz się do następnego wprowadzenia kodu) i robisz coś związanego z prawidłowym wprowadzeniem hasła. Jeśli nie to nie robisz nic.
b) Jeśli żaden przycisk nie był wciśnięty przez N milisekund (powiedzmy 2000), wywołujesz password.reset().
Pasi?
Pisze człowiek ambitnie, a tu przychodzi prostak i wszystko rozumie.
To jest ewidentna bezczelność!
uzi18
Majsterkowicz
Posty: 107
Rejestracja: 10 maja 2018, 05:06

Re: Po przyciśnięciu 4 przycisków w odpowiedniej kolejności załącza się LED

Post autor: uzi18 » 20 maja 2018, 12:07

Osobiscie olał bym ta biblioteke password skoro haslo to tylko 4 przyciski to mozna ich kokejnosc zapamietac w tablicy.

Wysłane z mojego MI MAX przy użyciu Tapatalka


Awatar użytkownika
ethanak
Złota rączka
Posty: 768
Rejestracja: 21 lis 2015, 14:41
Kontakt:

Re: Po przyciśnięciu 4 przycisków w odpowiedniej kolejności załącza się LED

Post autor: ethanak » 20 maja 2018, 12:41

A po co wyważać otwarte drzwi?
Pisze człowiek ambitnie, a tu przychodzi prostak i wszystko rozumie.
To jest ewidentna bezczelność!
tomikwr
Młodszy majsterkowicz
Posty: 8
Rejestracja: 23 sie 2015, 18:35

Re: Po przyciśnięciu 4 przycisków w odpowiedniej kolejności załącza się LED

Post autor: tomikwr » 23 maja 2018, 09:31

Ok, mam taki kod i to już działa jak chciałem, ale mam jeszcze jedną zagwozdkę do zrobienia. Czy da się tutaj dorobić jakąś funkcję sprawdzającą, czy np. jak się przyciśnie dwa przyciski naraz, lub wszystkie cztery to żeby nie wykonywało się nic? W tej chwili naciśnięcie 2 naraz powoduje losowe wybicie danej liczby (wynika to pewnie z tego, że i tak któryś przycisk został naciśnięty pierwszy).

Kod: Zaznacz cały

#include <Keypad.h>
 
char password[4];
int currentLength = 0;
char entered[4];
 
const byte ROWS = 1;
const byte COLS = 4;
// Define the Keymap
char keys[ROWS][COLS] = {
  {'1','2','3','4'}
  };
 
byte rowPins[ROWS] = { 9 };
byte colPins[COLS] = { 5,4,3,2 };
Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );
 
void setup(){
  Serial.begin(9600);
  password[0] = '1'; 
  password[1] = '2'; 
  password[2] = '3';
  password[3] = '4';
}
void loop()
{
  
  while (currentLength < 4)
        {
          
          char key = keypad.getKey();
                            
          if (key != NO_KEY)    
            {
             Serial.print(key);
             entered[currentLength] = key;
             currentLength++;
             delay(100);
            }
        }
 
      if (currentLength == 4)
        {
          if (entered[0] == password[0] && 
              entered[1] == password[1] && 
              entered[2] == password[2] && 
              entered[3] == password[3])   
            {
             
              Serial.print("Sukces");
              digitalWrite(LED_BUILTIN, HIGH);
              delay(500); //czekamy 500ms
              currentLength = 0; 

            }

      else
        { 
          Serial.print("Błąd");   
          delay(500); //czekamy 500ms
          currentLength = 0;  
        }  
         }
}
Awatar użytkownika
ethanak
Złota rączka
Posty: 768
Rejestracja: 21 lis 2015, 14:41
Kontakt:

Re: Po przyciśnięciu 4 przycisków w odpowiedniej kolejności załącza się LED

Post autor: ethanak » 23 maja 2018, 12:58

Da się, tylko nie korzystaj z biblioteki Keypad bo sobie niepotrzebnie skomplikujesz życie. Cztery piny na krzyż to sobie sam powinieneś oprogramować.
Pisze człowiek ambitnie, a tu przychodzi prostak i wszystko rozumie.
To jest ewidentna bezczelność!
Bob2462
Majsterkowicz
Posty: 79
Rejestracja: 13 mar 2016, 00:11

Re: Po przyciśnięciu 4 przycisków w odpowiedniej kolejności załącza się LED

Post autor: Bob2462 » 23 maja 2018, 15:49

Takie coś napisałem jako alternatywę dla twojego kodu:

Kod: Zaznacz cały

 
  
//definicje pinów, należy zmienić na to co jest w układzie 
#define KEY_1 2
#define KEY_2 3
#define KEY_3 4
#define KEY_4 5 

#define MAX_PSWD_LEN 10//maksymalna długość hasła

//stwórz klasę do walidacji hasła 
class password
{
   public:
      password();//konstruktor klasy (wykona się przy utworzeniu obiektu)
      void setPassword(char* input, unsigned short len);//ustaw hasło (powinno się to ulepszyć dodając możliwość dodawania hasła po jednym znaku)
      void clearInput();//wyczyść wejście użytkownika
      void appendInput(char character);//wprowadź znak hasła
      bool validatePassword();//sprawdź hasło
      short index;//aktualna pozycja kursora wejściowego
      
   private:
      void clearArray(char* input_array, unsigned short len);//wyczyść tablicę
      char password[MAX_PSWD_LEN];//hasło
      char input[MAX_PSWD_LEN];//bufor na wejście użytkownika
};

//wyczyść tablicę wypełniając ją znakiem NULL ('\0')
void password::clearArray(char* input_array, unsigned short len)
{
  for(unsigned short i=0;i<len;i++)
  {
     input_array[i] = '\0';
  }
}

//nadaj zmiennym stany początkowe
password::password()
{
    //wyzeruj wszystkie zmienne
    clearArray(password, MAX_PSWD_LEN);
    clearArray(input, MAX_PSWD_LEN);
    index = 0;
}


void password::setPassword(char* input, unsigned short len)
{
  clearArray(password, MAX_PSWD_LEN);//na początkuj wyczyść stare hasło
  for(unsigned short i=0;i<len;i++)//skopiuj wszystkie znaki do zmiennej przechowującej hasło
  {
    password[i] = input[i];
  }
}

void password::clearInput()
{
  index = 0;
  clearArray(input, MAX_PSWD_LEN);
}

void password::appendInput(char character)
{
  input[index] = character;
  index++;
}

bool password::validatePassword()
{
  for(unsigned short i=0; i<MAX_PSWD_LEN; i++)
  {
    if(input[i] != password[i])
    {
      return 0;//hasło się nie zgadza
    }
  }

return 1;//hasło się zgadza
}

char getKey()
{
  if(digitalRead(KEY_1) ==  LOW)
  {
    return '1';
  }
  if(digitalRead(KEY_2) ==  LOW)
  {
    return '2';
  }
  if(digitalRead(KEY_3) ==  LOW)
  {
    return '3';
  }
  if(digitalRead(KEY_4) ==  LOW)
  {
    return '4';
  }
  return 0;//jeśli nic nie zostało wprowadzone to wtedy zwracamy 0
}

password key;

void setup()
{
   Serial.begin(9600);
   //ustawienia pinów  (ustaw jako wejście, włącz rezystory podciągające)
   pinMode(KEY_1, INPUT_PULLUP);
   pinMode(KEY_2, INPUT_PULLUP);
   pinMode(KEY_3, INPUT_PULLUP);
   pinMode(KEY_4, INPUT_PULLUP);
   char ourPassword[4] = {'1','2','3','4'};//zdefiniuj hasło
   key.setPassword(ourPassword,4);//ustaw hasło
}

void loop()
{
  char x = getKey();//sprawdź stan klawiatury
  if(x!=0)
  {
    Serial.print("Wprowadzono:");
    Serial.println(x);
    key.appendInput(x);
    Serial.print("Index to : ");
    Serial.println(key.index);
    delay(1000);
  }

  if(key.index>=4)
  {
    Serial.print("Testuję hasło... ");
    if(key.validatePassword())
    {
      Serial.println("Ok");
    }
    else
    {
      Serial.println("ERR");
    }
    key.clearInput();
  }
}
Nie testowałem tego ale myślę, że działa.
Moim zdaniem taki kod jest lepszy bo pomimo swojej nieco większej długości zapewnia on możliwość łatwego dodanie takich bajerów jak na przykład przechowywanie hasła w EEPROM.
Dodatkowo nie są wymagane żadne zewnętrzne biblioteki.
ODPOWIEDZ

Strony partnerskie: