Cerradura por RFID id20

Les presento un prototipo que estoy probando muy basico pero funcional, lo que les permitirá a varios probar.

Explicacion del programa
Las llaves son fijas, alojadas en la memoria flash para ahorrar memoria ram.
Los defines es igual, ahorran mucho codigo

  • El programa lee la tarjeta o llavero RFID, en este caso uso el ID20 de innovations que lo tenia guardado hace 2 años sin usar.
  • Cuando lee una tarjeta valida activa la salida por el tiempo definido, a la vez que suena un buzzer.
  • Si la tarjeta es invalida envia el codigo por Serial para poder copiarlo y anotarlo en el codigo.
  • La busqueda es secuencial, pero hice la prueba con 100 registros y no hay demora.
  • Tiene 2 modos de activacion, Magnetico o liberapestillo, si es magnetico se activa apenas se enciende y desactiva cuando el codigo es correcto.
  • Tiene antipassing, que no deja que la misma tarjeta sea leida 2 veces almenos que pasen 10 segundos, tambien configurable.
  • Tiene un boton de activacion manual para los casos en que se ingresa con llave y se puede salir sin llave.
  • Uso el led de la salida 13 para un testigo de que el programa no se ha colgado, parpadeando indefinidamente

Lo dejé conectado 2 dias sin que se disparara ni colgara el programa, ahora en breve lo conecto a la realidad para ver como se comporta.

Haa notarán que no uso el loop(), pues por consejo de alguien que estudió mucho el ide asegura que el loop() solapa variables llevando a cuelques inesperados.

Espero sirva para alguien mas.

#include <Event.h>
#include <Timer.h>
#include <avr/pgmspace.h>


#define PINRESET 3
#define PINLED 13
#define PINRELE A1
#define PINSONIDO A2
#define PINBOTON A0
#define PINMODORELE 6


#define INTERVALO 100
#define NUM_TAGS 10
#define TIEMPORELE 3000 
#define REPITETAG 10000


const char tag_0[] PROGMEM = "8500622A09";  //
const char tag_1[] PROGMEM = "850061E734";  //
const char tag_2[] PROGMEM = "85006268A9";  //
const char tag_3[] PROGMEM = "85005E1E15";  //
const char tag_4[] PROGMEM = "8500623EE1";  //
const char tag_5[] PROGMEM = "8500623428";  //
const char tag_6[] PROGMEM = "8500625FFE";  //
const char tag_7[] PROGMEM = "850066E458";  //
const char tag_8[] PROGMEM = "85006238DD";  //
const char tag_9[] PROGMEM = "8500620776";  //




const char* const tags_table[] PROGMEM = 
{   
  tag_0,
  tag_1,
  tag_2,
  tag_3,
  tag_4,
  tag_5, 
  tag_6, 
  tag_7, 
  tag_8, 
  tag_9, 
};

Timer T; 
         
char codeant[11]="0000000000";
boolean MODORELE=HIGH; //si es magnetico LOW si es libera pestillo HIGH

void setup() 
{
  Serial.begin(9600);                                 // connect to the serial port
  
  pinMode(PINRESET ,OUTPUT);
  pinMode(PINRELE  ,OUTPUT);
  pinMode(PINSONIDO,OUTPUT);
  pinMode(PINBOTON ,INPUT_PULLUP);
  pinMode(PINMODORELE ,INPUT_PULLUP);
  
  //configurar modo de activacion del rele
  if (digitalRead(PINMODORELE)== false)
    MODORELE=LOW; //si es magnetico LOW 
  else
    MODORELE=HIGH; //si es libera pestillo HIGH
  

  DesactivarRele(); //inicializo 
  T.oscillate(PINLED,500,HIGH); //parpadeo del led

  
  ResetReader();

  char xcode[11];
 
  while (1)
  {
   if (LeerTarjetaID20(xcode))
   {
   
   if (strcmp(codeant,xcode)!=0) //es una tarjeta nueva
   {
   if (Existe_Tag(xcode))
  Abrir();
 else
  SonidoError();
 strcpy(codeant,xcode); //copiar la tarjeta leida
                        T.after(REPITETAG, LimpiarTarjeta);
                        //lanzar el borrado de tarjeta en 10 segundos 
 
   }
 ResetReader();
 Serial.println(xcode);
   Serial.println();
   Serial.flush();
   } 

        if (!digitalRead(PINBOTON)) //se presionó el boton
        {
          while(!digitalRead(PINBOTON)) //mientras se mantenga el boton presionado esperar
            T.update();
          Abrir();
         }  
         
   T.update();
  }
}

