Незвичайний кодовий замок на 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 секунд после небольшой тренировки, так что можно ещё зажать по времени. Мне пока не на ком тестировать систему, но если кому система понравится настолько, чтобы воплотить её в жизнь - пожалуйста, напишите о результатах!

Прикрепленные файлы:

Top