Eb4cak
Inventos:
=> Time Lapse
=> Soporte PDA para moto o bici
=> Cascos para el casco
=> Bluetooth para Moto
=> Mochila Moto
=> Proyectos
=> Como hacer un Servo Multivuelta modificando uno normal
=> Cerradura electronica
=> Aviso acceso con ESP8266
Contacto
 

Cerradura electronica

10-12-2012
 
http://www.youtube.com/watch?v=xSuP_aj86Bk
 
He modificado la cerradura electronica, que se puede ver en el video, para que funione con Arduino.
 
He usado:
Un Arduino Nano. 12€
Un teclado keypad de ebay. 3€
Un lcd 1602 que vale unos 5€
Un modulo de dos relés de ebay. 3€
Un sensor magnetico de puerta abierta. 4€
Un zumbador. 3€
El Motor con mando a distancia de ABUs Hometec. 70€ (En Alemania cuesta unos 40€, en ferreteria Española unos 150€... sin comentarios)
 
Estoy esperando de china: 
-RCT por I2C. Mi arduino atrasa 10 minutos al día¡¡  Se puede paliar por soft, pero el RTC es lo suyo y vale menos de 3€
-Un LCD con I2C para liberar pines y así poder poner sensor temperatura 18B20, grabador de tarjetas SD, sensor llamadas al timbre (poniendole un relé de 220 en paralelo) y cuarta columna keypad.
 
 
He conectado los dos relés a los botones del motor que abren y cierran la puerta manualmente. He tenido que usar el motor alrevés (que cierre cuando abre y viceversa).
 
El codigo fuente es el siguiente (compilado con Arduino 1.0.2):
 
 
 
 
 
 
/*******************************************************************************
  * CERRADURA ELECTRONICA de Antonio EB4CAK 
  * Pongo este programa bajo licencia GNU GPL.
  * 
  * 22-5-2011  INICIO    
* 20-6-11 Version 1.0
* 12-7-11 V 1.1  Puerta se cierra ante clave erronea - corregir bug que no cierra la puerta - 
* 10-9-11 V 1.2  Avisa de la ultima clave erronea
* 08-10-12 v 1.3  Modificacion para Mari Carmen y añadida clave 7 generica
        * 1-12-2012 v1.4  Adaptacion de STM8s a Arduino. Quitada clave7. Espera incremental si error.
        * 7-12-2012 Lo instalo
  ******************************************************************************
 
 
Cosas Pendientes:
-RTC   (pines A4 y A5)
-SD para grabar entradas y salidas
-Pin de entrada para avisar si han llamado al timbre
 
 
PINES:  
2 Teclado Col 1
3 Teclado Col 2
4 ABRIRCERRADURA   Rele cerradura ON
5 CERRARCERRADURA  Rele cerradura OFF
6 Teclado Col 3
7 Zumbador           Teclado Col 4 (Opcional)
8 Teclado Fila 1 
9 Teclado Fila 2
10Teclado Fila 3
11Teclado Fila 4
12  LCD RS
13* LCD E
A0  LCD D4
A1  LCD D5
A2  LCD D6
A3  LCD D7
A4* RTC
A5* RTC  
A6 Sensor timbre? 18b20?
A7 Sensor puerta abierta   (Poner una R de 5v al pin y luego el pin a Masa pasando por el interruptor)
 
 
 
 
 */
 
 
#include <LiquidCrystal.h>
#include <Keypad.h>
#include <Time.h>   // Para la hora
#include <Wire.h>  
#include <DS1307RTC.h>  // a basic DS1307 library that returns time as a time_t
#include <EEPROM.h>
 
// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(12, 13, 17, 16, 15, 14);
 
//////////// Config teclado
const byte ROWS = 4; //Filas
const byte COLS = 3; //Columnas
char keys[ROWS][COLS] = {
  {'1','2','3'},
  {'4','5','6'},
  {'7','8','9'},
  {'*','0','#'}
};
byte rowPins[ROWS] = {8,9,10,11}; //connect to the row pinouts of the keypad
byte colPins[COLS] = {2,3,6}; //connect to the column pinouts of the keypad
Keypad keypad = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );
//////////// Fin Config Teclado
 
