My Cart

How to Control a Servo with an RFID Tag Using Smart Cards Kit (RFID 125KHz)

Difficulty Level: Expert -

1. Introduction

This tutorial allows the user to move the servo (open and close a barrier) if the key of the RFID card is correct.

Ingredients:

    - 1 x Smart Cards Kit (RFID 125KHz):
    • 1x Platform
    • 1x RFID 125KHz
    • 1x GPRS antenna
    • 1x Servo
    • 1x LCD
    • 1x Potentiometer
    • 1x Breadboard
    • 1x External power supply
    • 1x Programming cable
    • Jumper Wires

Preparation Time: 30 minutes

Buy now
NOTE: Depending on the platform chosen to develop the project, the ingredients and the schematics shown in this tutorial can vary.

This project can be developed with Arduino or Intel Galileo. It is also compatible with Raspberry Pi using the Raspberry Pi to Arduino shields connection bridge.

For further information about the RFID 125kHz Shield, consult the main tutorial.

Step 1: Connection

Connect the RFID module with its antenna to the Xbee Shield and then, connect the shield to the Arduino. Connect the servo, the potentiometer and the LCD in the breadboard as you can see in the next diagram.

Connect two wires, red and black, to the two long rows on the side of the breadboard to provide access to the 5 volt supply and ground. A potentiometer will adjust LCD contrast. Connect left terminal of the potentiometer to 5 volt and the right terminal to GND. Connect the central leg of the potentiometer to the third pin of the LCD display. Follow the wire color diagram to connect all LCD pins. Finally connect Black/Brown wire of the servo to GND, Red wire to 5 volt and the remaining wire, Yellow/Orange, to pin 9 of Arduino.

WARNING: In Raspberry Pi, GPIO voltage levels are 3.3 V and are not 5 V tolerant. There is no over-voltage protection on the board. Digital inputs use a 3V3 logic level and are not tolerant of 5V levels, such as you might find on a 5V powered Arduino. Extreme caution when working with GPIO, you may damage your Raspberry Pi, your equipment and potentially yourself and others. Doing so is at your own risk!

Step 2: The Code

Arduino:

Code:
/*  
 *  RFID 125kHz Module
 *  
 *  Copyright (C) Libelium Comunicaciones Distribuidas S.L. 
 *  http://www.libelium.com 
 *  
 *  This program is free software: you can redistribute it and/or modify 
 *  it under the terms of the GNU General Public License as published by 
 *  the Free Software Foundation, either version 3 of the License, or 
 *  (at your option) any later version. 
 *  
 *  This program is distributed in the hope that it will be useful, 
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of 
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
 *  GNU General Public License for more details.
 *  
 *  You should have received a copy of the GNU General Public License 
 *  along with this program.  If not, see http://www.gnu.org/licenses/. 
 *  
 *  Version:           1.0
 *  Design:            David GascĂłn 
 *  Implementation:    Luis Miguel MartĂ­
 */
 			
#include <LiquidCrystal.h>
#include <Servo.h>

#define CLOSED_DOOR 90
#define OPEN_DOOR 180

LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
    

//Integer to hold commands received from serial monitor
byte userIdentifier[4];
byte auxID[4];
byte card = -1;

// initialize the library with the numbers of the interface pins
Servo garage_door;

void setup() {
  // put your setup code here, to run once:
  
  lcd.begin(16, 2);
  lcd.print("SM125 125khz");
  lcd.setCursor(0, 2);
  lcd.print("RFID Start");
  delay(2000);
  Serial.begin(19200);
  setParam();
  delay(200);
  Serial.flush();
    garage_door.attach(9);
  garage_door.write(CLOSED_DOOR);
  //***************************************************
  //***************************************************
  //before using this example remeber to write userIdentifier within the card
  //intialize users
  //user 1
  userIdentifier[0] = 0x15;
  userIdentifier[1] = 0x75;
  userIdentifier[2] = 0x57;
  userIdentifier[3] = 0x51;
  
  lcd.clear();
  lcd.print("Wave your card");
  setAutoMode();//keeps shield reading to detect whenever a card waves close to the antenna
}

