Open top menu
quinta-feira, 25 de abril de 2013

Hoje vou apresentar o hardware de um projeto de controle de acesso de colaboradores baseado em Arduino, RFID e Ethernet, futuramente vou postar uma versão da WEBAPI e site de gerenciamento dos acessos.

Para liberação de acesso o usuário aproxima o cartão RFID, o hardware realiza a leitura do número do cartão e acessa a WEBAPI de validação, se o cartão for válido, retorna o status de liberação com o nome do usuário cadastrado no sistema.

Vamos ver um video e fotos do projeto:


Protótipo do equipamento


Detalhe das conexões


Cada local de acesso é cadastrado com um código e as coordenadas de localização, possibilitando em tempo real acompanhar em um mapa todas as entradas e saídas dos colaboradores nos locais cadastrados.


API de acesso 
Request:

http://SERVIDOR/api/acesso/CODIGOCLIENTE/CODIGOEQUIPAMENTO/NUMEROCARTAORFID


SERVIDOR: IP ou DNS do servidor com WEBAPI publicada.
CODIGOCLIENTE: Codigo fixo do cliente, serve para agrupar os locais e usuários.
CODIGOEQUIPAMENTO: Código de identificação único do hardware, atráves dele é cadastrada as coordenadas para identificação do local do acesso.
NUMEROCARTAORFID: Número do cartão RFID.


Response:
<XML>|STATUS NOMEUSUARIO|</XML>
|: Caracter que identifica o início do retorno de validação do acesso
STATUS: Status da validação do acesso
NOMEUSUARIO: Nome do Usuário
|:Caracter que identifica o término do retorno de validação do acesso


Exemplo do acesso
O que é RFID?
Identificação por radiofrequência ou RFID (do inglês "Radio-Frequency IDentification" ) é um método de identificação automática através de sinais de rádio, recuperando e armazenando dados remotamente através de dispositivos denominados etiquetas RFID.

Uma etiqueta ou tag RFID é um transpondedor, pequeno objeto que pode ser colocado em uma pessoa, animal, equipamento, embalagem ou produto, dentre outros. Contém chips de silício e antenas que lhe permite responder aos sinais de rádio enviados por uma base transmissora. Além das etiquetas passivas, que respondem ao sinal enviado pela base transmissora, existem ainda as etiquetas semi-passivas e as ativas, dotadas de bateria, que lhes permite enviar o próprio sinal. São bem mais caras que do que as etiquetas passivas.
RFID: utiliza transponders ( os quais podem ser apenas lidos ou lidos e escritos) nos produtos, como uma alternativa aos códigos de barras, de modo a permitir a identificação do produto de alguma distância do scanner ou independente, fora de posicionamento. Tecnologia que viabiliza a comunicação de dados através de etiquetas com chips ou transponders que transmitem a informação a partir da passagem por um campo de indução. (ex: muito usado em pedágio "sem parar").

by Wikipedia


Conexões do projeto:

Lista de Componentes:
  • Arduino Mega 2560
  • Arduino Ethernet Shield
  • Arduino Rele Shield *
  • Regulador de tensão LM7805.
  • Leitor RFID ID-12 Innovations
  • Cartões RFid
  • Fonte chaveada 12V x 3A
  • LCD 40 Colunas x 4 Linhas (pode ser usado LCD com 2 linhas)
  • Buzzer
  • Rabicho de alimentação para fonte
  • Fios, barras de terminais e termoretráteis para conexão
* A montagem do rele shield foi apresentada no post Construindo um Relé Shield






Pode ser substuido por Arduino 5V Relay module





Código fonte do Arduino:
/*

Sergio de Miranda e Castro Mokshin
26/04/2013

Todos os direitos reservados

*/

#include 
#include 
#include 

#define PIN_SAIDA_BUZZ 49

byte mac[] = { 
  0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED};
// assign an IP address for the controller:
byte ip[] = { 
  192,169,1,20 };
byte gateway[] = {
  192,168,1,1}; 
byte subnet[] = { 
  255, 255, 255, 0 };

byte server[] = {  74, 86, 188 ,173 }; 

