Problema com código C - Arduino lendo RFID

Pessoal, boa tarde. :slight_smile:
Estou utilizando um modulo RFID e criei 2 arrays para guardar as chaves válidas e bloqueadas.
Qual é a lógica do loop:
Usando um "for" o código varre o primeiro array de chaves válidas. Se achar ok. Senão usando outro "for" procura no array de chaves bloqueadas. Se não estiver em nenhum desses arrays ele informa que a chave não esta cadastrada e mostra o UID da chave. Obviamente não liberando o acesso nesses dois últimos casos.
Os Problemas:
1 - Olhando o array de chaves bloqueadas, percebam que eu coloquei 2 chaves, uma na posição 0 e outra na posição 4, isso para que no teste eu garantisse que meu código estaria varrendo todo o array. Mas ai que está o problema, ele não esta varrendo todo o array. Quando utilizo essa última chave que esta cadastrada nos bloqueados ele não informa sobre chave bloqueada e sim inexistente.
2 - Tem um terceiro array que é de "nomes de usuários". A ideia seria associar esses itens de nomes as chaves autorizadas. Então quando uma chave autorizada é encontrada ela associa a posição e concatena no resultado o nome do usuário conforme a posição da chave. Como eu faria isso?
Tem um video que fiz para um colega me ajudar mas não descobrimos ainda. Pode servir como referencia para entender melhor o problema:

Vocês tem alguma ideia do que pode estar acontecendo? E como fazer para associar uma chave válida ao nome do usuário? :confused:

Segue código abaixo:
Muito Obrigado.

#include <SPI.h>
#include <MFRC522.h>
#define SS_PIN 10
#define RST_PIN 9
MFRC522 mfrc522(SS_PIN, RST_PIN);
//Pinos do LED RGB
int ledVermelho = 2;
int ledVerde = 3;
int ledAzul = 4;
// ******* CHAVES AUTORIZADAS *******
char* cartAut[] = {
/*0*/ "E4 DD 1F 2B", //CHAVE 1 (este é o cartão 1)
/*1*/ "XX XX XX XX", //CHAVE 2
/*2*/ "XX XX XX XX", //CHAVE 3
/*3*/ "XX XX XX XX", //CHAVE 4
/*4*/ "A9 60 90 85", //CHAVE 5
};
// ******* NOME DOS USUÁRIOS *******
char* cartName[] = {
/*0*/ "RAPHAEL", // USUARIO 1
/*1*/ "NOME DO USUARIO", // USUARIO 2
/*2*/ "NOME DO USUARIO", // USUARIO 3
/*3*/ "NOME DO USUARIO", // USUARIO 4
/*4*/ "NOME DO USUARIO", // USUARIO 5
};
// ******* CHAVES BLOQUEADAS *******
char* cartBlock[] = {
/*0*/ "42 F9 1C 2B", //CHAVE BLOQUEADA 1 (este é o cartão 2)
/*1*/ "XX XX XX XX", //CHAVE BLOQUEADA 2
/*2*/ "XX XX XX XX", //CHAVE BLOQUEADA 3
/*3*/ "XX XX XX XX", //CHAVE BLOQUEADA 4
/*4*/ "16 C5 BA 2D", //CHAVE BLOQUEADA 5
};
//char st[20];

void setup()
{
Serial.begin(9600);
SPI.begin();
mfrc522.PCD_Init();
mensageminicial();
//Inicia os pinos do LED RGB como saida
pinMode(ledVermelho, OUTPUT);
pinMode(ledVerde, OUTPUT);
pinMode(ledAzul, OUTPUT);
}

