Бескнопочный кодовый замок

Сама идея о создании кодового замка пришла после прочтения статьи «кодовый замок без кнопок» в журнале радио №7 2011г.
В основе устройства автор использовал микроконтролер PIC12F675, в качестве индикации состояния замка два светодиода красный и зеленый.
А так как я с недавних пор стал поклоником аrduino то решил написать скетч и создать похожее устройство на его базе. Схема простая минимум деталей. В качестве микроконтролера для arduino использовал ATMEGA8.

Необычность замка заключается в том, что ввод кода производится не с помощью стандартных кнопок а поворотом ручки переменного резистора, как на «модных» сейфах.
Панель ввода.
На передней панели устройства или дверях закрепляется резистор, рисуется шкала от 0 до 9 и желательно
надеть ручку с указателем чтобы выбирать нужные цифры, которые и будут нашим кодом. Для построения шкалы я использовал
скетч для вывода значения потенциометра в порт она есть в примерах. Только значение с вывода А0 разделить на 113(1023/113=9).
void setup() {
  Serial.begin(9600);
}

void loop() {
  int sensorValue = analogRead(A0)/113;
  Serial.println(sensorValue, DEC);
  delay(500);
}

Резистор использовал старый совковый СП1 со старого телевизора на 10кОм, главное чтобы сопротевление изменялось по
линейной зависимости от поворота ручки.Так шкала будет равномерной и красивой. Вот что у меня получилось(не так чтобы красиво, но все же).



Основная программа
Для того чтобы удобнее было пользоваться замком добавил дисплей 16*2 который подключил стандартно с помощью библиотеки LiquidCrystal.
При включении питания на дисплей выводится «Code_zamok V2.1»«loading...»(версия 2.1 потому что до етого я сделал кодовый замок
такой же но без дисплея. И поэтому что избежать путаницы назвал его так).Далее на транзисторный ключ подается LOW чтобы после
перезапуска программы замок случайно не был открыт. И соответствено на дисплей пишем «closed!!!» Для ввода кода нужно покрутить
резистором после чего звучит один сигнал(2сек) и на дисплее пишет «enter code». В моем варианте код 5-тизначный, но
как говорят, по желанию клиента можна и три, можна и десять. Выставляем ручку на первую нужную цифру
после чего звучит один сигнал(0.5сек), на екран выводится выбраное значение, которое через полсекунды меняется на "*"(так сделано во многих замках), это значит что первая цифра кода введена.Для ввода следующих цифр делаем также. Время на ввод каждой цифры 3 сек. Сначала
делал большую задержку но потом после ряда експериментов понял, что 3 сек вполне достаточно. Итак ввели 5 цифру кода после чего
звучит один длиный сигнал, значит код введен.Если код правельный на екран выводится «access granted !!!», подается
высокий уровень на транзисторный ключ и надпись на дисплей «open!!!». В противном случаи выводится «access denied», звучит преривистый сигнал
и надпись «closed!!!
Для того чтобы закрыть замок нужно покрутить ручкой резистора, после чего он вернется в исходное состояние.
#include <EEPROM.h>
#include <LiquidCrystal.h>
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

#define rele 13
#define button 8
#define podsvetka 9
int x;
int v;

byte val;
byte val1;

int code1;
int code2;
int code3;
int code4;
int code5;

int in_code1;
int in_code2;
int in_code3;
int in_code4;
int in_code5;

byte code1_prov;
byte code2_prov;
byte code3_prov;
byte code4_prov;
byte code5_prov;

boolean startCode=false;
boolean stanRele=false;

long time_podsvetka;

int stanCode;
void setup()
{  digitalWrite(podsvetka,HIGH);
   lcd.begin(16, 2);
   lcd.print("Code_zamok V2.1");
   lcd.setCursor(3,1);
   lcd.print("loading...");
   digitalWrite(rele,LOW);
   delay(2000);
pinMode(7,OUTPUT);
pinMode(13,OUTPUT);
pinMode(9,OUTPUT);
pinMode(8,INPUT);

}

  void bip_time(long time,int bip)
  {
    for(int i=0;i<bip;i++)
      {digitalWrite(7,HIGH);
       delay(time);
       digitalWrite(7,LOW);
       delay(time);
      }
  }