void loop() {
 
 garage_door.detach();
  while (Serial.available()) {
   
    if (getUID()){
      
      
      lcd.clear();
      lcd.print("Correct card...");
      delay(500);
      lcd.clear();
      lcd.print("Opening...");
      garage_door.attach(9);
      //writes the angle corresponding to open the door
      garage_door.write(OPEN_DOOR);
      delay(500);
      lcd.clear();
      lcd.print("Open...");
      delay(2000);
      lcd.clear();
      lcd.print("Closing...");
      garage_door.write(CLOSED_DOOR);
      delay(500);
      }
      lcd.clear();
  lcd.print("Wave your card");
  }
}

// ***This cards do not have UID, we will save different data in their block2
// so we can identify them***
boolean getUID(){
  
   if (Serial.read() == 0x01) { //fixed header value
      lcd.clear();
      delay(10);
      byte len = Serial.read();//message lenght
      delay(10);
      for (byte j = 0; j < 5; j++) {
        Serial.read();//first 2 blocks will be our "UIDCard"
        delay(10);
      }
      for (byte j = 0; j < 4; j++) {
        auxID [j] = Serial.read();//first 2 blocks will be our "UIDCard"
      }
      //discard other data
      delay(500);
      while(Serial.available()>0){
        Serial.read();
      } 
      boolean are_equals = false;
        for (byte j = 0; j<4; j++){
        
          if (auxID[j]==userIdentifier[j]){
            are_equals = true;
          }   
 
      }
      return are_equals;

    }
  return false;
}


byte setParam () {
  //Calculate checksum of all bytes except header
  byte msglength = 0x06;
  byte checksum = 0x01 + msglength + 0x40 + 0x32 + 0x64 + 0x5A + 0x1E + 0x60;
  
  //Build and execute command
  byte paramcommand[10] = {0xFF, 0x01, msglength, 0x40, 0x32, 0x64, 0x5A, 0x1E, 0x60, checksum};
        
        // send the request bytes
        for (byte i=0; i<10; i++) {
          Serial.write(paramcommand[i]);
        }
  //flush buffer *critical*
  while (Serial.available() > 0) {
    Serial.read();
  }
   //give some time to module to do its stuff     
        delay(500);
        
	//verify successful completion of command
  if (Serial.read() == 0xFF) {
    if (Serial.read() == 0x01) {
      if (Serial.read() == 0x01) {
        if (Serial.read() == 0x99) {
          if (Serial.read() == 0x9B) {
            return 0;
          }
          else return 1;
        }
        else return 1;
      }
      else return 1;
    }
    else return 1;
  }
  else return 1;
}

 byte setAutoMode () {
	//Calculate checksum of all bytes except header
	byte msglength = 0x09;
	byte checksum = 0x01 + msglength + 0x87 + 0x01 + 0x01 + 0x03;

        //Build and execute command
	byte cmdToExecute[13] = {0xFF, 0x01, msglength, 0x87, 0x01, 0x01, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, checksum};
        
        // send the request bytes
        for (int m=0; m<13; m++) {
			Serial.write(cmdToExecute[m]);
        }
        //flush buffer *critical*
  while (Serial.available() > 0) {
    Serial.read();
  }
        delay(500);
        
	//verify successful completion of command
	  if (Serial.read() == 0xFF) {
    if (Serial.read() == 0x01) {
      if (Serial.read() == 0x01) {
        if (Serial.read() == 0x99) {
          if (Serial.read() == 0x9B) {
            return 0;
          }
          else return 1;
        }
        else return 1;
      }
      else return 1;
    }
    else return 1;
  }
  else return 1;
}
        

Raspberry Pi:

Code:
/*  
 *  RFID 125kHz Module
 *  
 *  Copyright (C) Libelium Comunicaciones Distribuidas S.L. 
 *  http://www.libelium.com 
 *  
 *  This program is free software: you can redistribute it and/or modify 
 *  it under the terms of the GNU General Public License as published by 
 *  the Free Software Foundation, either version 3 of the License, or 
 *  (at your option) any later version. 
 *  
 *  This program is distributed in the hope that it will be useful, 
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of 
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
 *  GNU General Public License for more details.
 *  
 *  You should have received a copy of the GNU General Public License 
 *  along with this program.  If not, see http://www.gnu.org/licenses/. 
 *  
 *  Version:           1.0
 *  Design:            David GascĂłn 
 *  Implementation:    Jorge Casanova, Luis MartĂ­n
 */
 