////// Claves
char Clave1[15]={"1234"};  // Pueden ser 15 caracteres o menos.
char Clave2[15]={"00000000"};  
char Clave3[15]={"1111111111111"};  // Para Mari Carmen
char Clave4[15]={"32165498732165"};  // Clave de un solo uso
char Clave5[15]={"32112346549878"};  // Clave de un solo uso
char Clave6[15]={"55555556546546"};  // Clave de un solo uso
// Nota: Hay que cambiar estas claves. Solo son de prueba para la difusion del codigo.
 
////// Fin Claves
 
#define LUNES  2             
#define MARTES  3
#define MIERCOLES  4
#define JUEVES  5
#define VIERNES  6
#define SABADO  7
#define DOMINGO  1
#define SI  0xFF
#define NO  0
#define COMPROBAR  1   // Usado en exceso_de_tiempo
#define INICIAR  2 // Usado en exceso_de_tiempo
#define ANULAR   0 // Usado en exceso_de_tiempo
#define SensorPuerta A7
#define BUZZ 7   //Definimos el pin del zumbador
#define ABRIRCERRADURA  4
#define CERRARCERRADURA 5
#define INACTIVO   HIGH  // Para no liarse con ABRIRCERRADURA
#define ACTIVO  LOW
 
 
 
/********* PARA TEMPORIZACIONES  Y RELES ***********/
unsigned int error_acumulativo=1;  // Para que a cada codigo erroneo la espera sea mayor
/********* FIN PARA TEMPORIZACIONES Y RELES *************/
 
 
 
time_t pctime = 1354786049; // Tiempo inicial de prueba hasta poner el RTC.
 
time_t TiempoError = 0;   // Para pintar hora de ultima entrada erronea
 
void setup() {
  delay(50); // Por si acaso, para estabilizar.
  Serial.begin(9600); // Para depuracion solo.
  lcd.begin(16, 2);  // 16 Columnas y 2 filas  
  lcd.clear(); //Para evitar que queden cosas mal.
   
  pinMode(BUZZ, OUTPUT);   // Esto se puede quitar.
  pinMode(ABRIRCERRADURA, OUTPUT); 
  pinMode(CERRARCERRADURA, OUTPUT);   
  digitalWrite(ABRIRCERRADURA, INACTIVO);    // Reles inactivos
  digitalWrite(CERRARCERRADURA, INACTIVO);   // Reles inactivos
    
    /*   Aqui PONEMOS RTC   Revisarlo para varios intentos
    setSyncProvider(RTC.get);   // the function to get the time from the RTC
  if(timeStatus()!= timeSet) 
     Serial.println("Unable to sync with the RTC");
  else
     Serial.println("RTC has set the system time");      
     */
     
    setTime(pctime);
 
    melodia(2);  // Musiquilla que indica reinico 
 
 
}// Del setup
 
