Безопасность является одной из основных проблем в нашей повседневной жизни и цифровые замки стали важной частью различных систем безопасности. Существует много типов систем безопасности, доступных в настоящее время. К примеру, системы безопасности на основе датчиков движения, на основе радиочастотных меток, цифровые кодовые замки, замки управляемые со смартфона и т.д. В этой статье мы рассмотрим проект “умного” цифрового замка на основе платы Arduino, способного распознавать характер стуков в дверь. Замок будет открывать дверь только тогда, когда характер стуков будет соответствовать определенному образцу (шаблону). Для лучшего понимания работы проекта рекомендуется посмотреть видео, приведенное в конце статьи.
Необходимые компоненты
- Плата Arduino Uno (купить на AliExpress).
- Серводвигатель (сервомотор) (купить на AliExpress).
- Зуммер (Buzzer) (купить на AliExpress).
- Резистор 1 МОм (купить на AliExpress).
- Кнопка.
- Источник питания.
- Соединительные провода.
- Коробка.
Реклама: ООО "АЛИБАБА.КОМ (РУ)" ИНН: 7703380158
Работа схемы
Схема устройства представлена на следующем рисунке.
Как видите, схема нашего “умного детектора стуков” достаточно проста и содержит плату Arduino, управляющую всем процессом, кнопку, зуммер (buzzer) и сервомотор. Плата Arduino принимает пароль (образец стука) от зуммера (или датчика), сравнивает его с заданными шаблонами (образцами), дает команду сервомотору на открытие/закрытие двери и сохраняет образец (шаблон) стука.
Кнопка подключена к контакту D7 платы Arduino, второй контакт кнопки замкнут на землю. Зуммер при помощи параллельно включенного ему резистора на 1 МОм подключен к аналоговому контакту A0 платы Arduino. Сервомотор подключен к цифровому контакту D3 платы Arduino и будет управляться при помощи широтно-импульсной модуляции, доступной на данном контакте.
Запись образца стука в Arduino
В нашем проекте мы использовали зуммер или пьезоэлектрический датчик (Peizo Sensor) для обнаружения стука. Кнопка используется для считывания входа датчика и для сохранения образца стука в плату Arduino. Идея проекта похожа на код Морзе, но не в точности соответствует ему.
Мы использовали картонную коробку для демонстрации работы проекта. Чтобы считать значения с выхода зуммера мы должны стучать в коробку после нажатия кнопки. Анализируется время между стуками, большее или меньше 500 мс – это значение можно поменять в программе. Более подробно смотрите в видео в конце статьи.
Когда мы начинаем стучать плата Arduino начинает анализировать (мониторить) время от первого стука до второго стука и потом записывать это значение времени в массив. В нашем проекте мы использовали 6 стуков (можно поменять в программе), то есть мы будем считывать значения 5 временных промежутков.
Затем мы будем анализировать интервалы времени между всеми 6 стуками. Сначала мы проверим временной интервал между первым и вторым стуками и если он будет меньше 500 мс, то мы запишем в соответствующую переменную 0, а если больше 500 мс – то в эту переменную мы запишем 1. После этого мы будем проверять временной интервал между вторым и третьим стуками и т.д. В результате мы получим 5 цифр в двоичном формате (0 или 1).
Объяснение работы проекта
Сначала мы должны сохранить образец стука в системе (нашем замке). Для этого мы должны нажать и удерживать кнопку до тех пор пока не постучим 6 раз (можно изменить это количество стуков в программе). После 6 стуков плата Arduino сохраняет этот образец стука в EEPROM (энергонезависимую память). После этого, чтобы открыть замок с помощью стуков, мы должны быстро нажать и отпустить кнопку, после чего постучать 6 раз. Если образец (шаблон) наших 6 стуков совпадет с образцом, хранящимся в EEPROM, то плата Arduino откроет дверь.
Примечание: когда мы нажимаем или нажимаем и держим кнопку плата Arduino запускает 10-секундный таймер чтобы “принять” 6 стуков. То есть все стуки необходимо сделать в течение этого 10-секундного интервала. Для более детальной информации можно открыть монитор последовательного порта и посмотреть в нем лог событий.
Объяснение работы программы
В программе нам первым делом необходимо подключить заголовочные файлы, инициализировать входные и выходные контакты и объявить необходимые переменные – все это можно увидеть в полном тексте программы в конце статьи.
После этого в функции setup мы задаем направление работы используемых контактов и инициализируем сервомотор.
1 2 3 4 5 6 7 |
void setup() { pinMode(sw, INPUT_PULLUP); //с внутренним подтягивающим резистором myServo.attach(servoPin); myServo.write(180); Serial.begin(9600); } |
После этого мы считываем образец стука и сохраняем его значение в массив.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
void loop() { int i=0; if(digitalRead(sw) == LOW) { Serial.println("Start"); delay(1000); long stt= millis(); while(millis()<(stt+patternInputTime)) { int temp=analogRead(A0); if(temp>sensitivity && flag==0 && i<=patternLenth) { .... . ..... .... |
После этого мы декодируем входной образец стука.
1 2 3 4 5 6 7 8 9 |
for(int i=0;i<patternLenth;i++) { knok=1; if(slot[i+1]-slot[i] <500 ) pattern[i]=0; else pattern[i]=1; Serial.println(pattern[i]); } |
После этого сохраняем его если кнопка все еще нажата.
1 2 3 4 5 6 |
if(digitalRead(sw) == 0) { for(int i=0;i<patternLenth;i++) EEPROM.write(i,pattern[i]); while(digitalRead(sw) == 0); } |
А если кнопка уже не нажата, то плата Arduino будет сравнивать входной образец стуков с сохраненным образцом.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 |
else { if(knok == 1) { for(int i=0;i<patternLenth;i++) { if(pattern[i] == EEPROM.read(i)) { Serial.println(acceptFlag++); } else { Serial.println("Break"); break; } } } |
Если образцы стуков (пароли) совпадают, то плата Arduino дает команду сервомотору открыть ворота (дверь), иначе ничего не происходит, но результат этого все равно можно посмотреть в окне монитора последовательной связи (serial monitor).
1 2 3 4 5 6 7 8 9 10 11 |
Serial.println(acceptFlag); if(acceptFlag >= patternLenth-1) { Serial.println(" Accepted"); myServo.write(openGate); delay(5000); myServo.write(closeGate); } else Serial.println("Rejected"); } |
Исходный код программы
Если у вас возникнут какие либо вопросы по тексту данной программы, то вы можете задать их в комментариях к данной статье.
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 |
#include<EEPROM.h> // библиотека для работы с памятью EEPROM #include<Servo.h> // библиотека для работы с сервомотором #define patternLenth 5 #define patternInputTime 10000 // время за которое нужно сделать стуки #define sensitivity 80 // чувствительность #define margin 100 #define sw 7 #define servoPin 3 // к этому контакту подключен сервомотор #define openGate 0 #define closeGate 180 long slot[patternLenth+1]; int pattern[patternLenth]; int flag=0; int acceptFlag=0; int knok; Servo myServo; void setup() { pinMode(sw, INPUT_PULLUP); myServo.attach(servoPin); myServo.write(180); Serial.begin(9600); } void loop() { int i=0; if(digitalRead(sw) == LOW) { Serial.println("Start"); delay(1000); long stt= millis(); while(millis()<(stt+patternInputTime)) { int temp=analogRead(A0); if(temp>sensitivity && flag==0 && i<=patternLenth) { delay(10); flag=1; slot[i++]=millis()-stt; //Serial.println(slot[i-1] - stt); if(i>patternLenth) break; } else if(temp == 0) flag=0; } long stp=millis(); Serial.println("Stop"); // Serial.println(stp-stt); for(int i=0;i<patternLenth;i++) { knok=1; if(slot[i+1]-slot[i] <500 ) pattern[i]=0; else pattern[i]=1; Serial.println(pattern[i]); } if(digitalRead(sw) == 0) { for(int i=0;i<patternLenth;i++) EEPROM.write(i,pattern[i]); while(digitalRead(sw) == 0); } else { if(knok == 1) { for(int i=0;i<patternLenth;i++) { if(pattern[i] == EEPROM.read(i)) { Serial.println(acceptFlag++); } else { Serial.println("Break"); break; } } } Serial.println(acceptFlag); if(acceptFlag >= patternLenth-1) { Serial.println(" Accepted"); myServo.write(openGate); delay(5000); myServo.write(closeGate); } else Serial.println("Rejected"); } for(int i=0;i<patternLenth;i++) { pattern[i]=0; slot[i]=0; } slot[i]=0; acceptFlag=0; } } |
Arduino IDE РУГАЕТСЯ на ваши скетчи. пофиксите плиз
На что конкретно ругается?