void eeprom_write_code()

  { 
    do
    { lcd.clear(); 
      lcd.print("enter");
      lcd.setCursor(5,1);
      lcd.print("new code");
      bip_time(1000,2);
      delay(2000);
      lcd.clear();
    in_code1=analogRead(A0)/113;
    bip_time(500,1);
    lcd.setCursor(0,1);
    lcd.print(in_code1);
      EEPROM.write(1,in_code1);
    delay(3000);
         if(analogRead(A0)==0)
           { lcd.clear();
             lcd.print("cancel enter code");
             delay(500);
             break;}
    in_code2=analogRead(A0)/113;
    bip_time(500,1);
    lcd.setCursor(3,1);
    lcd.print(in_code2);
      EEPROM.write(2,in_code2);
    delay(3000);
         if(analogRead(A0)==0)
           {lcd.clear();
            lcd.print("cancel enter code");
            delay(500);
            break;}
     in_code3=analogRead(A0)/113;
     bip_time(500,1);
     lcd.setCursor(6,1);
     lcd.print(in_code3);
       EEPROM.write(3,in_code3);
     delay(3000);
          if(analogRead(A0)==0)
            {lcd.clear();
             lcd.print("cancel enter code");
             delay(500);
             break;}
    in_code4=analogRead(A0)/113;
    bip_time(500,1);
    lcd.setCursor(9,1);
    lcd.print(in_code4);
      EEPROM.write(4,in_code4);
    delay(3000);
         if(analogRead(A0)==0)
           {lcd.clear();
            lcd.print("cancel enter code");
            delay(500);
            break;}
    in_code5=analogRead(A0)/113;
    lcd.setCursor(12,1);
    lcd.print(in_code5);
      EEPROM.write(5,in_code5);
   x=2;
   delay(1000);
   lcd.setCursor(1,0);
   lcd.print("code write");
   bip_time(1000,2);
} while(x<=1);
  x=1;}
  
void eeprom_read_code()
  {code1_prov=EEPROM.read(1);
   code2_prov=EEPROM.read(2);
   code3_prov=EEPROM.read(3);
   code4_prov=EEPROM.read(4);
   code5_prov=EEPROM.read(5);}


void loop()
{
  if(millis()-time_podsvetka>=120000)
    {digitalWrite(podsvetka,LOW);}
  
  if(digitalRead(button)==HIGH)
    {eeprom_write_code();}
  
  if(startCode==false) 
    {lcd.clear();
     lcd.print("closed!!!");
     val=analogRead(A0)/113;
     delay(200);
     val1=analogRead(A0)/113;
        if(val-val1>1)
          { time_podsvetka=millis();
            digitalWrite(podsvetka,HIGH);
            startCode=true;
            lcd.clear();
            lcd.setCursor(3,0);
            lcd.print("enter code");}}
  if(startCode==true && stanRele==false)
    {
     do
       {  
        stanCode=0;
        bip_time(2000,1);
        eeprom_read_code();
        delay(3000);
      code1=analogRead(A0)/113;
      bip_time(500,1);
      lcd.setCursor(0,1);
      lcd.print(code1);
        if(code1==code1_prov);
          {stanCode=stanCode++;}
      delay(500);
      lcd.setCursor(0,1);
      lcd.print("*");
      delay(3000);
        if(analogRead(A0)==0)
          { lcd.clear();
            lcd.print("cancel enter code");
            bip_time(500,3);
            stanCode=0;
            break;}
       code2=analogRead(A0)/113;
       bip_time(500,1);
       lcd.setCursor(3,1);
       lcd.print(code2);
         if(code2==code2_prov)
           {stanCode=stanCode++;}
       delay(500);
       lcd.setCursor(3,1);
       lcd.print("*");
       delay(3000);
       if(analogRead(A0)==0)
         {lcd.clear();
          lcd.print("cancel enter code");
          bip_time(500,3);
          stanCode=0;
          break;}
       code3=analogRead(A0)/113;
       bip_time(500,1);
       lcd.setCursor(6,1);
       lcd.print(code3);
         if(code3==code3_prov)
           {stanCode=stanCode++;}
       delay(500);
       lcd.setCursor(6,1);
       lcd.print("*");
       delay(3000);
         if(analogRead(A0)==0)
           {lcd.clear();
            lcd.print("cancel enter code");
            bip_time(500,3);
            stanCode=0;
            break;}
       code4=analogRead(A0)/113;
       bip_time(500,1);
       lcd.setCursor(9,1);
       lcd.print(code4);
         if(code4==code4_prov)
           {stanCode=stanCode++;}
       delay(500);
       lcd.setCursor(9,1);
       lcd.print("*");
       delay(3000);
         if(analogRead(A0)==0)
           {lcd.clear();
            lcd.print("cancel enter code");
            bip_time(500,3);
            stanCode=0;
            break;}
      code5=analogRead(A0)/113;
      bip_time(500,1);
      lcd.setCursor(12,1);
      lcd.print(code5);
        if(code5==code5_prov)
          {stanCode=stanCode++;}
      delay(500);
      lcd.setCursor(12,1);
      lcd.print("*");
      bip_time(2000,1);
      v=2;
} while(v<=1);}

  if(stanCode==5 && stanRele==false && startCode==true)
    {digitalWrite(rele,HIGH);
     stanRele=true;
     lcd.clear();
     lcd.print("access granted !!!");
     delay(2000);}
   if(stanCode!=5 && stanRele==false && startCode==true)
      {lcd.clear();
       lcd.print("access denied");
       bip_time(100,10);
       startCode=false;}
 if(stanRele==true)
   {lcd.clear();
    lcd.print("open!!!");
    val=analogRead(A0)/113;
    delay(200);
    val1=analogRead(A0)/113;
       if(val-val1>1)
         {time_podsvetka=millis();
          digitalWrite(podsvetka,HIGH);
          digitalWrite(rele,LOW) ;
          stanRele=false;
          startCode=false;
          delay(2000);}}
 }