void loop() {
 
   pinta_reloj();
   delay(5);
  
    char key = keypad.getKey();    // Capturamos tecla 
    clave_tecla(key);              // Comprobamos si es la clave OK
  
  
   // Pintamos errores 
    if(TiempoError)pinta_reloj_eventos();
 
 
        // Si PUERTA ABIERTA pasamos a modo configuracion      
        if(analogRead(SensorPuerta) > 500){   //        if(analogRead(SensorPuerta) > 500){
          luz_puerta(SI);       // Encendemos la luz de la entrada
          modo_configuracion();  
          luz_puerta(SI);       // Volvemos para iniciar contador otra vez
        }else luz_puerta(NO);  // Con la puerta cerrada pensamos en apagar la luz de la entrada y en cerrar la cerradura a los x seg.
 
 
  
  
}// Del loop
 
 
 
 
 
 
/************************************************************************/
/************         Pintamos la Hora            ***********************/
/************************************************************************/
void pinta_reloj(){
int dia;
dia=weekday();
 
  lcd.setCursor(0,0);  // Situamos el cursor
  if(hour() < 10) lcd.print('0');  
  lcd.print(hour());
  printDigits(minute());
//  printDigits_segundos(second());
  lcd.print(" ");
/*  lcd.print(day(),DEC);
  lcd.print("/");
  lcd.print(month(),DEC);
  lcd.print("/");
  lcd.print(year(),DEC); */
 
  
switch(dia){
 
case LUNES:
lcd.print("L");
break;
case MARTES:
lcd.print("M");
break;
case MIERCOLES:
lcd.print("X");
break;
case JUEVES:
lcd.print("J");
break;
case VIERNES:
lcd.print("V");
break;
case SABADO:
lcd.print("S");
break;
case DOMINGO:
lcd.print("D");
break;
}  
}//Fin pinta_reloj()
void printDigits(int digits){
  // utility function for digital clock display: prints preceding colon and leading 0
  lcd.print(":");
  if(digits < 10)
    lcd.print('0');
  lcd.print(digits);
}
void printDigits_segundos(int digits){
  // utility function for digital clock display: prints preceding colon and leading 0
  lcd.print(".");
  if(digits < 10)
    lcd.print('0');
  lcd.print(digits);
}
 
 
 
 
/************************************************************************/
/************  Centralizacion de Musiquillas      ***********************/
/*  Tuve problemas hasta que descubrí que sin el delay() no funciona    */
/************************************************************************/
void melodia(int tipo){     // Musiquillas  1->Error  2->Inicio  3->Correcto  4->Pulsar tecla   5->puerta abierta    6->Puerta cerrada
 switch(tipo){
          case 1:
              cerrar_puerta();   // En caso de clave mal, echamos cerrojo                  
              tone(BUZZ,2000);
              TiempoError=now();    // Memorizamos hora para recordar el ultimo error
              delay(2000*error_acumulativo++); // Mas retraso y acumulativo (puede llegar a un pitido de 35 horas por cada error)
              noTone(BUZZ);         
             break;
          
          case 2:
              tone(BUZZ,1000);  delay(50);
              tone(BUZZ,4000);  delay(50);
              tone(BUZZ,1000);  delay(50);
              noTone(BUZZ);          
             break;
          
          case 3:
              tone(BUZZ,1000);   delay(20);
              tone(BUZZ,4000);   delay(40);
              tone(BUZZ,2000);   delay(20);
              tone(BUZZ,1000);   delay(40);
              tone(BUZZ,4000);   delay(40);
              tone(BUZZ,2000);   delay(20);
              tone(BUZZ,1000);   delay(40);
              tone(BUZZ,4000);   delay(60);              
              tone(BUZZ,2000);   delay(40);
              tone(BUZZ,1000);   delay(40);              
              tone(BUZZ,4000);   delay(40);
              tone(BUZZ,1000);   delay(60);
              noTone(BUZZ);  
              error_acumulativo=1;  // Reiniciamos la espera si claves errorneas.
             break;
          
          case 4:
              tone(BUZZ,1000);   delay(80);
              noTone(BUZZ);  
              break;
          
          case 5:
              tone(BUZZ,2000);   delay(80);
              tone(BUZZ,4000);   delay(50);
              tone(BUZZ,1000);   delay(80);
              tone(BUZZ,4000);   delay(30);
               noTone(BUZZ);               
             break;
          
          case 6:
              tone(BUZZ,4000);   delay(40);
              tone(BUZZ,2000);   delay(30);
              tone(BUZZ,4000);   delay(30);
              tone(BUZZ,1000);   delay(100);             
              noTone(BUZZ);                
             break;
     }//Del switch
   noTone(BUZZ); // Por si acaso.
}//del melodia()
 
 
 
 
 