void loop()
{
// Look for new cards
if ( ! mfrc522.PICC_IsNewCardPresent())
{
return;
}
// Select one of the cards
if ( ! mfrc522.PICC_ReadCardSerial())
{
return;
}
// CONVERTE O ID DO CARTÃO PARA HEXADECIMAL MAIÚSCULO
String conteudo = "";
byte letra;
for (byte i = 0; i < mfrc522.uid.size; i++)
{
conteudo.concat(String(mfrc522.uid.uidByte[i] < 0x10 ? " 0" : " "));
conteudo.concat(String(mfrc522.uid.uidByte[i], HEX));
}
//boolean tagVerificada = false;
conteudo.toUpperCase();
// ****** CHECA AUTORIZADOS *******
for ( uint8_t a = 0; a < sizeof( cartAut ) / sizeof( cartAut[0] ); a++ ) {
if (conteudo.substring(1) == cartAut[a])
{
Serial.println("Acesso Liberado... ");
Serial.print("Bem vindo: ");
Serial.print(cartName[0]);
Serial.println();
//tagVerificada = true;
tagValida();
//delay(3000);
mensageminicial();
conteudo = "";
return;
}
}

//****** CHECA BLOQUEADOS *******
for ( uint8_t b = 0; b < sizeof( cartBlock ) / sizeof( cartBlock[0] ); b++ ) {
if (conteudo.substring(1) == cartBlock[b])
{
Serial.println("Desculpe, este cartao foi bloqueado!");
tagInvalida();
conteudo = "";
mensageminicial();
return;
}

// ****** AVISA QUE CARTÃO NÃO ESTÁ AUTORIZADO E IMPRIME ID *******
else {
Serial.println("Acesso negado!");
Serial.print("UID: ");
Serial.print(conteudo);
Serial.println();
tagInvalida();
mensageminicial();
conteudo = "";
return;
}
}
}
// MENSAGEM INICIAL
void mensageminicial()
{
Serial.println();
Serial.println("Ola! Aproxime o seu cartao do leitor...");
digitalWrite(ledAzul, LOW);
digitalWrite(ledVermelho, HIGH);
digitalWrite(ledVerde, HIGH);
}

//Metodo chamado quando a tag é valida e cadastrada
void tagValida()
{
digitalWrite(ledAzul, HIGH);
digitalWrite(ledVermelho, HIGH);
digitalWrite(ledVerde, LOW);
delay(3000);
}
//Metodo chamado quando a tag invalida / desconhecida
void tagInvalida()
{
digitalWrite(ledAzul, HIGH);
digitalWrite(ledVermelho, LOW);
digitalWrite(ledVerde, HIGH);
delay(3000);
}

À primeira vista, eu digo que falta um espaço no início das chaves. Ou seja, isto:

// ******* CHAVES AUTORIZADAS *******
char* cartAut[] = {
/*0*/ "E4 DD 1F 2B", //CHAVE 1 (este é o cartão 1)
/*1*/ "XX XX XX XX", //CHAVE 2
/*2*/ "XX XX XX XX", //CHAVE 3
/*3*/ "XX XX XX XX", //CHAVE 4
/*4*/ "A9 60 90 85", //CHAVE 5
};

devia ser isto:

// ******* CHAVES AUTORIZADAS *******
char* cartAut[] = {
/*0*/ " E4 DD 1F 2B", //CHAVE 1 (este é o cartão 1)
/*1*/ " XX XX XX XX", //CHAVE 2
/*2*/ " XX XX XX XX", //CHAVE 3
/*3*/ " XX XX XX XX", //CHAVE 4
/*4*/ " A9 60 90 85", //CHAVE 5
};

Repare a posição em que está esta linha:

conteudo.concat(String(mfrc522.uid.uidByte[i] < 0x10 ? " 0" : " "));

primeiro adiciona o espaço e só depois é que adiciona o valor HEX.

Também não sei se está usando o a letra correcta. Será que na chave lida não existe "e4" em vez de "E4"?
Por outro lado, não sei se este if funciona:

if (conteudo.substring(1) == cartAut[a])

Repare que "conteudo" é uma variável do tipo String, mas "cartAut[a]", não o é! Se fosse eu a escrever esse código não utilizaria a variável do tipo String e faria as duas do tipo array de char.