При надобности изменив программу можно закрывать замок также вводом кода.
Смена пароля.
Для записи нового пароля служит кнопка program. Кнопка располагается на плате, можно сделать просто перемычку и когда нужно поменять код
просто замкнуть контакты. После нажатия на дисплее появляется „enter new code“ звучит два длиных сигнала ето значит можна вводить новый
код. Вводится код аналогично. После ввода выводится „code write“ и звучит два длиных сигнала, значит новый код записан в
EEPROM.
Для економии питания подсветка дисплея выключается через 2 минуты и включаеся при начале ввода кода.
Вместо пищалки можно поставить светодиод, чтобы не было лишнего шума.
Если кому то нужно и закрывать замок введением кода, то скетч следующий:
#include <EEPROM.h>
#include <LiquidCrystal.h>
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

#define rele 13
#define button 8
#define podsvetka 9
int x;
int v;

byte val;
byte val1;

int code1_on;
int code2_on;
int code3_on;
int code4_on;
int code5_on;

int code1_off;
int code2_off;
int code3_off;
int code4_off;
int code5_off;


int in_code1;
int in_code2;
int in_code3;
int in_code4;
int in_code5;

byte code1_prov;
byte code2_prov;
byte code3_prov;
byte code4_prov;
byte code5_prov;

boolean startCode_on=false;
boolean startCode_off=true;
boolean stanRele=false;

long time_podsvetka;

int stanCode_on;
int stanCode_off;
void setup()
{
   digitalWrite(podsvetka,HIGH);
   lcd.begin(16, 2);
   lcd.print("Code_zamok V3.1");
   lcd.setCursor(3,1);
   lcd.print("loading...");
   digitalWrite(rele,LOW);
   delay(2000);
pinMode(7,OUTPUT);
pinMode(13,OUTPUT);
pinMode(9,OUTPUT);
pinMode(8,INPUT);

}

  void bip_time(long time,int bip)
  {
    for(int i=0;i<bip;i++)
  {digitalWrite(7,HIGH);
  delay(time);
  digitalWrite(7,LOW);
  delay(time);
  }
  }



void eeprom_write_code()

  { 
    do
     { digitalWrite(podsvetka,HIGH);
       lcd.clear(); 
       lcd.setCursor(3,0);
       lcd.print("enter");
       lcd.setCursor(3,1);
       lcd.print("new code");
       bip_time(1000,2);
       lcd.clear();
       lcd.setCursor(3,0);
       lcd.print("enter code");
       delay(3000);
     in_code1=analogRead(A0)/113;
     bip_time(500,1);
     lcd.setCursor(0,1);
     lcd.print(in_code1);
         EEPROM.write(1,in_code1);
         delay(3000);
           if(analogRead(A0)==0)
             { lcd.clear();
               lcd.print("cancel enter code");
               delay(500);
               break;}
     in_code2=analogRead(A0)/113;
     bip_time(500,1);
     lcd.setCursor(3,1);
     lcd.print(in_code2);
         EEPROM.write(2,in_code2);
         delay(3000);
           if(analogRead(A0)==0)
             {lcd.clear();
              lcd.print("cancel enter code");
              delay(500);
              break;}
     in_code3=analogRead(A0)/113;
     bip_time(500,1);
     lcd.setCursor(6,1);
     lcd.print(in_code3);
       EEPROM.write(3,in_code3);
       delay(3000);
         if(analogRead(A0)==0)
           {lcd.clear();
            lcd.print("cancel enter code");
            delay(500);
            break;}
     in_code4=analogRead(A0)/113;
     bip_time(500,1);
     lcd.setCursor(9,1);
     lcd.print(in_code4);
       EEPROM.write(4,in_code4);
       delay(3000);
         if(analogRead(A0)==0)
           {lcd.clear();
            lcd.print("cancel enter code");
            delay(500);
            break;}
     in_code5=analogRead(A0)/113;
     lcd.setCursor(12,1);
     lcd.print(in_code5);
       EEPROM.write(5,in_code5);
       delay(2000);
   x=2;
   delay(1000);
   lcd.setCursor(1,0);
   lcd.print("new code write");
   bip_time(1000,2);
} while(x<=1);
  x=1;
  
  }