/************************************************************************/
/* Entramos en modo configuracion al abrir la puerta */
/* Solo saldremos al cerrar la puerta   */
/* Mantenemos la luz de la entrada encendida */
/************************************************************************/
void modo_configuracion(void){
 char key=0; char estado=0;
 
 melodia(5);  // Avisamos de puerta abierta
 
        lcd.setCursor(0,1);  // Situamos el cursor
lcd.print(" CONFIG PULSE 0 ");
        pctime=now();   // Igualamos pctime al tiempo del sistema.
   // Encender luz entrada (y mantenerla despues, quizas usando exceso_de_tiempo())
while(analogRead(SensorPuerta) > 500){  // Mientras la puerta este abierta:
  pinta_reloj();
  key = keypad.getKey();   //Capturamos tecla
 
     if (key) //new key has been pressed
     {
melodia(4);   // Pitidito de pulsacion 
if(key=='0') estado++;  // Cambiamos de menu con el CERO
if(estado>4)estado=1; // Lo hacemos ciclico
switch(estado)
{
case 1:  // BORRAR ENTRADAS ERRONEAS
lcd.setCursor(0,1);
lcd.print("  BORRAR ENTRADA");
if(key=='*'){TiempoError=0;error_acumulativo=1;}
if(key=='#'){TiempoError=0;error_acumulativo=1;}
break;
 
case 2:   // AJUSTAR HORA
lcd.setCursor(0,1);
lcd.print("  AJUSTE  HORA  ");
if(key=='*'){pctime-=3600;}
if(key=='#'){pctime+=3600;}
                                 setTime(pctime);     // igualamos el tiempo de sistema al de pctime
break;
 
case 3:  // AJUSTAR MINUTOS
lcd.setCursor(0,1);
lcd.print("  AJUSTE MINUTOS");
if(key=='*'){pctime-=60;}
if(key=='#'){pctime+=60;}
                                 setTime(pctime);  
break;
 
case 4:   // AJUSTAR DIA
lcd.setCursor(0,1);
lcd.print("  AJUSTE   DIA  ");
if(key=='*'){pctime-=86400;}
if(key=='#'){pctime+=86400;}
                                 setTime(pctime);  
break;
}
 
     } // Del si key
  } // Del while
  lcd.clear();       // Al salir hay que limpiar el display
        melodia(6);   // Cantamos q la puerta se cierra
}
 
 
 
 
 
/************************************************************************/
/* COMPROBAMOS LAS TECLA PULSADAS en busca de claves */
/************************************************************************/
void clave_tecla(char Tecla){
static char oldkey, posicion_clave=0;  
static char Clave[15]; 
 
 if(exceso_de_tiempo(10, COMPROBAR)){posicion_clave=0; melodia(1); return;} // Damos señal de error
 
 
if (Tecla != oldkey) //new key has been pressed
  {
   if (Tecla)
   {
melodia(4);   // Pitidito de pulsacion 
exceso_de_tiempo(10, INICIAR);
Clave[posicion_clave]=Tecla;
Clave[posicion_clave+1]=0; // Finalizamos la cadena para evitar errores
if(posicion_clave < 14){ posicion_clave++; }
                      else{  // Si metemos 15 num y no hay clave hay que esperar
posicion_clave=0;  
melodia(1);
exceso_de_tiempo(10, ANULAR);
// Implantar esperas si se mete codigo erroneo X veces
 }
    
if(!strcmp(Clave, Clave1)){    // CLAVE CORRECTA
                        clave_correcta(); // abrir puerta
posicion_clave=0;  // Reiniciamos contador
}
 
if(!strcmp(Clave, Clave2)){    // CLAVE CORRECTA
                        clave_correcta(); // abrir puerta
posicion_clave=0;  // Reiniciamos contador
}
 
/* La clave3 funcionará los dias de curro de 2 a 9 (OJO Hasta el RTC pongo todos los dias de 9 a 23)  */
if(hour()>9 && hour()<23 /* && day()!=DOMINGO && day()!=SABADO*/)  
if(!strcmp(Clave, Clave3)){    // CLAVE CORRECTA
clave_correcta(); // abrir puerta
posicion_clave=0;  // Reiniciamos contador
}
 
 
/* CLAVES DE UN SOLO USO */
if(!EEPROM.read(100))
if(!strcmp(Clave, Clave4)){    // CLAVE CORRECTA
clave_correcta();       // abrir puerta
posicion_clave=0;  // Reiniciamos contador
EEPROM.write(100, NO);  // La clave queda invalidada   // OJO poner temporizacion para que se pueda usar durante ~10 min.
}
 
if(!EEPROM.read(101))
if(!strcmp(Clave, Clave5)){    // CLAVE CORRECTA
clave_correcta(); // abrir puerta
posicion_clave=0;  // Reiniciamos contador
EEPROM.write(101, NO);  // La clave queda invalidada
}
 
if(!EEPROM.read(102))
if(!strcmp(Clave, Clave6)){    // CLAVE CORRECTA
clave_correcta(); // abrir puerta
posicion_clave=0;  // Reiniciamos contador
EEPROM.write(102, NO);  // La clave queda invalidada
}
 
    oldkey = Tecla;  // Antirebotes
}
else // Si no hay tecla pulsada o tecla no correcta
   {
    oldkey = 255;
   }
 } // Del si tecla != oldkey
 
}
 
