1

I successfully programmed an RFID card reader to switch lights on and off if any rfid card is presented. I have tested this and it works, with the lights continually switching on and off if any rfid enabled card is is presented.

I tried to add a command that if two specific cards are read (identified by their UID numbers) then only those cards would reset the lights to "off" no matter what the state they were currently in - like a reset button.

The problem is that once one of those cards is presented, the light goes off but the system stops responding and presenting one of the other cards no longer turns the light on and off.

I am fairly new to programming Arduino, as well as with RFID technology, but it seems like the loop does not reset to the beginning properly, or my IF statement somehow leaves the system in a state where the beginning code can't be run.

My code is below. Any thoughts would be appreciated.

`

#define r1 A0
int relay1 = LOW;

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

#define SS_PIN 10
#define RST_PIN 9
MFRC522 mfrc522(SS_PIN, RST_PIN);   // Create MFRC522 instance.


void setup()
{
  pinMode(r1, OUTPUT);

  Serial.begin(9600);   // Initiate a serial communication
  SPI.begin();      // Initiate  SPI bus
  mfrc522.PCD_Init();   // Initiate MFRC522
  Serial.println("Approximate your card to the reader...");
  Serial.println();
}

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

  //Show UID on serial monitor
  Serial.print("UID tag :");
  String content = "";
  byte letter;
  for (byte i = 0; i < mfrc522.uid.size; i++)
  {
    Serial.print(mfrc522.uid.uidByte[i] < 0x10 ? " 0" : " ");  
    Serial.print(mfrc522.uid.uidByte[i], HEX);
    content.concat(String(mfrc522.uid.uidByte[i] < 0x10 ? " 0" : " "));  
    content.concat(String(mfrc522.uid.uidByte[i], HEX));
  }
  Serial.println();
  Serial.print("Message : ");
  content.toUpperCase();


  if ((content.substring(1) == "23 49 1F BE") || (content.substring(1) == "CB CB 2C E3")) //change here the UID of the card/cards that you want to give access
  {
   Serial.println("Staff access");
    Serial.println();
    relay1 = HIGH;
    digitalWrite(r1, relay1);
    delay(500);
  }
  else
  {

    Serial.println("Authorized access");
    Serial.println();
    relay1 = ~ relay1;
    digitalWrite(r1, relay1);
    delay(500);
  }
}

`

7
  • Are you looking at the serial output when this happens? do you see the "Staff Access" message? and then is there any other indication of what its doing? I would add print statements in the two places you return, this way you will be able to monitor the state of the loop and/or see if it stops running and where the last place it printed from.
    – Chad G
    Commented May 11, 2023 at 18:16
  • 1
    if the first card i present is a generic card, the serial monitor returns "authorized access" with each tap and keeps turning the light on and off. If I then present staff card, the serial monitor returns "staff access" but the lights do nothing, and thereafter, if i tap the generic card again, the serial monitor returns "authorize access again, but the lights don't respond anymore.
    – Christine
    Commented May 11, 2023 at 22:07
  • This operation on an int needs some explanation: relay1 = ~ relay1;. Is there another way you could achieve your goal here?
    – 6v6gt
    Commented May 12, 2023 at 3:34
  • Ya, relay1 should be a bool, and then use relay1=!relay1; to switch states.
    – Chad G
    Commented May 12, 2023 at 15:17
  • relay1 = ~relay1 worked fine when i was just using one criteria for the cards (meaning everyone was authorized). it was only when I added the criteria of "Staff access" that it stopped working. Is there a particular reason why !relay1 would work better than ~relay1 ?
    – Christine
    Commented May 13, 2023 at 15:12

1 Answer 1

1

The problem is the inappropriate use of the tilde (~) , which is a bitwise NOT operator, against the int variable relay1. It appears to work correctly when relay1 starts with LOW which has the value 0. That is, relay1 has the internal value 0b0000000000000000. If now the statement relay1 = ~relay1 is executed, relay1 has the internal value 0b1111111111111111. This is treated as a HIGH in the expression digitalWrite(r1, relay1); So it appears to work correctly. If again the statement relay1 = ~relay1 is executed, relay1 has the internal value 0b0000000000000000 This is treated as a LOW in the expression digitalWrite(r1, relay1); So that would also appear to work continuously, turning the relay on and off.

The problem comes when you explicitly set relay1 to HIGH here: relay1 = HIGH;. HIGH has the value 1, that is relay1 now has the intenal value 0b0000000000000001 and again that works, however, the next execution of the statement relay1 = ~relay1 gives relay1 the internal value 0b1111111111111110 which is also treated as HIGH. So, from now on, the statement relay1 = ~relay1 will always result in relay1 having a value which is interpreted as HIGH. So the relay appears to be stuck.

The solution, which already appears in a comment, is to change the statement int relay1 = LOW; to bool relay1 = LOW; and change this statement relay1 = ~ relay1; to relay1 = ! relay1;

2
  • Thank you SO much for explaining. I didn't understand that there would be an internal value other than zero and one associated with LOW and HIGH, so couldn't really see how the solution of changing the relay statement would help. That does sound like it will fix the problem and now I have another concept to look into and understand more :)
    – Christine
    Commented May 14, 2023 at 14:01
  • @Christine, the protocol is to tick the answer is correct. :-) Commented Jun 14, 2023 at 4:50

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.