Pull to refresh

Arduino KeyLock

Lumber room
Awaiting invitation
image

Предыстория:


Однажды вечером, в незапамятные времена, на Хабре я увидел несколько статей по Ардуинке… и знаете что? Я тоже захотел такую штуку
На следующий день незамедлительно были заказаны с eBay:

1. Funduino Mega2560
2. LCD KeyPad Shield

Как мне показалось, этого комплекта хватит не на долго… Так и оказалось. За пару дней Ардуина и Шилд были измучены и оставлены лежать в одиночестве, в ожидании новой партии комплектующих с eBay.

Step 1

Плавным движением руки одеваем наш LCD KeyPad Shield на Мегу. У нас получается вот такой «бутерброд»:

image

Step 2

Идем за шоколадкой, сладкое нам пригодится.
После успешного открытия шоколадки открываем Arduino IDE и создаем новый скетч.

Step 3

Приступаем к написанию кода.
Начнем с объявления переменных и библиотек:

// Библиотеки
#include <LiquidCrystal.h> // Библиотека LCD
LiquidCrystal lcd(8, 9, 4, 5, 6, 7 ); // Объявим к камим пинам подключен LCD
// Переменные
int button; // Кнопка
int codeIndex = 0; // Хранение последовательности ввода чисел
int led = 13; //  LED
int userInputs[4]; // Массив для сохранения в нем вводимых чисел с KeyPad
int doorPass[4] = {1,2,3,4}; // Пароль для "двери"
// Кнопки
const int BUTTON_NONE   = 0; 
const int BUTTON_RIGHT  = 1;
const int BUTTON_UP     = 2; // Комментарии излишни
const int BUTTON_DOWN   = 3; // думаю,что сдесь все понятно.
const int BUTTON_LEFT   = 4;
const int BUTTON_SELECT = 5;


Я старался комментировать каждую строчку кода, если вас что-то будет не понятно, с радостью отвечу в комментариях.
Затем добавим процедуру получения значения кнопки:

// Получение значения кнопки
int getPressedButton()
{
  int buttonValue = analogRead(0);
  if (buttonValue < 100) {
    return BUTTON_RIGHT;  
  }
  else if (buttonValue < 200) {
    return BUTTON_UP;
  }
  else if (buttonValue < 400){
    return BUTTON_DOWN;
  }
  else if (buttonValue < 600){
    return BUTTON_LEFT;
  }
  else if (buttonValue < 800){
    return BUTTON_SELECT;
  }
  return BUTTON_NONE;
}


Теперь создаем главную функцию:

// SETUP
void setup()
{
  Serial.begin(9600); // Задаем скорость порта
  lcd.begin(16, 2); // В моем LCD 2 строчки по 16 символов          
  lcd.print("   ENTER PIN   "); // На первой строчку пишем "ENTER PIN"
  lcd.setCursor(0, 2);  // Устанавливаем курсор на 1 символ 2-ой строки
  lcd.print("     LOCKED     "); // На вторую строчку пишем "LOCKED"
  pinMode(led, OUTPUT); // Устанавливаем ПинМод для 13 пина
}


Так же создадим функцию для программной перезагрузки Ардуино:

// RESET FUNC
void(* resetFunc) (void) = 0;


Создаем функцию loop(), она является самой главной частью нашей программы:

// LOOP
void loop()
{
 button = getPressedButton(); // Присваиваем кнопке значение
 if(button!=0 && button!=5){ // Что-то нажали
  userInputs[codeIndex]=button; // Запомнили что нажали
  delay(250); // Защита от дребезга кнопок
  codeIndex++; // Ждем следующую кнопку
 if(codeIndex >= 4){ // Пользователь ввел код целиком
  if (userInputs[0] == doorPass[0] &&
      userInputs[1] == doorPass[1] &&  // Сверка массивов
      userInputs[2] == doorPass[2] &&  // Проверка кода на правильность
      userInputs[3] == doorPass[3]) {
        lcd.setCursor(0,1);
        lcd.print(" Access Granted ");
        digitalWrite(led, HIGH);   // turn the LED on (HIGH is the voltage level)
        delay(3000);               // wait for a 3 second
        lcd.setCursor(0, 1);
        lcd.print("     LOCKED     ");
        digitalWrite(led, LOW);    // turn the LED off by making the voltage LOW
        userInputs[0] = 0;
        userInputs[1] = 0;
        userInputs[2] = 0;  // Обнуляем введеные цифры
        userInputs[3] = 0;
        userInputs[4] = 0;
        resetFunc();
      } else {
        lcd.setCursor(0,1);
        lcd.print(" Access Denied! ");
        userInputs[0] = 0;
        userInputs[1] = 0;
        userInputs[2] = 0;  // Обнуляем введеные цифры
        userInputs[3] = 0;
        userInputs[4] = 0;
        delay(3000);
        resetFunc();
    }
   }
  }
 }