void eeprom_read_code()
  {code1_prov=EEPROM.read(1);
   code2_prov=EEPROM.read(2);
   code3_prov=EEPROM.read(3);
   code4_prov=EEPROM.read(4);
   code5_prov=EEPROM.read(5);}


void loop()
{
  if(millis()-time_podsvetka>=120000)
    {digitalWrite(podsvetka,LOW);}
  
  if(digitalRead(button)==HIGH)
  {eeprom_write_code();}
  
if(startCode_on==false)  
{
  lcd.clear();
  lcd.print("closed!!!");
  val=analogRead(A0)/113;
  delay(200);
  val1=analogRead(A0)/113;
    if(val-val1>1)
      { time_podsvetka=millis();
        digitalWrite(podsvetka,HIGH);
        startCode_on=true;
        lcd.clear();
        lcd.setCursor(0,0);
        lcd.print("for door open");
        lcd.setCursor(3,1);
        lcd.print("enter code");
        delay(2000);
        lcd.clear();
        lcd.setCursor(3,0);
        lcd.print("enter code");}
      }
  
  
if(startCode_on==true && stanRele==false)
{
  do
   {  
    stanCode_on=0;
    bip_time(2000,1);
    eeprom_read_code();
    delay(3000);
    code1_on=analogRead(A0)/113;
    bip_time(500,1);
    lcd.setCursor(0,1);
    lcd.print(code1_on);
      if(code1_on==code1_prov);
        {stanCode_on=stanCode_on++;}
    delay(500);
    lcd.setCursor(0,1);
    lcd.print("*");
    delay(3000);
          if(analogRead(A0)==0)
             { lcd.clear();
               lcd.print("cancel enter code");
               bip_time(500,3);
               stanCode_on=0;
               break;}
    code2_on=analogRead(A0)/113;
    bip_time(500,1);
    lcd.setCursor(3,1);
    lcd.print(code2_on);
      if(code2_on==code2_prov)
        {stanCode_on=stanCode_on++;}
         delay(500);
         lcd.setCursor(3,1);
         lcd.print("*");
         delay(3000);
              if(analogRead(A0)==0)
                {  lcd.clear();
                   lcd.print("cancel enter code");
                   bip_time(500,3);
                   stanCode_on=0;
                   break;}
   code3_on=analogRead(A0)/113;
   bip_time(500,1);
   lcd.setCursor(6,1);
   lcd.print(code3_on);
      if(code3_on==code3_prov)
         {stanCode_on=stanCode_on++;}
    delay(500);
    lcd.setCursor(6,1);
    lcd.print("*");
    delay(3000);
         if(analogRead(A0)==0)
           {  lcd.clear();
              lcd.print("cancel enter code");
              bip_time(500,3);
              stanCode_on=0;
              break;}
   code4_on=analogRead(A0)/113;
   bip_time(500,1);
   lcd.setCursor(9,1);
   lcd.print(code4_on);
     if(code4_on==code4_prov)
       {stanCode_on=stanCode_on++;}
    delay(500);
    lcd.setCursor(9,1);
    lcd.print("*");
    delay(3000);
         if(analogRead(A0)==0)
           { lcd.clear();
             lcd.print("cancel enter code");
             bip_time(500,3);
             stanCode_on=0;
             break;}
   code5_on=analogRead(A0)/113;
   bip_time(500,1);
   lcd.setCursor(12,1);
   lcd.print(code5_on);
      if(code5_on==code5_prov)
       {stanCode_on=stanCode_on++;}
   delay(500);
   lcd.setCursor(12,1);
   lcd.print("*");
   bip_time(2000,1);
   v=2;
} while(v<=1);
  v=1;}

  if(stanCode_on==5 && stanRele==false && startCode_on==true)//если код верный
    { stanRele=true;
      startCode_off=false;
      lcd.clear();
      lcd.print("access granted !!!");
      delay(2000);}
     if(stanCode_on!=5 && stanRele==false && startCode_on==true)
      {  lcd.clear();
         lcd.print("access denied");
         bip_time(100,10);
         startCode_on=false;}                              
 if(startCode_off==false)                                   
   {lcd.clear();
    lcd.print("open!!!");
    digitalWrite(rele,HIGH);
    val=analogRead(A0)/113;
    delay(200);
    val1=analogRead(A0)/113;
       if(val-val1>1)
         {time_podsvetka=millis();
          digitalWrite(podsvetka,HIGH);
          startCode_off=true; 
          lcd.clear();
          lcd.setCursor(0,0);
          lcd.print("for door closed");
          lcd.setCursor(3,1);
          lcd.print("enter code");
          delay(2000);
          lcd.clear();
          lcd.setCursor(3,0);
          lcd.print("enter code");  }}
        if(startCode_off==true && stanRele==true)             
             {
                do
                  { stanCode_off=0;
                    bip_time(2000,1);
                    eeprom_read_code();
                    delay(3000);
                    code1_off=analogRead(A0)/113;
                    bip_time(500,1);
                    lcd.setCursor(0,1);
                    lcd.print(code1_off);
                      if(code1_off==code1_prov);
                        {stanCode_off=stanCode_off++;}
                    delay(500);
                    lcd.setCursor(0,1);
                    lcd.print("*");
                    delay(3000);
                        if(analogRead(A0)==0)
                         { lcd.clear();
                           lcd.print("cancel enter code");
                           bip_time(500,3);
                           stanCode_off=0;
                           break;}
                    code2_off=analogRead(A0)/113;
                    bip_time(500,1);
                    lcd.setCursor(3,1);
                    lcd.print(code2_off);
                      if(code2_off==code2_prov)
                        {stanCode_off=stanCode_off++;}
                    delay(500);
                    lcd.setCursor(3,1);
                    lcd.print("*");
                    delay(3000);
                          if(analogRead(A0)==0)
                             {  lcd.clear();
                                lcd.print("cancel enter code");
                                bip_time(500,3);
                                stanCode_off=0;
                                break;}
                     code3_off=analogRead(A0)/113;
                     bip_time(500,1);
                     lcd.setCursor(6,1);
                     lcd.print(code3_off);
                       if(code3_off==code3_prov)
                          {stanCode_off=stanCode_off++;}
                     delay(500);
                     lcd.setCursor(6,1);
                     lcd.print("*");
                     delay(3000);
                            if(analogRead(A0)==0)
                               {  lcd.clear();
                                  lcd.print("cancel enter code");
                                  bip_time(500,3);
                                  stanCode_off=0;
                                  break;}
                     code4_off=analogRead(A0)/113;
                     bip_time(500,1);
                    lcd.setCursor(9,1);
                    lcd.print(code4_off);
                      if(code4_off==code4_prov)
                         {stanCode_off=stanCode_off++;}
                    delay(500);
                    lcd.setCursor(9,1);
                    lcd.print("*");
                    delay(3000);
                           if(analogRead(A0)==0)
                              { lcd.clear();
                                lcd.print("cancel enter code");
                                bip_time(500,3);
                                stanCode_off=0;
                                break;}
                    code5_off=analogRead(A0)/113;
                    bip_time(500,1);
                    lcd.setCursor(12,1);
                    lcd.print(code5_off);
                      if(code5_off==code5_prov)
                        {stanCode_off=stanCode_off++;}
                    delay(500);
                    lcd.setCursor(12,1);
                    lcd.print("*");
                    bip_time(2000,1);
      v=2;
   } while(v<=1);
      v=1;}
     if(stanCode_off==5 && stanRele==true && startCode_off==true)  
       {digitalWrite(rele,LOW);
        lcd.clear();
        lcd.print("access granted");
        delay(2000);
        lcd.clear();
        lcd.print("closed!!!");
        stanRele=false;
        startCode_on=false;}
         if(stanCode_off!=5 && stanRele==true && startCode_off==true)
          {lcd.clear();
           lcd.print("access denied");
           bip_time(100,10);
           startCode_off=false;}

         
 }

В этом варианте все аналогично предыдущему. Код для закрытия тот же, что и для открытия.
Cобрал на макетной плате:
  • +1
  • 3 мая 2013, 14:24
  • nanit

Комментарии (0)

RSS свернуть / развернуть

Только зарегистрированные и авторизованные пользователи могут оставлять комментарии.