char serverName[] = "dns.servidor.api"; //trocar pelo DNS API Web
EthernetClient client;

char tagRFID[10];
boolean lastConnected = false;

LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
int rele1 = 22;
char validacaoTag;
char nomeTag[20];
int indexretornoServer;
boolean inicioretornoServer;

int KEY1 = 26;
int KEY2 = 28;
int KEY3 = 30;
int KEY4 = 32;
int localKEY1 = 0;
int localKEY2 = 0;
int localKEY3 = 0;
int localKEY4 = 0;


void setup() {
  
  pinMode(rele1, OUTPUT);  
  digitalWrite(rele1, HIGH); 

  indexretornoServer = 0;
  inicioretornoServer = false;
  
  lcd.begin(20, 4);
  lcd.print("Me Encontre         ");
  lcd.setCursor(0, 1);
  lcd.print("                    ");
  lcd.setCursor(0, 2);
  lcd.print("Iniciando Sistema   ");
  
  Serial.begin(9600);
  delay(1000);
  Serial.println("connecting...");
  
   if (Ethernet.begin(mac) == 0) {
    Serial.println("Failed to configure Ethernet using DHCP");
    while(true);
  }
  
  aguardandocomandos();    
  
}


void loop()
{    
  verificacartao();  
  lastConnected = client.connected();   
}

void verificacartao(){
  
  byte i = 0;
  byte val = 0;
  byte code[6];
  byte checksum = 0;
  byte bytesread = 0;
  byte tempbyte = 0;
   
  if(Serial.available() > 0) {      
    if((val = Serial.read()) == 2) { 
      bytesread = 0; 
      while (bytesread < 12) {     
        if( Serial.available() > 0) { 
          
          lcd.setCursor(0, 1);
          lcd.print("                   ");
          lcd.setCursor(0, 2);
          lcd.print("Buscando Dados     ");
          lcd.setCursor(0, 3);
          lcd.print("                   ");
            
          val = Serial.read();          
          if (bytesread < 10)
          {
            tagRFID[bytesread] = val;
          }
                    
          if((val == 0x0D)||(val == 0x0A)||(val == 0x03)||(val == 0x02)) { 
            break;   
          }
   
          if ((val >= '0') && (val <= '9')) {
            val = val - '0';
          } else if ((val >= 'A') && (val <= 'F')) {
            val = 10 + val - 'A';
          }
          
          if (bytesread & 1 == 1) {
            code[bytesread >> 1] = (val | (tempbyte << 4));
            if (bytesread >> 1 != 5) {               
              checksum ^= code[bytesread >> 1];      
            };
          } else {
            tempbyte = val;                          
          };

          bytesread++;                               
        } 
      } 

      if (bytesread == 12) {
        tagRFID[10] = '\0';
        validaAcesso();
      }            
      bytesread = 0;
    }
  }

  
}