У вас должен получиться приблизительно такой код:

// Библиотеки
#include <LiquidCrystal.h> // Библиотека LCD
LiquidCrystal lcd(8, 9, 4, 5, 6, 7 ); // Объявим к камим пинам подключен LCD
// Переменные
int button; // Кнопка
int codeIndex = 0; // Хранение последовательности ввода чисел
int led = 13; //  LED
int userInputs[4]; // Массив для сохранения в нем вводимых чисел с KeyPad
int doorPass[4] = {1,2,3,4}; // Пароль для "двери"
// Кнопки
const int BUTTON_NONE   = 0; 
const int BUTTON_RIGHT  = 1;
const int BUTTON_UP     = 2; // Комментарии излишни
const int BUTTON_DOWN   = 3; // думаю,что сдесь все понятно.
const int BUTTON_LEFT   = 4;
const int BUTTON_SELECT = 5;
// Получение значения кнопки
int getPressedButton()
{
  int buttonValue = analogRead(0);
  if (buttonValue < 100) {
    return BUTTON_RIGHT;  
  }
  else if (buttonValue < 200) {
    return BUTTON_UP;
  }
  else if (buttonValue < 400){
    return BUTTON_DOWN;
  }
  else if (buttonValue < 600){
    return BUTTON_LEFT;
  }
  else if (buttonValue < 800){
    return BUTTON_SELECT;
  }
  return BUTTON_NONE;
}
// SETUP
void setup()
{
  Serial.begin(9600); // Задаем скорость порта
  lcd.begin(16, 2); // В моем LCD 2 строчки по 16 символов          
  lcd.print("   ENTER PIN   "); // На первой строчку пишем "ENTER PIN"
  lcd.setCursor(0, 2);  // Устанавливаем курсор на 1 символ 2-ой строки
  lcd.print("     LOCKED     "); // На вторую строчку пишем "LOCKED"
  pinMode(led, OUTPUT); // Устанавливаем ПинМод для 13 пина
}
// RESET FUNC
void(* resetFunc) (void) = 0;
// LOOP
void loop()
{
 button = getPressedButton(); // Присваиваем кнопке значение
 if(button!=0 && button!=5){ // Что-то нажали
  userInputs[codeIndex]=button; // Запомнили что нажали
  delay(250); // Защита от дребезга кнопок
  codeIndex++; // Ждем следующую кнопку
 if(codeIndex >= 4){ // Пользователь ввел код целиком
  if (userInputs[0] == doorPass[0] &&
      userInputs[1] == doorPass[1] &&  // Сверка массивов
      userInputs[2] == doorPass[2] &&  // Проверка кода на правильность
      userInputs[3] == doorPass[3]) {
        lcd.setCursor(0,1);
        lcd.print(" Access Granted ");
        digitalWrite(led, HIGH);   // turn the LED on (HIGH is the voltage level)
        delay(3000);               // wait for a 3 second
        lcd.setCursor(0, 1);
        lcd.print("     LOCKED     ");
        digitalWrite(led, LOW);    // turn the LED off by making the voltage LOW
        userInputs[0] = 0;
        userInputs[1] = 0;
        userInputs[2] = 0;  // Обнуляем введеные цифры
        userInputs[3] = 0;
        userInputs[4] = 0;
        resetFunc();
      } else {
        lcd.setCursor(0,1);
        lcd.print(" Access Denied! ");
        userInputs[0] = 0;
        userInputs[1] = 0;
        userInputs[2] = 0;  // Обнуляем введенные цифры
        userInputs[3] = 0;
        userInputs[4] = 0;
        delay(3000);
        resetFunc();
    }
   }
  }
 }


Все! Теперь скорее загружаем наш скетч в контроллер.

Step 4

Давайте протестируем наш замок.
Включаем плату:

image

Давайте введем правильный пароль:

image

А теперь неправильный:

image

Дальнейшие планы:
1. Сделать запись и чтение пароля из EPROM и наконец-то добавить серву.
2. Сделать меню для смены пароля.
3. Сделать дополнительный длинный сервисный пароль, который в случае изменения пароля двери злоумышленником, поможет его изменить (и себя тоже).
4. Сделать логирование введенных паролей, как правильных, так и неправильных, даты и времени.
5. Добавить звуков.

P.S. Изначально я планировал использовать вместо светодиода — серву, но к сожалению наша почта России… да вы и сами все знаете.
P.P.S. Статья со временем будет дополняться и изменяться, в лучшую сторону конечно.
Tags:
Hubs:
You can’t comment this post because its author is not yet a full member of the community. You will be able to contact the author only after he or she has been invited by someone in the community. Until then, author’s username will be hidden by an alias.