Porque não adiciona umas linhas de debug para ver o que está acontecendo, por exemplo:

(...)
// CONVERTE O ID DO CARTÃO PARA HEXADECIMAL MAIÚSCULO
String conteudo = "";
byte letra;
for (byte i = 0; i < mfrc522.uid.size; i++)
{
conteudo.concat(String(mfrc522.uid.uidByte[i] < 0x10 ? " 0" : " "));
conteudo.concat(String(mfrc522.uid.uidByte[i], HEX));
}
Serial.print("Cartão lido: ");
Serial.println(conteudo);
(...)

Luisilva, muito obrigado pela resposta.
Vou verificar mais tarde todos os pontos levantados por você.
Assim que tiver uma resposta trago o feedback aqui.

E quanto a fazer a correspondência de chave vs nome do usuário? Saberia como fazer isso?

Obrigado novamente.

rptmatrox:
Luisilva, muito obrigado pela resposta.
Vou verificar mais tarde todos os pontos levantados por você.
Assim que tiver uma resposta trago o feedback aqui.

E quanto a fazer a correspondência de chave vs nome do usuário? Saberia como fazer isso?

Obrigado novamente.

Só vi o vídeo agora e pelo que vi, o problema é bem mais fácil do que o que eu estava a imaginar inicialmente.
O problema é este else:

else {
Serial.println("Acesso negado!");
Serial.print("UID: ");
Serial.print(conteudo);
Serial.println();
tagInvalida();
mensageminicial();
conteudo = "";
return;
}

Repare que o "else" é executado para TODAS as posições do array. Por isso, quando passa o cartão que está na 4ª posição, quando o "for" é executado ele verifica se o valor do cartão é o que está na 1ª posição. Como não é, ele executa IMEDIATAMENTE o "else" e mostra a mensagem de erro (não passa à próxima posição e tenta ver se o cartão é o que está na 2ª posição).
O "else" tem OBRIGATORIAMENTE que ser executado fora do "for" (se não foi detectado o cartão em NENHUMA das posições do array de bloqueados, então o acesso é negado). Como o "if" está dentro do "for" o "else" não pode existir fora desse ciclo for. Sendo assim, vai ter que testar essa condição recorrendo a outra estratégia, por exemplo usar uma variável que fica 1 quando ele encontra a chave e 0 caso contrário.

Qualquer coisa assim:

(...)

void loop()
{
// Look for new cards
if ( ! mfrc522.PICC_IsNewCardPresent())
{
return;
}
// Select one of the cards
if ( ! mfrc522.PICC_ReadCardSerial())
{
return;
}
// CONVERTE O ID DO CARTÃO PARA HEXADECIMAL MAIÚSCULO
String conteudo = "";
byte letra;
int encontrou = 0;

for (byte i = 0; i < mfrc522.uid.size; i++)
{
conteudo.concat(String(mfrc522.uid.uidByte[i] < 0x10 ? " 0" : " "));
conteudo.concat(String(mfrc522.uid.uidByte[i], HEX));
}
//boolean tagVerificada = false;
conteudo.toUpperCase();
// ****** CHECA AUTORIZADOS *******
for ( uint8_t a = 0; a < sizeof( cartAut ) / sizeof( cartAut[0] ); a++ ) {
if (conteudo.substring(1) == cartAut[a])
{
Serial.println("Acesso Liberado... ");
Serial.print("Bem vindo: ");
Serial.print(cartName[0]);
Serial.println();
//tagVerificada = true;
tagValida();
//delay(3000);
mensageminicial();
conteudo = "";
return;
}
}

//****** CHECA BLOQUEADOS *******
for ( uint8_t b = 0; b < sizeof( cartBlock ) / sizeof( cartBlock[0] ); b++ ) {
if (conteudo.substring(1) == cartBlock[b])
{
Serial.println("Desculpe, este cartao foi bloqueado!");
tagInvalida();
conteudo = "";
mensageminicial();
encontrou = 1;
}
}

// ****** AVISA QUE CARTÃO NÃO ESTÁ AUTORIZADO E IMPRIME ID *******
if (encontrou == 0) {
Serial.println("Acesso negado!");
Serial.print("UID: ");
Serial.print(conteudo);
Serial.println();
tagInvalida();
mensageminicial();
conteudo = "";
return;
}

}