void validaAcesso() 
{
  Serial.println(tagRFID);
  if (client.connect(serverName, 80)) {
    Serial.println("connected");
    client.print("GET /api/acesso/INNER/0001/"); //INNER é o codigo do cliente e 0001 o código do Equipamento
    client.print(tagRFID); 
    client.println(" HTTP/1.0");
    client.println("Host: dns.servidor.api"); //trocar pelo DNS API Web
    client.println(); 
  } 
  else {
    Serial.println("connection failed");
    Serial.println();
    lcd.setCursor(0, 1);

    lcd.print("Erro durante acesso ");
    lcd.setCursor(0, 2);
    lcd.print("Tente novamente     ");

  }

  inicioretornoServer = false;
  indexretornoServer = 0;
  
  while(client.connected() && !client.available()) delay(1); //waits for data
  while (client.connected() || client.available()) { //connected or data available
    char c = client.read(); //gets byte from ethernet buffer
    Serial.print(c);
    if (c == '|')
    {
      inicioretornoServer = !inicioretornoServer;
      indexretornoServer = 0;
    }
    
    if (inicioretornoServer)
    {    
      //Serial.println(indexretornoServer);          
      //Serial.println(c); 
      if(indexretornoServer == 1)
      {
            validacaoTag = c;            
      }
      else if(indexretornoServer >= 2 && indexretornoServer <= 22)      
      {
          nomeTag[indexretornoServer-2] = c;            
      }      
      indexretornoServer++;
      //Serial.println(indexretornoServer);          
    }  
  }

  Serial.println(" ");    
  Serial.print("Validacao: ");    
  Serial.print(validacaoTag);    
  Serial.println(" ");    
  Serial.print("Nome: ");    
  Serial.print(nomeTag);    
  
  lcd.setCursor(0, 1);
  lcd.print("                    ");
  lcd.setCursor(0, 2);
  lcd.print(nomeTag);
  lcd.setCursor(0, 3);

  if(validacaoTag == 'E'){
    digitalWrite(rele1, LOW);
    lcd.print("Entrada Registrada  ");}    
    
  if(validacaoTag == 'S'){
    digitalWrite(rele1, LOW);    
    lcd.print("Saida Registrada    ");}

   if(validacaoTag == 'X'){
    lcd.print("Cartao sem Acesso   ");}   

  Serial.println();
  Serial.println("disconnecting.");
  Serial.println("==================");
  Serial.println();


  delay(1000);  
  digitalWrite(rele1, HIGH);
  delay(500);  
  client.stop(); //stop client
  aguardandocomandos();  
}


void consultacartaoserver(){
   
  lcd.setCursor(0, 1);
  lcd.print("Consultando dados   ");   
  lcd.setCursor(0, 2);
  lcd.print("      Aguarde       ");   
    
  Serial.print("Cartao: ");
  Serial.println(tagRFID); 
  
  
  int thisData;
  thisData = 12234;


  
}

void aguardandocomandos(){
  lcd.setCursor(0, 1);
  lcd.print("                    ");
  lcd.setCursor(0, 2);
  lcd.print("Passe o Cartao      ");   
  lcd.setCursor(0, 3);
  lcd.print("                    ");


}


Fluxo de Operação

Código Fonte
O código fonte da API  e site de administração e localização está disponível no github.


Tagged