#include "arduPi.h"

//#define CLOSED_DOOR 90
//#define OPEN_DOOR 180

int SERVO = 9;
int servoState = LOW; 
unsigned long previousMillis = 0; 

//Integer to hold commands received from serial monitor
byte userIdentifier[4];
byte auxID[4];
byte card = -1;

// initialize the library with the numbers of the interface pins


boolean getUID();
byte setParam ();
byte setAutoMode ();

const long CLOSED_DOOR = 0.9;
const long OPEN_DOOR = 2.1;

void setup() {
  // put your setup code here, to run once:
  pinMode(SERVO, OUTPUT);
  printf("SM125 125khz\n");
  printf("RFID Start\n");
  delay(2000);
  Serial.begin(19200);
  setParam();
  delay(200);
  Serial.flush();
   int tiempo = millis();
  while (millis()-tiempo < 1000) {
	  
  unsigned long currentMillis = millis();
  
  if(currentMillis - previousMillis >= CLOSED_DOOR) {
    previousMillis = currentMillis;   

    if (servoState == LOW)
      servoState = HIGH;
    else
      servoState = LOW;
    digitalWrite(SERVO, servoState);
  }
}
  //***************************************************
  //***************************************************
  //before using this example remeber to write userIdentifier within the card
  //intialize users
  //user 1
  userIdentifier[0] = 0x15;
  userIdentifier[1] = 0x75;
  userIdentifier[2] = 0x57;
  userIdentifier[3] = 0x51;
  
  printf("Wave your card\n");
  setAutoMode();//keeps shield reading to detect whenever a card waves close to the antenna
}

void loop() {
 
 unsigned long currentMillis = millis();
  while (Serial.available()) {
   
    if (getUID()){
      
      
      printf("Correct card...\n");
      delay(500);
      printf("Opening...\n");
      int tiempo1 = millis(); 
  while (millis()-tiempo1 < 1000) {
	  
  unsigned long currentMillis = millis();
  
  if(currentMillis - previousMillis >= OPEN_DOOR) {
    previousMillis = currentMillis;   

    if (servoState == LOW)
      servoState = HIGH;
    else
      servoState = LOW;
    digitalWrite(SERVO, servoState);
  }
}
      delay(500);
      printf("Open...\n");
      delay(2000);
      printf("Closing...\n");
       int tiempo2 = millis();
   while (millis()-tiempo2 < 1000) {
	  
  unsigned long currentMillis = millis();
  
  if(currentMillis - previousMillis >= CLOSED_DOOR) {
    previousMillis = currentMillis;   

    if (servoState == LOW)
      servoState = HIGH;
    else
      servoState = LOW;
    digitalWrite(SERVO, servoState);
  }
}
      delay(500);
      }
  printf("Wave your card\n");
  }
}

// ***This cards do not have UID, we will save different data in their block2
// so we can identify them***
boolean getUID(){
  
   if (Serial.read() == 0x01) { //fixed header value
      delay(10);
      byte len = Serial.read();//message lenght
      delay(10);
      for (byte j = 0; j < 5; j++) {
        Serial.read();//first 2 blocks will be our "UIDCard"
        delay(10);
      }
      for (byte j = 0; j < 4; j++) {
        auxID [j] = Serial.read();//first 2 blocks will be our "UIDCard"
      }
      //discard other data
      delay(500);
      while(Serial.available()>0){
        Serial.read();
      } 
      boolean are_equals = false;
        for (byte j = 0; j<4; j++){
        
          if (auxID[j]==userIdentifier[j]){
            are_equals = true;
          }   
 
      }
      return are_equals;

    }
  return false;
}


