Безопасность с каждым годом играет все более значимую роль в современном обществе. Кодовые замки, датчики движения, радиочастотные метки, лазерные системы – это лишь неполный перечень элементов, применяющихся в современных системах безопасности.
В данной статье мы рассмотрим простейший кодовый замок на основе платы Raspberry Pi, в котором пароль доступа будет вводиться с помощью модуля цифровой клавиатуры. Ранее на нашем сайте мы уже рассматривали создание подобного кодового замка на основе платы Arduino.
Необходимые компоненты
- Плата Raspberry Pi (с установленной SD картой) (купить на AliExpress).
- Модуль клавиатуры (Keypad Module) (купить на AliExpress).
- Зуммер (Buzzer) (купить на AliExpress).
- ЖК дисплей 16x2 (купить на AliExpress).
- Резистор 1 кОм (купить на AliExpress).
- Блок резисторов 10 кОм.
- Потенциометр 10 кОм (купить на AliExpress).
- Светодиод (купить на AliExpress).
- CD/DVD привод, который будет использоваться в качестве двери/ворот.
- Источник питания с напряжением 5 В.
- Батарейка на 12 В.
- Микросхема драйвера двигателя L293D (купить на AliExpress).
- Макетная плата.
- Соединительные провода.
Реклама: ООО "АЛИБАБА.КОМ (РУ)" ИНН: 7703380158
Подключение клавиатуры 4x4 к Raspberry Pi
В данном проекте мы для подключения клавиатуры (клавишной панели) 4x4 к плате Raspberry Pi будем использовать технологию мультиплексирования. Суть ее заключается в следующем. Наша клавиатура 4х4 содержит 16 кнопок (клавиш). В обычном режиме нам для их подключения понадобилось бы 16 контактов, но с использованием технологии мультиплексирования мы задействуем для этой цели всего 8 контактов.
Поэтому технология мультиплексирования является эффективным способом экономии выводов микроконтроллера. Основной принцип этой технологии заключается в том, что сначала сканируется строка, а затем столбец. В программе аналогичного кодового замка на Arduino мы использовали специальную библиотеку для работы с клавиатурой (#include <Keypad.h>), поэтому нам не нужно было заморачиваться с ручным (самостоятельным) программированием технологии мультиплексирования. Но в этом проекте мы не будем использовать никакой подобной библиотеки и вручную, "коротким" способом запрограммируем технологию мультиплексирования.
Схема проекта
Схема цифрового кодового замка на Raspberry Pi представлена на следующем рисунке.
Как видите, схема достаточно проста и содержит плату Raspberry Pi, модуль клавиатуры, зуммер, DVD/CD привод в качестве ворот и ЖК дисплей. В этой схеме плата Raspberry Pi управляет всеми процессами в схеме: ввода пароля с клавиатуры, сравнение паролей, включение/выключение зуммера, открытие/закрытие ворот и отображение статусных сообщений на ЖК дисплее. Клавиатура (Keypad) используется для ввода пароля. Зуммер используется для целей индикации. ЖК дисплей используется для отображения информации о состоянии замка.
Контакты столбцов клавиатуры непосредственно подключены к контактам GPIO 22, 23, 24, 25 платы Raspberry Pi, а контакты строк клавиатуры – к контактам 21, 14, 13, 12 платы. ЖК дисплей подключен к Raspberry Pi в 4-битном режиме. Контакты управления ЖК дисплеем RS, RW и En непосредственно подключены к контактам 11, GND и 10 платы Raspberry Pi. Контакты данных ЖК дисплея D4-D7 подключены к контактам GPIO 6, 15, 4 и 1 платы Raspberry Pi, а зуммер подключен к ее контакту 8. Драйвер двигателей L293D подключен к контактам 28 и 29 платы. Батарея 12 В подключена к контакту 8 микросхемы L293D.
Объяснение работы проекта
Принцип работы рассматриваемого нами цифрового кодового замка достаточно прост. После запуска программы на Raspberry Pi на экране ЖК дисплея показывается приветственное сообщение, после этого на нем в первой строке показывается сообщение “A- Input Password” (введите пароль), а на второй – “B- Change Passkey” (измените пароль). После этого пользователь должен нажать одну из кнопок на клавиатуре – A или B.
Теперь, если пользователь хочет открыть ворота/замок, он должен нажать ‘A’ на клавиатуре, после чего система попросит его ввести пароль. Пароль по умолчанию – “1234”. Пользователь вводит пароль и система проверяет корректен он или нет:
- Если пользователь ввел правильный пароль, то система открывает ворота/замок.
- Если пользователь ввел неправильный пароль, то включается зуммер и на экране дисплея высвечивается сообщение “Access Denied” (доступ запрещен).
Структурная схема взаимодействия элементов проекта показана на следующем рисунке.
Если пользователь хочет изменить пароль, то ему необходимо нажать на клавиатуре клавишу ‘B’, после чего система попросит его ввести текущий пароль (“Current Password” или “Current Passkey”). Пользователь вводит пароль и система проверяет его на корректность:
- Если пароль правильный, то система предложит пользователю ввести новый пароль (“New Password”).
- Если пароль неправильный, то включается зуммер и на экране ЖК дисплея показывается сообщение о неправильно введенном пароле (“Wrong Password”). После этого пользователь должен заново повторить весь процесс чтобы изменить пароль.
Открытие и закрытие ворот/замка в нашем проекте – это ничто иное как вращение двигателя по часовой и против часовой стрелки. Для простого проекта можно использовать обычный двигатель постоянного тока, также можно применить и сервомотор или шаговый двигатель, однако в этом случае понадобится немного изменить код программы.
Также можно улучшить этот проект замка если использовать настоящий электронный замок (например, такой, какой был использован в этой статье). В своем составе он имеет электромагнит, который удерживает дверь в закрытом состоянии когда по его обмотке не протекает тока. Когда же на его обмотку подается ток, то замок втягивает личинку внутрь себя и, таким образом, дверь открывается.
Объяснение программы для Raspberry Pi
Полный код программы приведен в конце статьи, здесь же мы кратко рассмотрим его основные фрагменты.
Программа для данного проекта написана на языке C, поэтому она во многом похожа на аналогичные программы для плат Arduino. Для написания этой программы необходимо также установить библиотеку wiringPi для работы с контактами ввода/вывода (GPIO).
Первым делом в программе нам необходимо подключить используемые библиотеки и определить (задать) контакты, к которым подключены ЖК дисплей, зуммер, светодиод и микросхема драйвера двигателей.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
#include<wiringPi.h> #include<string.h> #include<stdio.h> #define buzz 8 #define m1 29 #define m2 28 #define led 27 #define RS 11 #define EN 10 #define D4 6 #define D5 5 #define D6 4 #define D7 1 |
После этого мы с помощью массивов зададим номера контактов, к которым подключены строки и столбцы клавиатуры и зададим массив для хранения пароля.
1 2 3 4 5 6 7 8 9 10 11 12 |
char pass[4]; char pass1[]={'1','2','3','4'}; int n=0; char row[4]={21, 14, 13, 12}; char col[4]={22, 23, 24, 25}; char num[4][4]={ {'1','2','3','A'}, {'4','5','6','B'}, {'7','8','9','C'}, {'*','0','#','D'} }; |
Затем мы запрограммируем несколько функций для работы с ЖК дисплеем. Функция void lcdcmd будет использоваться для передачи команд на ЖК дисплей, функция void write – для передачи данных на ЖК дисплей, а функция void print – для передачи строки на ЖК дисплей.
1 2 3 4 5 6 7 8 |
void print(char *str) { while(*str) { write(*str); str++; } } |
Функция void setCursor используется для установки позиции курсора на экране ЖК дисплея.
1 2 3 4 5 6 7 8 9 |
void setCursor(int x, int y) { int set=0; if(y==0) set=128+x; if(y==1) set=192+x; lcdcmd(set); } |
Функция void clear() используется для очистки экрана ЖК дисплея, а функция void buzzer() – для включения сигнала зуммера.
Функции void gate_open(), void gate_stop() и void gate_close() используются для управления воротами/замком (CD приводом).
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 |
void gate_open() { digitalWrite(m1, LOW); digitalWrite(m2, HIGH); delay(2000); } void gate_stop() { digitalWrite(m1, LOW); digitalWrite(m2, LOW); delay(2000); } void gate_close() { digitalWrite(m1, HIGH); digitalWrite(m2, LOW); delay(2000); } |
Следующая функция используется для инициализации ЖК дисплея в 4-битном режиме.
1 2 3 4 5 6 7 8 |
void begin(int x, int y) { lcdcmd(0x02); lcdcmd(0x28); lcdcmd(0x06); lcdcmd(0x0e); lcdcmd(0x01); } |
Функция void keypad() используется для подключения клавиатуры к плате Raspberry Pi по "упрощенному варианту".
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
void keypad() { int i,j; int x=0,k=0; delay(2000); while(k<4) { for(i=0;i<4;i++) { digitalWrite(col[i], LOW); for(j=0;j<4;j++) { if(digitalRead(row[j])==0) { setCursor(x,1); .... ...... ..... ...... |
Исходный код программы на C
К коду программы комментариев нет, но отдельные ее части подробно обсуждены в предыдущей части статьи.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 |
#include<wiringPi.h> #include<string.h> #include<stdio.h> #define buzz 8 #define m1 29 #define m2 28 #define led 27 #define RS 11 #define EN 10 #define D4 6 #define D5 5 #define D6 4 #define D7 1 char pass[4]; char pass1[]={'1','2','3','4'}; int n=0; char row[4]={21, 14, 13, 12}; char col[4]={22, 23, 24, 25}; char num[4][4]={ {'1','2','3','A'}, {'4','5','6','B'}, {'7','8','9','C'}, {'*','0','#','D'} }; void keypad(); void buzzer(); void lcdcmd(unsigned int ch) { int temp=0x80; digitalWrite(D4, temp & ch<<3); digitalWrite(D5, temp & ch<<2); digitalWrite(D6, temp & ch<<1); digitalWrite(D7, temp & ch); digitalWrite(RS, LOW); digitalWrite(EN, HIGH); delay(10); digitalWrite(EN, LOW); digitalWrite(D4, temp & ch<<7); digitalWrite(D5, temp & ch<<6); digitalWrite(D6, temp & ch<<5); digitalWrite(D7, temp & ch<<4); digitalWrite(RS, LOW); digitalWrite(EN, HIGH); delay(10); digitalWrite(EN, LOW); } void write(unsigned int ch) { int temp=0x80; digitalWrite(D4, temp & ch<<3); digitalWrite(D5, temp & ch<<2); digitalWrite(D6, temp & ch<<1); digitalWrite(D7, temp & ch); digitalWrite(RS, HIGH); digitalWrite(EN, HIGH); delay(10); digitalWrite(EN, LOW); digitalWrite(D4, temp & ch<<7); digitalWrite(D5, temp & ch<<6); digitalWrite(D6, temp & ch<<5); digitalWrite(D7, temp & ch<<4); digitalWrite(RS, HIGH); digitalWrite(EN, HIGH); delay(10); digitalWrite(EN, LOW); } void clear() { lcdcmd(0x01); } void setCursor(int x, int y) { int set=0; if(y==0) set=128+x; if(y==1) set=192+x; lcdcmd(set); } void print(char *str) { while(*str) { write(*str); str++; } } void begin(int x, int y) { lcdcmd(0x02); lcdcmd(0x28); lcdcmd(0x06); lcdcmd(0x0e); lcdcmd(0x01); } void enter() { clear(); print("Current Passkey:"); setCursor(0,1); keypad(); if(strncmp(pass,pass1,4)==0) { clear(); print("Enter New Passkey"); setCursor(0,1); keypad(); for(n=0;n<4;n++) pass1[n]=pass[n]; clear(); print("Passkey Changed."); delay(3000); return; } else { clear(); print("Wrong Passkey"); setCursor(0,1); print("Try again later"); digitalWrite(led, HIGH); buzzer(); buzzer(); buzzer(); buzzer(); delay(2000); digitalWrite(led, LOW); return; } } void gate_open() { digitalWrite(m1, LOW); digitalWrite(m2, HIGH); delay(2000); } void gate_stop() { digitalWrite(m1, LOW); digitalWrite(m2, LOW); delay(2000); } void gate_close() { digitalWrite(m1, HIGH); digitalWrite(m2, LOW); delay(2000); } void choice() { digitalWrite(col[0], LOW); digitalWrite(col[1],HIGH); if(digitalRead(row[3])==0) { buzzer(); clear(); print("Enter Passkey:"); setCursor(0,1); keypad(); if(strncmp(pass,pass1,4)==0) { clear(); print(" Welcome"); setCursor(0,1); print("Access Granted"); gate_open(); gate_stop(); gate_close(); gate_stop(); return; } else { clear(); print("Access Denied"); setCursor(0,1); print("Try again later"); digitalWrite(led, HIGH); digitalWrite(buzz, HIGH); delay(3000); digitalWrite(led, LOW); digitalWrite(buzz, LOW); return; } } digitalWrite(col[0], HIGH); digitalWrite(col[1], LOW); if(digitalRead(row[3])==0) { buzzer(); enter(); } } void setup() { if(wiringPiSetup()==-1) printf("Error"); pinMode(RS, OUTPUT); pinMode(EN, OUTPUT); pinMode(D4, OUTPUT); pinMode(D5, OUTPUT); pinMode(D6, OUTPUT); pinMode(D7, OUTPUT); pinMode(m1, OUTPUT); pinMode(m2, OUTPUT); pinMode(led, OUTPUT); pinMode(buzz, OUTPUT); for(n=0;n<4;n++) pinMode(row[n], INPUT); for(n=0;n<4;n++) pinMode(col[n], OUTPUT); for(n=0;n<4;n++) digitalWrite(col[n], HIGH); } void main(void) { setup(); begin(16,2); print("Electronic Door"); setCursor(0,1); print("Lock Using RPI "); delay(2000); clear(); print("Circuit Digest"); setCursor(0,1); print("Raspberry Pi"); delay(2000); clear(); while (1) { setCursor(0,0); //keypad(); print("A-Input Password"); setCursor(0,1); print("B-Change Passkey"); choice(); } } void buzzer() { digitalWrite(buzz, HIGH); delay(200); digitalWrite(buzz, LOW); } void keypad() { int i,j; int x=0,k=0; delay(2000); while(k<4) { for(i=0;i<4;i++) { digitalWrite(col[i], LOW); for(j=0;j<4;j++) { if(digitalRead(row[j])==0) { setCursor(x,1); write(num[i][j]); buzzer(); setCursor(x,1); write('*'); x++; pass[k++]=num[i][j]; while(digitalRead(row[j])==0); } } digitalWrite(col[i], HIGH); } } } |