15 comentários :

  1. Boa noite Sergio, gostei muito do seu projeto e meu TCC eh muito parecido.
    A diferença eh que tenho que abrir um portão automatico e verificar no site o fluxo dos tags rfid.
    terias como me ajudar?

    ResponderExcluir
    Respostas
    1. O projeto já está preparado para integração com um portão automático, quando um cartão é autorizado, o circuito aciona o relé por um tempo programado. O site, infelizmente eu não posso disponibilizar o código fonte.

      Excluir
  2. Boa tarde Sérgio, no caso do site, vc quer quanto para disponibilizar o código?
    O meu TCC não tem nenhum foco na criação do site.
    Com certeza irei modificar muita coisa.
    O seu site tem acesso a qual banco de dados?

    ResponderExcluir
    Respostas
    1. Boa Tarde!

      O site é educacional, não comercializo código fonte de projetos.

      Desculpe.


      Excluir
    2. Boa noite Sérgio,

      Consegui fazer um sistema parecido, porém fiz com apenas duas tags.
      Queria colocar mais 4 tags, mas da seguinte forma:
      3 tags para identificar carros e as outras 3 tags identifica pessoas.
      O sistema só aceita a liberação do acesso, após 2 tags (distintas: carro e pessoa) forem válidos.
      o trecho do código segue abaixo, mas esse código não está dando certo. Tem como vc dar uma olhada e ver no que pode ajudar?
      ///////////////////////////////////
      //Verifica todos os tags
      ///////////////////////////////////

      if(strlen(tag) == 0) return; //se vazio, não verifica

      if(compareTag(tag, tag_carro))
      { // se é carro
      Serial.println("TAG 1");
      LCD.setCursor(0,1);
      LCD.print(" OCS 4616 ");
      carro_ok = 1;

      }else if(compareTag(tag, tag_pessoa))
      //se é pessoa
      Serial.println("TAG 2");
      LCD.setCursor(0,1);
      LCD.print(" Igor ");
      pessoa_ok = 1;

      if(compareTag(tag, tag_carro1))
      { // se é carro
      Serial.println("TAG 3");
      LCD.setCursor(0,1);
      LCD.print(" OSP 5408 ");
      carro_ok = 1;

      }else if(compareTag(tag, tag_pessoa1))
      { //se é pessoa
      Serial.println("TAG 4");
      LCD.setCursor(0,1);
      LCD.print(" Marcio ");
      pessoa_ok = 1;
      }
      else
      {// senão é nenhum dos dois escreve na serial
      Serial.println("Tag Inválido!");
      LCD.setCursor(0,1);
      LCD.print(" Tag Inválido ");
      carro_ok = 2;
      pessoa_ok = 2;
      }
      }

      Excluir
  3. Olá Sergio acho muito legal seu projeto assim como sua iniciativa e tudo mais.

    Comecei com Arduino a pouco tempo entretanto já programo a mais. Em um dos projetos que tive realizando com Arduino me deparei com a dificuldade em estar enviando varias variáveis ao Arduino ao mesmo tempo e o mesmo identificar o que é cada variável, seja via PHP ou C#.

    Pesquisei bastante na internet e esse projeto foi o que achei de mais próximo pois pelo que imagino na validação de acesso você precisa em algum momento retornar para o Arduino os dados e informações.

    Um exemplo que posso lhe dar é o controle de um LED RGB via PHP, aonde eu envio o código das cores obtidos para Arduino, no caso cada cor possui um código diferente, mas o Arduino não sabe diferenciar qual código é de cada cor. Outro exemplo é o de enviar dados de 3 sensores simultaneamente e saber de qual sensor no Arduino e cada dado enviado.

    Não sei se ficou claro mas ficarei grato se puder ajudar.

    Obrigado.

    ResponderExcluir
    Respostas
    1. Hércules, não ficou muito claro.
      Mas pelo que entendi, sua dificuldade é receber variaveis no arduino?
      Voce pode configurar como WebClient ou WebServer, precisa identificar qual implementação atende seu projeto.
      No meu caso, está implmentando como WebClient. Consumo uma WEBAPI Rest escrita em .NET (poderia sem em PHP, Java, etc) e essa API recebe o numero do cartao, valida e devolve um status.
      A partir da linha while(client.connected() && !client.available()) delay(1); //waits for data
      eu faço o tratamento e atualizo a variavel validacaoTag com o retorno.

      Excluir
    2. Sergio obrigado pela atenção.
      Pois então a dificuldade se encontra justamente em receber varias variáveis simultaneamente no Arduino já que não existe uma forma de eu identificar qual é cada variavel que eu enviei para o arduino sendo assim uma dificuldade no tratamento delas no arduino.

      Excluir
    3. Hercules,

      Nesse projeto eu recebo 2 variáveis, o status da validação e nome do Usuário, voce pode adaptar para enviar e receber mais variáveis.

      Response:
      |STATUS NOMEUSUARIO|
      |: Caracter que identifica o início do retorno de validação do acesso
      STATUS: Status da validação do acesso
      NOMEUSUARIO: Nome do Usuário
      |:Caracter que identifica o término do retorno de validação do acesso

      Excluir
  4. Bom dia Sergio. Estou desenvolvendo um sistema de controle para alunos e professores de uma escola municipal de música de minha cidade. Gostaria, se possível, da sua indicação do material para estudo. Se puder indicar eu agradeço.

    ResponderExcluir
  5. É no método valida acesso que enviar o ID para o web server ?Como faço para enviar para uma pagina php/jsp para capturar o valor da ID ?Ótimo tutorial.

    ResponderExcluir
    Respostas
    1. Fala Wilton, Boa Noite!
      No projeto eu precisava armazenar o histórico de acessos, a API apenas inseria um registro de localização e data do usuário no banco de dados e a página mostrava a última localização.

      Excluir
  6. Onde encontro esta API, seria possível compartilhar ?
    Obrigado.

    ResponderExcluir
    Respostas
    1. Boa tarde! A API e gerenciador foram desenvolvidos em .NET. Liberei o código fonte no github, o link foi disponibilizado no fim do artigo.

      Excluir