byte setParam () {
  //Calculate checksum of all bytes except header
  byte msglength = 0x06;
  byte checksum = 0x01 + msglength + 0x40 + 0x32 + 0x64 + 0x5A + 0x1E + 0x60;
  
  //Build and execute command
  byte paramcommand[10] = {0xFF, 0x01, msglength, 0x40, 0x32, 0x64, 0x5A, 0x1E, 0x60, checksum};
        
        // send the request bytes
        for (byte i=0; i<10; i++) {
          Serial.write(paramcommand[i]);
        }
  //flush buffer *critical*
  while (Serial.available() > 0) {
    Serial.read();
  }
   //give some time to module to do its stuff     
        delay(500);
        
	//verify successful completion of command
  if (Serial.read() == 0xFF) {
    if (Serial.read() == 0x01) {
      if (Serial.read() == 0x01) {
        if (Serial.read() == 0x99) {
          if (Serial.read() == 0x9B) {
            return 0;
          }
          else return 1;
        }
        else return 1;
      }
      else return 1;
    }
    else return 1;
  }
  else return 1;
}

 byte setAutoMode () {
	//Calculate checksum of all bytes except header
	byte msglength = 0x09;
	byte checksum = 0x01 + msglength + 0x87 + 0x01 + 0x01 + 0x03;

        //Build and execute command
	byte cmdToExecute[13] = {0xFF, 0x01, msglength, 0x87, 0x01, 0x01, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, checksum};
        
        // send the request bytes
        for (int m=0; m<13; m++) {
			Serial.write(cmdToExecute[m]);
        }
        //flush buffer *critical*
  while (Serial.available() > 0) {
    Serial.read();
  }
        delay(500);
        
	//verify successful completion of command
	  if (Serial.read() == 0xFF) {
    if (Serial.read() == 0x01) {
      if (Serial.read() == 0x01) {
        if (Serial.read() == 0x99) {
          if (Serial.read() == 0x9B) {
            return 0;
          }
          else return 1;
        }
        else return 1;
      }
      else return 1;
    }
    else return 1;
  }
  else return 1;
}

int main (){
	setup();
	while(1){
		loop();
	}
	return (0);
}

        

Intel Galileo:

Code:
/*  
 *  RFID 125kHz Module
 *  
 *  Copyright (C) Libelium Comunicaciones Distribuidas S.L. 
 *  http://www.libelium.com 
 *  
 *  This program is free software: you can redistribute it and/or modify 
 *  it under the terms of the GNU General Public License as published by 
 *  the Free Software Foundation, either version 3 of the License, or 
 *  (at your option) any later version. 
 *  
 *  This program is distributed in the hope that it will be useful, 
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of 
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the 
 *  GNU General Public License for more details.
 *  
 *  You should have received a copy of the GNU General Public License 
 *  along with this program.  If not, see http://www.gnu.org/licenses/. 
 *  
 *  Version:           1.0
 *  Design:            David GascĂłn 
 *  Implementation:    Jorge Casanova, Luis MartĂ­n
 */
 			
#include <LiquidCrystal.h>
#include <Servo.h>

#define CLOSED_DOOR 90
#define OPEN_DOOR 180

LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
    

//Integer to hold commands received from serial monitor
byte userIdentifier[4];
byte auxID[4];
byte card = -1;

// initialize the library with the numbers of the interface pins
Servo garage_door;

void setup() {
  // put your setup code here, to run once:
  
  lcd.begin(16, 2);
  lcd.print("SM125 125khz");
  lcd.setCursor(0, 2);
  lcd.print("RFID Start");
  delay(2000);
  Serial.begin(19200);
  Serial1.begin(19200);
  setParam();
  delay(200);
  Serial1.flush();
    garage_door.attach(9);
  garage_door.write(CLOSED_DOOR);
  //***************************************************
  //***************************************************
  //before using this example remeber to write userIdentifier within the card
  //intialize users
  //user 1
  userIdentifier[0] = 0x15;
  userIdentifier[1] = 0x75;
  userIdentifier[2] = 0x57;
  userIdentifier[3] = 0x51;
  
  lcd.clear();
  lcd.print("Wave your card");
  setAutoMode();//keeps shield reading to detect whenever a card waves close to the antenna
}

