Mobile RFID reader - a Maker Kit project

As a first project I set out to build a mobile RFID reader posting live data to either MySQL, Google Sheets or Ubidots via Webhooks.

Note:

This is not a tutorial as such, rather just a showcase of the product. As I have had much help from the Particle Forum, I have deiced to publish my Eagle files and code to make it available to anyone that might want to use it.

I assume you have basic knowledge of the Particle environment, web hooks and have set up your account and devices in Particle Console. If not, please do so before attempting this build.

The brief:
Building a truly wireless (mobile) RFID scanner with the purposed of scanning RFID cards, capturing the UID’s off these cards and posting them to either;

  • Google Sheets
  • MySQL Database
  • Dashboard

Bill of materials:

  1. MFRC522 card reader module
  2. 3.7V LiPo 1100mA Battery
  3. Battery Charing module
  4. LM394N
  5. Bunch of 0603 LEDs for battery indicator
  6. 2 x RGB LEDs for system status and card read status
  7. Particle Photon
  8. Slide switch - Main power
  9. Tilt switch
  10. Custom design PCB
  11. Custom design enclosure
  12. Various 0603 resistors
  13. Ferrite !!!

First things first:

If you are anything like me, simple generic prototype enclosure will not suffice, so I put a little extra effort in, got to know my way around Rhinoceros and designed a simple, yet elegant (or at least I thought so) enclosure that would showcase the Particle Photon and some other components.

In addition to this, I decided not to opt for a generic proto board as I absolutely HATE wires. I included an image of my initial attempt to make a “pretty” board using proto board and jumper wires, but after couple of hours realised it simply won’t do. Yet another learning curve, Google’d and spent couple of hours on YouTube and managed to find my way around Autodesk Eagle. Worth every minute spent.



***The last image indicating the fully assembled PCB with status LED indicating "OK" as well as the LM3914N in action indicating ±90% charged battery. (7 of 8 LED’s)

Submitted the Gerber files to PCBWAY and in less than a week and In had my brand new custom PCB’s ready for assembly.

The important stuff:

Now the coding, this is the part that I struggle with the most, but thanks to some helpful gentleman on the Particle and Hackster forums, I came up with the code below. Now it probably is not the cleanest code ever written, but it works, so feel free to use and improve if you’d like.

//  Project:        Mobile RFID Attendence register 
//                      A project by FireFli (PTY) LTD

//  Date:                July 2019
//  Compiled by:    Friedl Basson
//  Details:            Scan for UID's from RFID cards and posting via webhooks to, UbiDots, mySQL DB or Google Sheets
//  Credits:            Sepcial thanks to the Particle community for assisting and making this project possible!
//  Firmware:       V2.1.1



//System Mode// - comment out if you will be settng up WiFi via Particle app and do not need to connect to another Wireless network aftwer the fact
//SYSTEM_MODE(SEMI_AUTOMATIC);


// This #include statement was automatically added by the Particle IDE.
#include "RFID.h"
#include <Ubidots.h>


/* Define the pins used for the SS (SDA) and RST (reset) pins for BOTH hardware and software SPI */
#define SS_PIN      A2      
#define RST_PIN     D2

/* Define the pins used for the DATA OUT (MOSI), DATA IN (MISO) and CLOCK (SCK) pins for SOFTWARE SPI ONLY */
#define MOSI_PIN    D3      
#define MISO_PIN    D4      
#define SCK_PIN     D5      


//Initialising RGB START  - RGB LED and buzzer is used as system status indicator
int redPin = D6;       
int greenPin = D1;    
int bluePin = D0;     
int buzzPin = D7;
//Initializing RGB END   


/* Create an instance of the RFID library */
#if defined(_USE_SOFT_SPI_)
    RFID RC522(SS_PIN, RST_PIN, MOSI_PIN, MISO_PIN, SCK_PIN);    // Software SPI
#else
    RFID RC522(SS_PIN, RST_PIN);                                 // Hardware SPI
#endif

//const char* WEBHOOK_NAME = "rfid_uid";
const char* WEBHOOK_NAME = "Ubidots";
Ubidots ubidots("webhook", UBI_PARTICLE);

void setup()