Na minha opinião, o maior erro que está cometendo no seu código é o uso do "return". Deveria ver-se livre de TODOS os "return" da função "loop()".

Luisilva, obrigado novamente pela resposta.
Boas notícias funcionou =D e aprendi mais uma lição lol.

Apenas modifiquei o tipo de variável para bool (não sei se faz mais sentido para o propósito, mas usei =p)

Quanto ao "return", tentei remover do código, mas ai o que acontece é que no SERIAL ele imprime a mensagem de tag não identificada 6 vezes, ou seja pelo que entendi ele repete isso em todos os valores do array. Então acredito que precisa desse RETURN para em caso de sucesso sair do loop e passar para a próxima instrução.
Na verdade o código original tinha um "break". Sabe a diferença entre eles?

E quanto a possibilidade de imprimir o nome do usuário quando ele encontra uma chave válida, saberia como fazer esta regra?

Muito obrigado pela disposição de tempo em auxiliar.

Abs

O outro problema ainda é ais fácil de resolver. Basta utilizar o índice encontrado para o array "cartAut". Assim, basta fazer:

for ( uint8_t a = 0; a < sizeof( cartAut ) / sizeof( cartAut[0] ); a++ ) {
if (conteudo.substring(1) == cartAut[a])
{
Serial.println("Acesso Liberado... ");
Serial.print("Bem vindo: ");
Serial.print(cartName[a]);   //NESTA LINHA
Serial.println();
//tagVerificada = true;
tagValida();
//delay(3000);
mensageminicial();
conteudo = "";
return;
}

Deve ter em atenção que os nomes devem estar na mesma ordem que estão os cartões.

Nossa não imaginava que seria tão fácil assim.
Ainda não testei, mas a noite vou testar e lhe aviso.
Com certeza colocarei todos os itens de array em ordem correspondente.

Novamente muito obrigado.
Abs

Luisilva, boa noite.
Obrigado por toda a ajuda. Tudo funcionou perfeitamente e esta do jeito que eu queria =D

Segue código pronto a quem interessar. Apenas removi as chaves e nomes. Deixando o código limpo para receber as chaves que quiserem.
Aqui está o tutorial que utilizei como referência, apenas removi o LCD, pois não vou utilizar desta forma, mas é simples de implementar o LCD novamente:

Abraços.

#include <SPI.h>
#include <MFRC522.h>

#define SS_PIN 10
#define RST_PIN 9
MFRC522 mfrc522(SS_PIN, RST_PIN);

//Pinos do LED RGB
int ledVermelho = 2;
int ledVerde = 3;
int ledAzul = 4;

// ******* CHAVES AUTORIZADAS *******
char* cartAut[] = {
  /*0*/ "XX XX XX XX", //CHAVE 1 
  /*1*/ "XX XX XX XX", //CHAVE 2
  /*2*/ "XX XX XX XX", //CHAVE 3
  /*3*/ "XX XX XX XX", //CHAVE 4
  /*4*/ "XX XX XX XX", //CHAVE 5
};

// ******* NOME DOS USUÁRIOS  *******
char* cartName[] = {
  /*0*/ "NOME DO USUARIO 1", // USUARIO 1
  /*1*/ "NOME DO USUARIO 2", // USUARIO 2
  /*2*/ "NOME DO USUARIO 3", // USUARIO 3
  /*3*/ "NOME DO USUARIO 4", // USUARIO 4
  /*4*/ "NOME DO USUARIO 5", // USUARIO 5
};

// ******* CHAVES BLOQUEADAS *******
char* cartBlock[] = {
  /*0*/ "XX XX XX XX", //CHAVE BLOQUEADA 1
  /*1*/ "XX XX XX XX", //CHAVE BLOQUEADA 2
  /*2*/ "XX XX XX XX", //CHAVE BLOQUEADA 3
  /*3*/ "XX XX XX XX", //CHAVE BLOQUEADA 4
  /*4*/ "XX XX XX XX", //CHAVE BLOQUEADA 5
};

bool unknowTag=true;


void setup()
{
  Serial.begin(9600);
  SPI.begin();
  mfrc522.PCD_Init();
  mensageminicial();

  //Inicia os pinos do LED RGB como saida
  pinMode(ledVermelho, OUTPUT);
  pinMode(ledVerde, OUTPUT);
  pinMode(ledAzul, OUTPUT);
}


void loop()
{

  // Look for new cards
  if ( ! mfrc522.PICC_IsNewCardPresent())
  {
    return;
  }
  // Select one of the cards
  if ( ! mfrc522.PICC_ReadCardSerial())
  {
    return;
  }

  // CONVERTE O ID DO CARTÃO PARA HEXADECIMAL MAIÚSCULO
  String conteudo = "";
  byte letra;
  for (byte i = 0; i < mfrc522.uid.size; i++)
  {
    conteudo.concat(String(mfrc522.uid.uidByte[i] < 0x10 ? " 0" : " "));
    conteudo.concat(String(mfrc522.uid.uidByte[i], HEX));
  }

  //boolean tagVerificada = false;
  conteudo.toUpperCase();

  // ******  CHECA AUTORIZADOS *******
  for ( uint8_t a = 0; a < sizeof( cartAut ) / sizeof( cartAut[0] ); a++ ) {
    if (conteudo.substring(1) == cartAut[a])
    {
      Serial.println("Acesso Liberado... ");
      Serial.print("Bem vindo: ");
      
      //int cartPosition;

      //Colocar a posição do array de chave autorizada na variável cartPosition acima
      //cartPosition =  0;
      
      //Imprime o nome correspondente do array de nomes
      Serial.print(cartName[a]);
      
      Serial.println();
      tagValida();
      mensageminicial();
      conteudo = "";
      return;
    }
  }
  
  //******  CHECA BLOQUEADOS *******
  for ( uint8_t b = 0; b < sizeof( cartBlock ) / sizeof( cartBlock[0] ); b++ ) {
    if (conteudo.substring(1) == cartBlock[b])
    {
      Serial.println("Desculpe, este cartao foi bloqueado!");
      tagInvalida();
      conteudo = "";
      mensageminicial();
      unknowTag = true;
      return;
    }
    
    // ******  AVISA QUE CARTÃO NÃO ESTÁ AUTORIZADO E IMPRIME ID *******
    if (unknowTag == true) {
      Serial.println("Acesso negado!");
      Serial.print("UID: ");
      Serial.print(conteudo);
      Serial.println();
      tagInvalida();
      mensageminicial();
      conteudo = "";
      return;
    }
  }
}

// MENSAGEM INICIAL
void mensageminicial()
{
  Serial.println();
  Serial.println("Ola! Aproxime o seu cartao do leitor...");
  digitalWrite(ledAzul, LOW);
  digitalWrite(ledVermelho, HIGH);
  digitalWrite(ledVerde, HIGH);
}


//Metodo chamado quando a tag é valida e cadastrada
void tagValida()
{
  digitalWrite(ledAzul, HIGH);
  digitalWrite(ledVermelho, HIGH);
  digitalWrite(ledVerde, LOW);
  delay(3000);
}

//Metodo chamado quando a tag invalida / desconhecida
void tagInvalida()
{
  digitalWrite(ledAzul, HIGH);
  digitalWrite(ledVermelho,  LOW);
  digitalWrite(ledVerde, HIGH);
  delay(3000);
}