void loop() {
 
 //garage_door.detach();
  while (Serial1.available()) {
   
    if (getUID()){
      
      
      lcd.clear();
      lcd.print("Correct card...");
      delay(500);
      lcd.clear();
      lcd.print("Opening...");
      //garage_door.attach(9);
      //writes the angle corresponding to open the door
      garage_door.write(OPEN_DOOR);
      delay(500);
      lcd.clear();
      lcd.print("Open...");
      delay(2000);
      lcd.clear();
      lcd.print("Closing...");
      garage_door.write(CLOSED_DOOR);
      delay(500);
      }
      lcd.clear();
  lcd.print("Wave your card");
  }
}

// ***This cards do not have UID, we will save different data in their block2
// so we can identify them***
boolean getUID(){
  
   if (Serial1.read() == 0x01) { //fixed header value
      lcd.clear();
      delay(10);
      byte len = Serial1.read();//message lenght
      delay(10);
      for (byte j = 0; j < 5; j++) {
        Serial1.read();//first 2 blocks will be our "UIDCard"
        delay(10);
      }
      for (byte j = 0; j < 4; j++) {
        auxID [j] = Serial1.read();//first 2 blocks will be our "UIDCard"
      }
      //discard other data
      delay(500);
      while(Serial1.available()>0){
        Serial1.read();
      } 
      boolean are_equals = false;
        for (byte j = 0; j<4; j++){
        
          if (auxID[j]==userIdentifier[j]){
            are_equals = true;
          }   
 
      }
      return are_equals;

    }
  return false;
}


byte setParam () {
  //Calculate checksum of all bytes except header
  byte msglength = 0x06;
  byte checksum = 0x01 + msglength + 0x40 + 0x32 + 0x64 + 0x5A + 0x1E + 0x60;
  
  //Build and execute command
  byte paramcommand[10] = {0xFF, 0x01, msglength, 0x40, 0x32, 0x64, 0x5A, 0x1E, 0x60, checksum};
        
        // send the request bytes
        for (byte i=0; i<10; i++) {
          Serial1.write(paramcommand[i]);
        }
  //flush buffer *critical*
  while (Serial1.available() > 0) {
    Serial1.read();
  }
   //give some time to module to do its stuff     
        delay(500);
        
	//verify successful completion of command
  if (Serial1.read() == 0xFF) {
    if (Serial1.read() == 0x01) {
      if (Serial1.read() == 0x01) {
        if (Serial1.read() == 0x99) {
          if (Serial1.read() == 0x9B) {
            return 0;
          }
          else return 1;
        }
        else return 1;
      }
      else return 1;
    }
    else return 1;
  }
  else return 1;
}

 byte setAutoMode () {
	//Calculate checksum of all bytes except header
	byte msglength = 0x09;
	byte checksum = 0x01 + msglength + 0x87 + 0x01 + 0x01 + 0x03;

        //Build and execute command
	byte cmdToExecute[13] = {0xFF, 0x01, msglength, 0x87, 0x01, 0x01, 0x03, 0x00, 0x00, 0x00, 0x00, 0x00, checksum};
        
        // send the request bytes
        for (int m=0; m<13; m++) {
			Serial1.write(cmdToExecute[m]);
        }
        //flush buffer *critical*
  while (Serial1.available() > 0) {
    Serial1.read();
  }
        delay(500);
        
	//verify successful completion of command
	  if (Serial1.read() == 0xFF) {
    if (Serial1.read() == 0x01) {
      if (Serial1.read() == 0x01) {
        if (Serial1.read() == 0x99) {
          if (Serial1.read() == 0x9B) {
            return 0;
          }
          else return 1;
        }
        else return 1;
      }
      else return 1;
    }
    else return 1;
  }
  else return 1;
}
		

Links and Documentation

Related Tutorials

Datasheets and Manuals



If you are interested in Internet of Things (IoT) or M2M projects check our open source sensor platform Waspmote which counts with more than 100 sensors available to use 'off the shelf', a complete API with hundreds of ready to use codes and a low consumption mode of just 0.7µA to ensure years of battery life.

Know more at:

Get the Starter Kits at: