Help needed with ESP8266 RFID program

I started down the road of a project that I knew would require me to gain additional skills in the IDE world (my experience level is mid), but really ran stuck, and could use some assistance.

Basic components:
8vdc-50vdc to 5vdc regulator
ESP8266 dev (nodemcu 12E variant)
rfid-rc522
RFID fob's
3.3v-5v single relay board
tri-color led

Scope of project:
RFID badge reader interface to open/close contacts on a relay after 2 unique fob's are scanned (11 fob id's stored locally on device). LED to provide visual indication of status (red=inactive, blue=first scan good, green=second scan good) . The key elements: fob id's to remain with device, any combination of 2 fob id's from list required to activate relay (but not same fob twice).

Current work in progress code attached. As it sits, the code accounts for 21% space and 39% dynamic mem.

Core function is there, but I'm failing dramatically on getting my 2 step fob scan requirement to work. I've been attempting to try arrays and what not, but am really struggling. I'm definitely not looking for a hand out, but if there is something simple I'm overlooking, or another methodology entirely I should chase, please let me know. Any assistance would help at this point.

RFIDtest.ino (3.28 KB)

Please add your code to your message, inside code [/] tags. This way it's too hard to read.

For your problem, maybe something like this (pseudo-code, won't compile):

String RFID1 = "";
String RFID2 = "";

#define RED = 0;
#define BLUE = 1;
#define GREEN = 2;

loop() {
  newRFID = readRFID();
  if (newRFID) {
    if (inGoodList(newRFID)) {
      if (RFID1 == "") {
        RFID1 = newRFID;
        setLED(BLUE);
      }
      elif (newRFID != RFID1) {
        RFID2 = newRFID;
        setLED(GREEN);
      }
    }
    if (RFID1 && RFID2) {
      doopOpened = millis();
      openDoor(true);
      RFID1 = "";
      RFID2 = "";
    }
  }
  if (doorOpened - millis() > doorOpenInterval) {
    openDoor(false);
    setLED(RED);
  }
}

wvmarle:
Please add your code to your message, inside code [/] tags. This way it's too hard to read.

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

#define RST_PIN         20           // Reset pin, Configurable
#define SS_PIN          2            // SS / SDA pin, Configurable
MFRC522 mfrc522(SS_PIN, RST_PIN);    // Create MFRC522 instance.

#define Relay 10               //Relay pin
#define BlueLed 15             //Blue LED pin
#define GreenLed 0             //Green LED pin
#define RedLed 3               //Red LED pin

String read_rfid;
String ok_rfid_0="87e2e63a";
String ok_rfid_1="25a5f4c2";
String ok_rfid_2="4732d23a";
String ok_rfid_3="c71ae33a";
String ok_rfid_4="475be13a";
String ok_rfid_5="e785e23a";
String ok_rfid_6="57a1d13a";
String ok_rfid_7="278edf3a";
String ok_rfid_8="e77db3a";
String ok_rfid_9="7792c93a";
String ok_rfid_10="67f2db3a";         //add as many as you need.
 
void setup() {
    Serial.begin(9600);         // Initialize serial communications with the PC
    while (!Serial);            // Do nothing if no serial port is opened (added for Arduinos based on ATMEGA32U4)
    SPI.begin();                // Init SPI bus
    mfrc522.PCD_Init();         // Init MFRC522 card

    pinMode(Relay, OUTPUT);         //Set relay pin mode
    digitalWrite(Relay, HIGH);      //Set relay pin mode high/low depending on model of relay
    pinMode(BlueLed, OUTPUT);       //Set led pin mode
    pinMode(GreenLed, OUTPUT);      //Set led pin mode
    pinMode(RedLed, OUTPUT);        //Set led pin mode
    digitalWrite(RedLed, HIGH);     //Set red led pin mode high
    
}

/*
 * Helper routine to dump a byte array as hex values to Serial.
 */
void dump_byte_array(byte *buffer, byte bufferSize) {
    read_rfid="";
    for (byte i = 0; i < bufferSize; i++) {
        read_rfid=read_rfid + String(buffer[i], HEX);
    }
}
void no_good(){                 //Bad read or id not in list
  digitalWrite(Relay, HIGH);
  digitalWrite(RedLed, HIGH);
  digitalWrite(BlueLed, LOW);
  digitalWrite(GreenLed, LOW);
}
void scan_one() {               //First scan good, goto second scan
  digitalWrite(RedLed, LOW);
  digitalWrite(BlueLed, HIGH);
  digitalWrite(GreenLed, LOW);
  digitalWrite(Relay, HIGH);
}
void scan_two() {                 //Second scan good, goto relay close
  digitalWrite(RedLed, LOW);
  digitalWrite(BlueLed, HIGH);
  digitalWrite(GreenLed, HIGH);
  digitalWrite(Relay, HIGH);
}
void close_relay() {              //Relay close, normally open contacts
  digitalWrite(Relay, LOW);
  digitalWrite(GreenLed, HIGH);
  digitalWrite(BlueLed, LOW);
  digitalWrite(RedLed, LOW);
  delay(5000);                    //testing mode reset delay, remove before flight
  digitalWrite(Relay, HIGH);      //testing mode reset relay, remove before flight
  digitalWrite(GreenLed, LOW);    //testing mode reset led, remove before flight
  digitalWrite(RedLed, HIGH);     //testing mode reset led, remove before flight
}

void loop() {
   
      // Look for new cards
    if ( ! mfrc522.PICC_IsNewCardPresent())
        return;

    // Select one of the cards
    if ( ! mfrc522.PICC_ReadCardSerial())
        return;

    dump_byte_array(mfrc522.uid.uidByte, mfrc522.uid.size);
    Serial.println(read_rfid);
    if (read_rfid==ok_rfid_0){
        scan_one();                   //Valid rfid, wait for scan two
    }
        
    if (read_rfid==ok_rfid_1){
        close_relay();                   //Valid rfid, ready to close relay contacts
    }
    
    // else not needed. Anything else is not ok...
}

Sorry about that, couldn't copy/paste from the device I was on at the time of posting.

I think I get the rough idea of what you have in the pseudo code, I'll see if I can adapt it. But my initial question would be how to generate the "inGoodList" in your example beyond just looking at one String as I currently have it. Array?

Definitely tun that list ok_rfid in a string, that also makes it easier to add/remove some later. After that you can check for whether a received id is in the string like this:

bool isvalueinarray(int val, int *arr, int size){
    int i;
    for (i=0; i < size; i++) {
        if (arr[i] == val)
            return true;
    }
    return false;
}

Then you'll also want to add some time outs:

  • a maximum time between the first and second pass being scanned,
  • same for the LED's to switch off again.

Another good addition may be an alarm for when the door remains open (add e.g. a microswitch that tells you whether the door is open or not).

Thank you for the input thus far, still working on getting the darn thing to compile without sending me on a totally different tangent path to try and determine where I'm messing up...

USMCwarmachine:
Thank you for the input thus far, still working on getting the darn thing to compile

That shouldn't be too hard, the compiler is usually quite clear in what's wrong.

Especially if you get a long list of errors I did find it's a good idea to start with the top error, fix it, and recompile. Very often the next ten errors disappear as well (where the fix may have been a simple missing ; or } or so).

I'll admit to being in a frustration spiral of failure, the more I dive into what it takes to satisfy one error, the further down the rabbit hole I go. I've started to understand more of why the errors are occurring (can't be an char if it's HEX, can't convert String to Const char..), but holy cow. >:( I did not imagine I would struggle so badly with reading a UID, checking a list for go/no go, and then reading another UID that cannot be equal to the first, but still on the go/no go list. Newbies....lol

Here's the current work in progress:

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

#define RST_PIN         20           // Reset pin, Configurable
#define SS_PIN          2            // SS / SDA pin, Configurable
MFRC522 mfrc522(SS_PIN, RST_PIN);    // Create MFRC522 instance.

#define Relay 10               //Relay pin
#define BlueLed 15             //Blue LED pin
#define GreenLed 0             //Green LED pin
#define RedLed 3               //Red LED pin

String read_rfid;
//String ok_rfid_0="13522623058";
//String ok_rfid_1="37165244194";
//String ok_rfid_2="715021058";
//String ok_rfid_3="1992622758";
//String ok_rfid_4="719122558";
//String ok_rfid_5="23113322658";
//String ok_rfid_6="8716120958";
//String ok_rfid_7="3914222358";
//String ok_rfid_8="231721958";
//String ok_rfid_9="11914620158";
//String ok_rfid_10="10324221958";         //add as many as you need.

//int myArray[11]={13522623058, 37165244194, 715021058, 1992622758, 719122558, 23113322658, 8716120958, 3914222358, 231721958, 11914620158, 10324221958};
String okrfid="13522623058, 37165244194, 715021058, 1992622758, 719122558, 23113322658, 8716120958, 3914222358, 231721958, 11914620158, 10324221958";
//String okrfid="87e2e63a, 25a5f4c2, 4732d23a, c71ae33a, 475be13a, e785e23a, 57a1d13a, 278edf3a, e77db3a, 7792c93a, 67f2db3a";
int cardcount = 11;

void setup() {
    Serial.begin(9600);         // Initialize serial communications with the PC
    while (!Serial);            // Do nothing if no serial port is opened (added for Arduinos based on ATMEGA32U4)
    SPI.begin();                // Init SPI bus
    mfrc522.PCD_Init();         // Init MFRC522 card

    pinMode(Relay, OUTPUT);         //Set relay pin mode
    digitalWrite(Relay, HIGH);      //Set relay pin mode high/low depending on model of relay
    pinMode(BlueLed, OUTPUT);       //Set led pin mode
    pinMode(GreenLed, OUTPUT);      //Set led pin mode
    pinMode(RedLed, OUTPUT);        //Set led pin mode
    digitalWrite(RedLed, HIGH);     //Set red led pin mode high
    
}

/*
 * Helper routine to dump a byte array as hex values to Serial.
 */
void dump_byte_array(byte *buffer, byte bufferSize) {
    read_rfid="";
    for (byte i = 0; i < bufferSize; i++) {
        read_rfid=read_rfid + String(buffer[i], DEC);  //or HEX
    }
}
void no_good(){                 //Bad read or id not in list
  digitalWrite(Relay, HIGH);
  digitalWrite(RedLed, HIGH);
  digitalWrite(BlueLed, LOW);
  digitalWrite(GreenLed, LOW);
  Serial.println("Nope!");
}
void scan_one() {               //First scan good, goto second scan
  digitalWrite(RedLed, LOW);
  digitalWrite(BlueLed, HIGH);
  digitalWrite(GreenLed, LOW);
  digitalWrite(Relay, HIGH);
  Serial.println("Looks Good");
  delay(5000);                    //testing mode reset delay
  digitalWrite(Relay, HIGH);      //testing mode reset relay
  digitalWrite(BlueLed, LOW);     //testing mode reset led
  digitalWrite(GreenLed, LOW);    //testing mode reset led
  digitalWrite(RedLed, HIGH);     //testing mode reset led
}

void close_relay() {              //Relay close, normally open contacts
  digitalWrite(Relay, LOW);
  digitalWrite(GreenLed, HIGH);
  digitalWrite(BlueLed, LOW);
  digitalWrite(RedLed, LOW);
  delay(5000);                    //testing mode reset delay
  digitalWrite(Relay, HIGH);      //testing mode reset relay
  digitalWrite(GreenLed, LOW);    //testing mode reset led
  digitalWrite(RedLed, HIGH);     //testing mode reset led
}

void loop() {
 
       // Look for new cards
    if ( ! mfrc522.PICC_IsNewCardPresent())
        return;

    // Select one of the cards
    if ( ! mfrc522.PICC_ReadCardSerial())
        return;

    dump_byte_array(mfrc522.uid.uidByte, mfrc522.uid.size);
//    Serial.println(read_rfid);

    
   for(int i=0; i < cardcount; i++){
     if(strcmp(read_rfid,okrfid)==0){
        scan_one();
      }
    }
//      if (read_rfid==ok_rfid_0 || ok_rfid_1 || ok_rfid_2 || ok_rfid_3 || ok_rfid_4 || ok_rfid_5 || ok_rfid_6 || ok_rfid_7 || ok_rfid_8 || ok_rfid_9 || ok_rfid_10){
//          scan_one();                       //Valid rfid, wait for scan two
//    }
    
    
        
//      if (read_rfid==ok_rfid_3){
//        close_relay();                   //Valid rfid, ready to close relay contacts
//    }
    
    
    // else not needed. Anything else is not ok, and will not open the door...
}

USMCwarmachine:
can't be an char if it's HEX

Well that's just not true. EVERYTHING in a computer is stored as binary. Whether or not you wrote it in hexadecimal, decimal, octal, or binary has no bearing on what type of variable you can use. It all gets turned into binary in the end.

Delta_G:
Well that's just not true. EVERYTHING in a computer is stored as binary. Whether or not you wrote it in hexadecimal, decimal, octal, or binary has no bearing on what type of variable you can use. It all gets turned into binary in the end.

If you have any suggestions or advise, I'd appreciate it.

USMCwarmachine:

//int myArray[11]={13522623058, 37165244194, 715021058, 1992622758, 719122558, 23113322658, 8716120958, 3914222358, 231721958, 11914620158, 10324221958};

String okrfid="13522623058, 37165244194, 715021058, 1992622758, 719122558, 23113322658, 8716120958, 3914222358, 231721958, 11914620158, 10324221958";

The first is an array (of int values),

the second just a long String. You can make it an array of String as such:

String okrfid[2]={"13522623058", "37165244194"};

"If you have any suggestions or advise, I'd appreciate it."

About how to initialize a char variable with hex? I haven't seen what you did wrong there so there's not much I can tell you about how to fix it. But this would certainly work just as expected.

char foo = 0x49;  //foo == '1'

Delta_G:
"If you have any suggestions or advise, I'd appreciate it."

About how to initialize a char variable with hex? I haven't seen what you did wrong there so there's not much I can tell you about how to fix it. But this would certainly work just as expected.

char foo = 0x49;  //foo == '1'

Converting the UID to either DEC or HEX is an option, so that opened up options, but getting the comparison in the loop to be compile is causing me issues.

Please see the original scope

wvmarle:
The first is an array (of int values),

the second just a long String. You can make it an array of String as such:

String okrfid[2]={"13522623058", "37165244194"};

Thanks, I'll try again

Work has kept me away from trying out a few things, but I appreciate the input thus far.

Ran into an issue with any UID will now trigger the event, even if it is not in the list. Any input on where I went wrong? I've also started calling the read_rfid String as read_rfid1, in an assumption that I'll need two separate instance of UID reading (read_rfid2?) and then later do an if read_rfid1 != read_rfid2 but == okrfid[11] then close_relay type statement for my second stage pass/fail. Just thinking and typing here...but i'll have to sort out how to do that...

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

#define RST_PIN         20           // Reset pin, Configurable
#define SS_PIN          2            // SS / SDA pin, Configurable
MFRC522 mfrc522(SS_PIN, RST_PIN);    // Create MFRC522 instance.

#define Relay 10               //Relay pin
#define BlueLed 15             //Blue LED pin
#define GreenLed 0             //Green LED pin
#define RedLed 3               //Red LED pin

String read_rfid1;

String okrfid[11]={"13522623058", "37165244194", "715021058", "1992622758", "719122558", "23113322658", "8716120958", "3914222358", "231721958", "11914620158", "10324221958"};


void setup() {
    Serial.begin(9600);         // Initialize serial communications with the PC
    SPI.begin();                // Init SPI bus
    mfrc522.PCD_Init();         // Init MFRC522 card

    pinMode(Relay, OUTPUT);         //Set relay pin mode
    digitalWrite(Relay, HIGH);      //Set relay pin mode high/low depending on model of relay
    pinMode(BlueLed, OUTPUT);       //Set led pin mode
    pinMode(GreenLed, OUTPUT);      //Set led pin mode
    pinMode(RedLed, OUTPUT);        //Set led pin mode
    digitalWrite(RedLed, HIGH);     //Set red led pin mode high
    
}

/*
 * Helper routine to dump a byte array as hex values to Serial.
 */
void dump_byte_array(byte *buffer, byte bufferSize) {
    read_rfid1="";
    for (byte i = 0; i < bufferSize; i++) {
        read_rfid1=read_rfid1 + String(buffer[i], DEC);  //or HEX
    }
}
void no_good(){                 //Bad read or id not in list
  digitalWrite(Relay, HIGH);
  digitalWrite(RedLed, HIGH);
  digitalWrite(BlueLed, LOW);
  digitalWrite(GreenLed, LOW);
  Serial.println("Nope!");
}
void scan_one() {               //First scan good, goto second scan
  digitalWrite(RedLed, LOW);
  digitalWrite(BlueLed, HIGH);
  digitalWrite(GreenLed, LOW);
  digitalWrite(Relay, HIGH);
  Serial.println("Looks Good");

}

void close_relay() {              //Relay close, normally open contacts
  digitalWrite(Relay, LOW);
  digitalWrite(GreenLed, HIGH);
  digitalWrite(BlueLed, LOW);
  digitalWrite(RedLed, LOW);
  delay(5000);                    //testing mode reset delay
  digitalWrite(Relay, HIGH);      //testing mode reset relay
  digitalWrite(GreenLed, LOW);    //testing mode reset led
  digitalWrite(RedLed, HIGH);     //testing mode reset led
}

void loop() {
 
       // Look for new cards
    if ( ! mfrc522.PICC_IsNewCardPresent())
        return;

    // Select one of the cards
    if ( ! mfrc522.PICC_ReadCardSerial())
        return;

    dump_byte_array(mfrc522.uid.uidByte, mfrc522.uid.size);
    Serial.println(read_rfid1);

    
//      if (read_rfid1==ok_rfid[11]){
//          scan_one();                       //Valid rfid, wait for scan two
//    }
    
    
        
      if (read_rfid1==okrfid[11]){
        close_relay();                   //Valid rfid, ready to close relay contacts
    }
    
    
    // else not needed. Anything else is not ok, and will not open the door...
}

This is how I detect if the card is the good one or not.

byte goodCard0[10] = {0x4b, 0x50, 0x28, 0x2b};

byte goodCard1[10] = {0x00, 0x00, 0x00, 0x00};

void setup()
{

//standard code to initialize the rfid
}

void loop()

//standard code to initialize the rfid

if ((memcmp(goodCard0, mfrc522[reader].uid.uidByte, mfrc522[reader].uid.size) == 0) 

{

 // code to run when the card matches with goodCard0.

}

else if

if ((memcmp(goodCard1, mfrc522[reader].uid.uidByte, mfrc522[reader].uid.size) == 0)

{
 // code to run when the card matches with goodCard1.

}
}

There are two parts to your code, each of which can be tested separately.

  1. the reading and verification of the cards. Write a simple script that reads and verifies the cards, then prints "good" or "no good" on the Serial console.

  2. the locking/unlocking sequence. Write a simple sketch that reads Serial input (you just enter 1 if you want to simulate a good read, 0 for a wrong one - just like your verification routing would just return a true/false value).

Makes trying out things a lot easier. When both work it'll be a simple integration.

wvmarle:
There are two parts to your code, each of which can be tested separately.

  1. the reading and verification of the cards. Write a simple script that reads and verifies the cards, then prints "good" or "no good" on the Serial console.

  2. the locking/unlocking sequence. Write a simple sketch that reads Serial input (you just enter 1 if you want to simulate a good read, 0 for a wrong one - just like your verification routing would just return a true/false value).

Makes trying out things a lot easier. When both work it'll be a simple integration.

The first instance of the code (calling out each "good" UID as a separate String) proved the core relay and led sequence to work, but the issue I keep running into is my requirement for two sequential "good" UID's to be read, but not allow relay/led operation if it is the same UID swiped twice. I'm still stumped.

After switching the individual UID's from individual Strings to a String array, any UID (either in the "good" array or not) will pass. Which seems to be setting me back a step.

Throwing in the towel on this one for awhile, I appreciate the help.