{ 
    
  Serial.begin(9600);    
  
//  WiFi.listen();

        pinMode(redPin, OUTPUT);
        pinMode(greenPin, OUTPUT);
        pinMode(bluePin, OUTPUT);
        pinMode(buzzPin, OUTPUT);
    

// Setting credentials for new WiFi Connection
/*  
    This section is only needed if you want to connect to a new WiFi Network after initial setup
    This will only work if current WiFi credentials have been cleared.  
    Code will run ONLY ONCE on startup and set new crediatials specified.  Once new credentials is set, this code will not run again.
*/

WiFi.on();

if (!WiFi.hasCredentials()) {
WiFi.setCredentials("SSID", "PASSWORD", WPA2, WLAN_CIPHER_AES);      
}

WiFi.connect();
waitUntil(WiFi.ready);
Particle.connect();

#if !defined(_USE_SOFT_SPI_)
  /* Enable the HW SPI interface */
  SPI.setDataMode(SPI_MODE0);
  SPI.setBitOrder(MSBFIRST);
  SPI.setClockDivider(SPI_CLOCK_DIV8);
  SPI.begin();
#endif

  /* Initialise the RFID reader */
  RC522.init();

delay(5000);
            
            digitalWrite(bluePin, HIGH);
            digitalWrite(greenPin, HIGH);
            digitalWrite(redPin, LOW); 

}

 
void loop()

{
 
  /* Temporary loop counter */
  uint8_t i;

  /* Has a card been detected? */
  if (RC522.isCard())
  {
    /* If so then get its serial number */
    RC522.readCardSerial();

  char str[16]; 
  snprintf(str, sizeof(str)
          , "%02X %02X %02X %02X"
          , RC522.serNum[0]
          , RC522.serNum[1]
          , RC522.serNum[2]
          , RC522.serNum[3]
          );

// Webhooks//
/*
RFID_WP = your webhook name
str = your data you want to publish
PRIVATE or PUBLIC
*/

//            Particle.publish("RFID_WP", str, PRIVATE);          //Publish Data to Wordpress DB
//            Particle.publish("XLS", str, PRIVATE);              // Publish Data to Google Sheets   
        
        Serial.print(str);
        

/* Adds context key-value pairs */
    ubidots.addContext("UID", str);
    char* context = (char *) malloc(sizeof(char) * 60);

    /* Builds the context with the array above to send to Ubidots */
    ubidots.getContext(context);
    ubidots.add("UID", 1, context);  // Change for your variable name  
    
    bool bufferSent = false;
    bufferSent = ubidots.send(WEBHOOK_NAME, PUBLIC);  // Will use particle webhooks to send data
    
    
//}
    
// - TRY Ubidots - //          

            
//            digitalWrite(buzzPin, HIGH);
            delay(500);
            digitalWrite(buzzPin, LOW);
            digitalWrite(bluePin, LOW);
            delay(750);
            digitalWrite(bluePin, HIGH);
            
}
             
            
else if (RC522.isCard())
  
  {

    RC522.readCardSerial();

 char str[16]; 
  snprintf(str, sizeof(str)
          , "%02X %02X %02X %02X"
          , RC522.serNum[0]
          , RC522.serNum[1]
          , RC522.serNum[2]
          , RC522.serNum[3]
          ); 

            digitalWrite(bluePin, LOW);
            digitalWrite(greenPin, LOW);
            digitalWrite(redPin, HIGH);
 //         digitalWrite(buzzPin, HIGH);
            delay(1000);
            digitalWrite(bluePin, HIGH);
            digitalWrite(greenPin, HIGH);
            digitalWrite(redPin, LOW);
            digitalWrite(buzzPin, LOW);
    }
 
  delay(500);

}



Front Ends:

Thanks the the webhook function in the Particle Console, I was able to seamlessly post code to just about anywhere. Now if you know PHP and MySQL quite well, you might be able to write your own server side script, but for those who are new to this like me, I would recommend the following two services;

  • Zapier
  • Ubidots

The differ vastly, so you have a look at both to determine which is more suitable for your use. Bottom line, if you want the data to be published live to a location of your choice, Zapier (or something similar) is the way to go. If you do not mind storing data on someone else’s server, Ubidots is a much more cost effective (cost per datapoints) way to go and has the added benefit of some nifty widgets to present your data in a graphical way. I have attached a screen grab of a sample Dashboard I build in Ubidots.


In hind sight:

Initially I though building a battery indicator that works outside of the Microcontroller was the best idea as It would function independently and it frees up much needed digital pins, but the trade-off to this is that without an analogue input being sent to the MC, you are not able to display the battery life on a dashboard. The LM3914N also requires some calculations to set reference volutes and to determine which resistors to use depending on your voltage difference between “fully charge” and “depleted” status. Keep in mind that for all praticle reasons you should work with 3.1V on the battery as depleted as most components will not work below 3V or start behaving sporadically. Six of the one I suppose.

I would also not make use of the tilt switch again to trigger the battery indicator as it is to sensitive and causes ‘flicker’. A simple tactile switch seems like a much better idea
 just a though.

A Must:

The biggest learning curve here for me was the effect any metal or circuit will have and a RFID reader. I designed, built and tested the entire unit first connected to a constant PSU. Due to the compact design of the unit, the battery was installed in very close proximity to the RFID reader module. The consequence
. No scans :astonished: As I temporary measure I wrapped the battery in electrical insulation tape which did an “ok” job. I ordered some Ferrite from Amazon as a Hail Mary and like magic the interference was a thing of the past.

Thank you to everyone that assisted with the project in some way, @ScruffR for understanding we all had to start somewhere and showing extreme patience :slight_smile: Also a huge thank you to @Joe at Particle for the awesome Maker Kits. Looking forward to more projects!!!

Files:
Eagle Schematic - DOWNLOAD
Eagle Board File - DOWNLOAD

7 Likes

The project looks amazing and nicely presented. Well done!!!

as for:

I read one time he said that he's standing in the shoulders of giants, but I think he's a giant himself.
Way to go!
Gustavo.

2 Likes

Hi Gustavo -

Thank you for the good feedback. Fior someone nw in this is looking to pursue this further, such comments are greatly appreciated.

If you have any feedback on to improve presentation, please feel free to advise. As this was my first post, I am sure there are plenty of ways to improve. I will try to put the images to better use.

@ScruffR was a great in helping me compile the string to send via Particle web hooks to mySQL

I will post more projects soon, working on a much larger and possible more intriguing project. Will post as I progress :slight_smile:

I hope this project help some newbies!

Many Thanks,
Friedl.

1 Like

So what exactly what your motivation for building this RFID card reader?

I’m assuming to count attendance, but did all the vistors get RFID Cards, please tell us more if you can.

Thanks for sharing!

Hi RWB -

The scanner was for a corporate client. They have employee count of ±250 and have regular compulsory training session, not necessarily at the same location.

They needed a mobile attendance register, not connected via USB to a laptop but one which could funciton completely independently. They would alway be able to connect to WiFi either via local WiFi or to a phone, so I suggested WiFi as apposed to a 3G connection.

The data is currently being sent either to the dashboard as indicated, or to a mySQL database in which they also store all personal information. In this database the link between UID’s that attended and personal is made and this way they have record of which personal attended the compulsory hours of training.

So to answer your question, yes all employees have, and visitors are assigned, RFID cards.

Hope this makes sense, let me know if you have any further questions.

2 Likes

Before asking something, big thanks for your effort first, Friedl Basson.

I planned to use mobile RFID reader entegrated with relay for opening door. The issue is security that we can manipulate relays easily and if we connect RFID and door relay without a wire we assume the problem will be solved but readers will mounted the walls. So in deep sleep mode, tilt switch might doesn’t work. Do you inform me about the power assumption of the system and any solution to wake up procedure when we don’t use tilt switch? Thanks.

Hi @cnrysv -

No problem, I gladly will help wherever I can :slight_smile:

Just one side note first; The tilt switch in my case was simply to activate the battery monitor and had no effect whatsoever on the device. The battery monitor operates independently from the device in order for the client to be able to see battery status even when device is power off completely.

In your case (wall mounted) I would assume the device will be permanently powered correct, or do you want to battery power them? My question is then, if on permanent power, do you really need Deep Sleep?

To answer your question (and in my experience) the MFRC522 will bring the device out of sleep mode when sending data from the reader module to the MCU. Did you maybe test this already?

With regards to the power consumption; I have not measured it in ideal circumstances but rather asked the client to give me real world feedback. With daily use, they recharge the devices weekly. We are using 2000mAh Lipo’s in this case.

I will have some time a bit later today and will try to duplicated this matter.

Please keep me posted!!
Regards,
Friedl.

1 Like