Необычный кодовый замок на Arduino

Ардуино — идеальная платформа для быстрого прототипирования. Много дурацких, но интересных идей без неё явно не реализовались бы. Вот давно зрела у меня идея какого-нибудь хитрого кодового замка — например, где кодом было бы время удерживания кнопки. Суть в том, что такой замок трудно вскрыть, даже зная в точности пароль — те, кто им успешно пользуются, выдерживаю интервалы, используя мышечную память, которой у злоумышленника явно не будет. Ну это в теории, конечно.

Я уже даже был готов взять генератор прямоугольных импульсов, 3 десятеричных счётчика и ещё ворох какой-то логики, чтобы это всё собрать… Но даже в smd это выглядело бы слишком громоздко и неудобно для практического использования. Но идея вертелась в голове и зрела… Избавиться от неё удалось, только написав прогу под Ардуино, превращающую её в кодовый замок, в котором одом является не номер нажатой кнопки (как в обычных), а сочетание кнопок, нажатых одновременно. Нигде раньше не встречал такого решения, если встретите — сообщите 🙂

Схема проста до безобразия. (код, впрочем, тоже )

Не очень хорошо видно, но кнопки подключаются к: а) земле и D3 (третий цифровой пин), b) D5 и D7 c) D9 и D11.

Кстати, fritzing оказалась удобной программой для создания таких рисунков — очень быстро, просто и наглядно. Не зря все уроки по ардуине с его помощью проиллюстрированы.

Вот и код:

 const int ina = 3; const int inb = 5; const int inc = 9; const int ledPin = 13;       int i = 1000; byte a = 0; byte b = 0; byte c = 0; byte d = 0; unsigned long time = 0;              //не забывайте всё, что принимает значение millis() unsigned long temp = 0;              //хранить в unsigned long byte keya[] = {  0, 0, 0, 0, 0, 0, 0, 0};   //коды собственно byte keyb[] = {  1, 1, 1, 1, 0, 1, 0, 0}; byte keyc[] = {  1, 0, 1, 0, 1, 1, 1, 0}; byte k = 0;  void setup() {   pinMode(ina, INPUT_PULLUP);   //3 входа, подключаемые к кнопкам   pinMode(inb, INPUT_PULLUP);   pinMode(inc, INPUT_PULLUP);   pinMode(ledPin, OUTPUT);      //встроенный светодиод на 13-ом пине   pinMode(7, OUTPUT);   pinMode(11, OUTPUT);   digitalWrite(7, LOW);           //заменяют землю   digitalWrite(11, LOW);   time = millis();                //нужно для отсчёта времени }  void blinktwice() { //двойное мигание светодиодом   digitalWrite(ledPin, HIGH);   delay(100);   digitalWrite(ledPin, LOW);   delay(100);   digitalWrite(ledPin, HIGH);   delay(100);   digitalWrite(ledPin, LOW);   delay(200); }  void loop() {   if(k==0) {     blinktwice(); //приглашение ввести код   }   if (k == 8) {     digitalWrite(ledPin, HIGH);     delay(3000);     k = 0;   }   a = digitalRead(ina);       //считываются уровни сигналов с кнопок - нажата/не нажата   b = digitalRead(inb);   c = digitalRead(inc);   delay(100);  //следующий if - защита против ложных срабатываний, можно не использовать   if((digitalRead(ina) == a)&&(digitalRead(inb) ==b)&&(digitalRead(inc)==c)) {     if (a == keya[k]) {       if (b == keyb[k]) {         if (c == keyc[k]) {            k++;         }       }     }   }   if (k==1) {     if (d ==0) {       time = millis ();       d++;     }   }   temp = millis();   temp = temp - time;   if (temp > 10000) {     k= 0;     d=0;     time = millis ();   } } 

И раз уж на то пошло, объясню всё так, чтобы ни у кого не осталось вопросов. В setup() стандартно — назначение портов и установка низкого уровня на тех, кому предстоит заменять землю. INPUT_PULLUP — это значит что пин подтянут к +5В внутренним резистором (10 кОм, вроде). Это позволяет избежать «плавающего» сигнала на нём и не коротнуть чего лишнего при замыкании кнопкой на землю. blinktwice выделен в отдельную функцию ради удобства — никогда не упускайте возможности попрактиковаться в использовании функций! Далее считываются уровни сигнала на портах (они будут LOW, т.е 0, когда кнопка нажата, и 1, когда не нажата), и сравниваются с записанными в массивах значениями — например нулевые значения 0,1,1 означают, что первая кнопка должна быть нажата, а две других обязательно отжаты. Если условие выполняется, происходит переход к следующим значениям. Когда все 7 последовательных условий выполнились, выполняется условие k==8 и светодиод загорается на 3 секунды, сигнализируя о правильности введённого кода. В этот кусок кода надо вписывать то, что и должно происходить при этом — открытие двери, звуковой сигнал и т.д.

Оставшийся кусок кода сбрасывает счётчик, если с момента первого введения комбинации (при этом гаснет светодиод) прошло больше 10 секунд. Без этого было бы в принципе возможно перебрать все последовательности нажатых кнопок, хотя их число составляет (2^3)^7 = 2^21, что больше двух миллионов. Очень полезно помнить при этом, что в году всего лишь 31 миллион секунд. А время введения правильного кода — 5 секунд после небольшой тренировки, так что можно ещё зажать по времени. Мне пока не на ком тестировать систему, но если кому система понравится настолько, чтобы воплотить её в жизнь — пожалуйста, напишите о результатах!