Password.h и keypad.h меняют скетч пароля для Arduino

У меня фиксированный пароль. Если нажать на клавиатуре букву "D" и ввести правильный пароль, фиксированный пароль будет изменен. Этот новый введенный пароль теперь является правильным паролем, пока пользователь снова не решит сменить пароль. Это не работает. Как это исправить?

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

const byte ROWS = 4; //четыре строки
const byte COLS = 4; //четыре столбца

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

Keypad    keypad { makeKeymap(keys), rowPins, colPins, ROWS, COLS };
Password passwd = Password("123A4");
char passwd2;

void setup() {
  Serial.begin(9600);
}

void loop() {

  char key = keypad.getKey();
   if (key != NO_KEY){
      delay(60); 
      switch (key){
      case 'D': changepasswd(); break; 
      case '*': checkpasswd(); break;
      case '#': passwd.reset(); break;
     default: passwd.append(key);
      }
   }
}


void checkpasswd() {

  Serial.print(passwd2);

   if (passwd.evaluate()){
      Serial.println(" OK.");
   } else {
      Serial.println(" Wrong password!");
   } 
   passwd.reset();
}

void changepasswd() {
  char key = keypad.getKey();
      delay(60); 
      Serial.print(key);
      passwd2 += key;
      passwd.set(passwd2);

   Serial.print("Password changed to ");
   Serial.println(passwd2);

}

, 👍0


1 ответ


Лучший ответ:

1

Логика вашей функции искажена:

  1. Функция checkpasswd(): Большая часть функции в порядке, но вам не нужно отправлять passwd2 через Serial, так как он не имеет никакого отношения к этой функции. Вы используете переменную только для установки нового пароля. Вы можете выбросить этот оператор печати.
  2. Функция changepasswd(): Здесь кроется проблема. Скорее всего, getKey() возвращает здесь NO_KEY, который определен как нулевой символ. Поэтому при выводе его в Serial вы ничего там не видите (нулевой символ отмечает конец строки в C/C++). Вы устанавливаете пароль как нулевой символ, который не может быть введен пользователем. Также есть еще одна ловушка: Сайт Arduino Playground для библиотеки Password утверждает для функции set():

    Внимание: новый пароль должен быть глобальной переменной (не локальной) функциональная переменная), так как эта функция копирует указатель на новую пароль в библиотеку, а не копия пароля.

Поскольку переменная key является только локальной, после функции библиотека Password имеет свой внутренний указатель, указывающий на теперь освобожденное пространство памяти. В какой-то другой точке программы это пространство может быть записано снова, фактически меняя пароль на что-то другое.

И, наконец, функция не содержит никаких циклов, поэтому будет введен только 1 символ, а новый установленный пароль может быть длиной только 1 символ. Переменная буфера passwd2 имеет тип char, поэтому также только 1 символ. Что вам действительно нужно, так это char [] (массив символов).

Вот фрагмент кода (не проверенный), который должен реализовать это правильно:

char passwd2[6]=""; //глобальный буфер для нового пароля
                    // 6 байт, так как строка C должна заканчиваться нулевым символом

void changepasswd(){
    for(byte i=0;i<5;i++){
        char key = NO_KEY;
        while(key == NO_KEY || key=='*' || key=='#' || key=='D') key = keypad.getKey();
        passwd2[i] = key;
        delay(60);
    }
    passwd2[5] = '\0'; //обеспечиваем правильное окончание строки
    passwd.set(passwd2);
}

Обратите внимание на следующие моменты:

  • Эта реализация блокирует выполнение программ, пока не будет введен полный действительный пароль. Она будет игнорировать все недействительные символы, которые вы используете для других целей (#, * и D).
  • passwd.set(passwd2) на самом деле необходим только в первый раз, когда мы меняем пароль, чтобы объект Password имел указатель на наш буфер. После этого мы технически можем изменить пароль непосредственно в буфере, не вызывая функцию set(). Я включил ее здесь для удобства чтения и для того, чтобы сделать код немного более отказоустойчивым (против неправильного дальнейшего кодирования).
  • Это жестко закодировано для приема только 5-значных паролей. Если вам нужны пароли произвольной длины, вы можете начать программирование с этой основы.
  • Устранение дребезга кнопок с помощью простого delay() может быть недостаточным в какой-то момент. Но насколько я понимаю исходный код библиотеки Keypad, он также включает код для устранения дребезга, проверяя только каждые 10 мс на наличие измененной кнопки и возвращая NO_KEY в противном случае.
,