Предыстория:
Однажды вечером, в незапамятные времена, на Хабре я увидел несколько статей по Ардуинке… и знаете что? Я тоже захотел такую штуку
На следующий день незамедлительно были заказаны с eBay:
1. Funduino Mega2560
2. LCD KeyPad Shield
Как мне показалось, этого комплекта хватит не на долго… Так и оказалось. За пару дней Ардуина и Шилд были измучены и оставлены лежать в одиночестве, в ожидании новой партии комплектующих с eBay.
Step 1
Плавным движением руки одеваем наш LCD KeyPad Shield на Мегу. У нас получается вот такой «бутерброд»:
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
Давайте протестируем наш замок.
Включаем плату:
Давайте введем правильный пароль:
А теперь неправильный:
Дальнейшие планы:
1. Сделать запись и чтение пароля из EPROM и наконец-то добавить серву.
2. Сделать меню для смены пароля.
3. Сделать дополнительный длинный сервисный пароль, который в случае изменения пароля двери злоумышленником, поможет его изменить (и себя тоже).
4. Сделать логирование введенных паролей, как правильных, так и неправильных, даты и времени.
5. Добавить звуков.
P.S. Изначально я планировал использовать вместо светодиода — серву, но к сожалению наша почта России… да вы и сами все знаете.
P.P.S. Статья со временем будет дополняться и изменяться, в лучшую сторону конечно.