/*****************************************************/
/* Abrir puerta, cerrarla luego, memorizar evento y  */
/*****************************************************/
void clave_correcta(){
digitalWrite(ABRIRCERRADURA, ACTIVO);    // abrimos puerta
melodia(3);  // Usamos melodia de timer
digitalWrite(ABRIRCERRADURA, INACTIVO); // Dejamos de abrir puerta
exceso_de_tiempo(10, ANULAR);
}
 
 
/*****************************************************/
/* Cerrar Puerta solo si esta cerrada, memorizar evento y  */
/*****************************************************/
void cerrar_puerta(){
if(analogRead(SensorPuerta) < 500){  //Si la puerta está cerrada
       digitalWrite(CERRARCERRADURA, ACTIVO);  // Echamos el cerrojo
melodia(6);   // Avisamos del cierre y lo usamos de timer
       digitalWrite(CERRARCERRADURA, INACTIVO);  // Dejamos de cerrar
}
}
 
 
/************************************************************************/
/* Para comprobar si ha pasado mucho tiempo (en segundos) sin respuesta */
/************************************************************************/
char exceso_de_tiempo(int tiempo_espera, char tipo_operacion)
{
 static time_t hora2=0;
 pctime=now();
if(tipo_operacion == INICIAR) hora2=pctime;
if(tipo_operacion == ANULAR) hora2=0;
  if(tipo_operacion == COMPROBAR){ 
 if(hora2){ // Para que no salte sin iniciar
if((hora2+tiempo_espera) < pctime){ 
hora2=0; // Para no comprobar de nuevo sin iniciar
return SI;  // TIEMPO DE ESPERA EXCEDIDO
}
}
 
return NO;  // Tiempo de espera no excedido
}
 
 
 
/************************************************************************/
/* Pintamos horas de eventos especificos */
/************************************************************************/
void pinta_reloj_eventos(){
  int dia;
dia=weekday(TiempoError);
 
  lcd.setCursor(0,1);  // Situamos el cursor
  if(hour() < 10) lcd.print('0');  
  lcd.print(hour(TiempoError));
  printDigits(minute(TiempoError));
  lcd.print(" ");
/*  lcd.print(day(),DEC);
  lcd.print("/");
  lcd.print(month(),DEC);
  lcd.print("/");
  lcd.print(year(),DEC); */
 
  
switch(dia){
case LUNES:
lcd.print("L");
break;
case MARTES:
lcd.print("M");
break;
case MIERCOLES:
lcd.print("X");
break;
case JUEVES:
lcd.print("J");
break;
case VIERNES:
lcd.print("V");
break;
case SABADO:
lcd.print("S");
break;
case DOMINGO:
lcd.print("D");
break;
}  
  } // Fin del void pinta_reloj_eventos()
 
 
 
/******************************************************************/
/**         Encendemos y apagamos la luz de la entrada           **/
/**            La luz se apaga con 20seg de reatraso             **/
/** También cerramos la cerradura a los 20 seg de cerrar puerta  **/
/******************************************************************/
void luz_puerta(char estado)
{
static time_t horaX=0;
  if(estado){ 
//GPIO_WriteHigh(GPIOA, GPIO_PIN_3);  // Encendemos luz
horaX=now();  // Empezamos a contar (cada vez que pasemos por aqui, empezamos a contar)
}else{ // Si el estado es NO, nos preparamos para apagar y cerrar
if((horaX) && (now() > (horaX+20))){  
//GPIO_WriteLow(GPIOA, GPIO_PIN_3);  //Apagar luz
                                cerrar_puerta();
horaX=0;  // Reiniciamos el contador
}
} // Del else
}
 
 
 
 
 

Hoy habia 1 visitantes (2 clics a subpáginas) ¡Aqui en esta página!
 
 
Este sitio web fue creado de forma gratuita con PaginaWebGratis.es. ¿Quieres también tu sitio web propio?
Registrarse gratis