void Abrir()
{
  T.every(INTERVALO,SonidoAbre,((TIEMPORELE-INTERVALO)/INTERVALO));    //le resto INTERVALO para compensar el delay.
  ActivarRele();//activamos rele manualmente
  T.after(TIEMPORELE, DesactivarRele); //despues de transcurrido el tiempo lo desactivamos
}

void SonidoAbre()
{
  tone(PINSONIDO,1000);
  delay(50);
  tone(PINSONIDO,1200);
  delay(50);
  noTone(PINSONIDO); 
}

void LimpiarCodigo()
{
  for(byte f=0;f<10;f++)    
    codeant[f]=0;
  codeant[10]='\0';

}


boolean Existe_Tag(char codigo[])
{
 char buffer[30]; 
 
 for(int f=0;f<NUM_TAGS;f++)
 {
 strcpy_P(buffer, (char*)pgm_read_word(&(tags_table[f])));
 buffer[10]='\0';//agrego el fin de linea para que funcione la comparacion
 if (strcmp(buffer,codigo)==0)
 return true; 
 }
 return false; //si recorrio todo el array y no la encontró devolver falso
}

void ParpadeaLed()
{
    if (ledState == LOW)
      ledState = HIGH;
    else
      ledState = LOW;

    // set the LED with the ledState of the variable:
    digitalWrite(PINLED, ledState);
}
 
boolean LeerTarjetaID20(char pcode[]) 
{
  byte i = 0;
  byte val = 0;
  byte code[16];
  byte checksum = 0;
  byte bytesread = 0;
  byte tempbyte = 0;

  if(Serial.available() > 0) 
  {
 if((val = Serial.read()) == 2) 
    {                  // check for header 
     bytesread = 0; 
       while (bytesread < 12) 
       {                        // read 10 digit code + 2 digit checksum
         if( Serial.available() > 0) 
         { 
           val = Serial.read();
           if((val == 0x0D)||(val == 0x0A)||(val == 0x03)||(val == 0x02)) 
           { // if header or stop bytes before the 10 digit reading 
             break;                                    // stop reading
           }
           code[bytesread]=val;
           bytesread++; 
         }
 } 

  
      // si se leyeron los 12 digitos pasarlos al paramero
 if (bytesread == 12) 
    {                          
 for (i=0; i<10; i++) 
        {
         pcode[i]=code[i]; 
        }
        pcode[10]='\0';//agregar fin de linea
     }
    }
  }
  return bytesread == 12;
}



void ResetReader()
{ 
  digitalWrite(PINRESET, LOW);
  delay(10);
  digitalWrite(PINRESET, HIGH);
}


void ActivarRele()
{ 
  digitalWrite(PINRELE,MODORELE); 
}

void DesactivarRele()
{ 
  digitalWrite(PINRELE,!MODORELE); 
}

void LimpiarTarjeta()
{
  strcpy(codeant,"0000000000"+'\0');
}


void SonidoError()
{
  for(byte f =0; f < 5; f++)
  {
    tone(PINSONIDO,800);
    delay(100);
    noTone(PINSONIDO);
  }
  noTone(PINSONIDO);

}


void loop () 
{
}

Agrego un pequeño video
Video de ejemplo

maxid:
Agrego un pequeño video
Video de ejemplo

El video aparece como privado en youtube.

si no usas loop() es mejor usar for(;:wink: que while(1), esto lo lei en un pdf de la documentación de atmel.

carmeloco:
El video aparece como privado en youtube.

Ya lo puse como publico

ehrja:
si no usas loop() es mejor usar for(;:wink: que while(1), esto lo lei en un pdf de la documentación de atmel.

La verdad que no lo sabia, hay que ver como lo convierte el compilador para ver la conveniencia

maxid:
La verdad que no lo sabia, hay que ver como lo convierte el compilador para ver la conveniencia

Acabo de leer, no recuerdo donde, un comentario de un usuario de Internet, comenta que su profesor le comento que el while hace una comparación 1:1 y el foro no hace nada y tiene sentido.

El resultado quizá no sea mucho mejor que con el while pero si se trata de optimizar a todo, tal vez con el tiempo si sea mas rentable en un porcentaje determinado según la aplicación. Solo lo digo por comentar. jeje

El proyecto está puesto y con total exito de funcionamiento, sin cuelgues.
Claro que tomé medidas extras como agregar capacitor 1000uf en la entrada de fuente y varistor en los contactos del relé para evitar falsos reseteos.
La version mejorada va a permitir la programacion remota, control de horarios de cada llave y un registro de marcaciones.