RFID Based Toll Collection System

Published by MKDas on

In this article we are going to make a complete project with RFID. Many students made this project and submitted to their institute as their final year project. You can make this project for your final year project too. It will be a complete project for you.

Disclaimer: Electricity is always dangerous. Skill required to work with electricity. Do work with your own risk. Author will not be responsible for any misuse or harmful act. This website contents is also copyright protected. Anything copied and directly posted in your website and claiming it as yours is prohibited and nonsensical. Author published all the articles as opensource to help you making your project and learning purpose only. Learn and make one for yourself. If need any help feel free to ask the author. Author will be helpful to you. Thanks.

About this project:

In this project, we are going to make a toll collection system. A toll collection system can be found near any bridge or similar locations in the street where each vehicle have to pay to cross that part of the road. In most of the countries, this toll is manually collected and a printed slip is provided by a toll man.

Here in this project we are going to make something automated for this purpose. As an educational project, we are going to make a basic system where each vehicle will have a preregistered unique ID (using RFID card). When driver arrive in the toll plaza, driver punch the ID to a specific device where RFID reader is placed.

Then the system detects the vehicle ID and cut the fee from that card. If the card balance is low, driver have to recharge the card.

In this project, we are using a micro-controller (PIC16F877A), a RFID module (RDM6300), a servo motor (SG90), a 16×2 LCD, IR sensor and some associated components.

Block diagram:

The block diagram of our project is:

Block diagram

About Block Diagram:

In the block diagram we can see that our project have 3 inputs and 3 outputs. The IR sensors detects vehicle arrival and RFID scans the ID. Then the micro-controller drives servo motor to pass the vehicle. LCD display is used to show information and buzzer for alarming purpose. The button is used to recharge the card. And the power supply which is supplying 5V DC to MCU from AC220V line.

Circuit diagram:

Now, we will see the circuit diagram of our project:

Circuit diagram

Working principle:

Here in out project IR transmitter led and IR receiver diode is used to detect the vehicle arrival. D1 is IR transmitter which is transmitting a Infra Red beam to the receiver diode. The receiver diode is inversely connected with a pulled up resistor R5 which is driving a transistor Q2. When there is an IR beam detected by the receiver diode, the diode acts as a conductive path. The transistor Q2 then acts as cut-off mode. So we are getting 5V due to the pulled up resistor R6 which is feed to RA0 pin of PIC16F877A micro-controller.

When there is an vehicle in between these transmitter and receiver, no IR beam is detected thus 0V is found at RA0 pin due to Transistor Q2’s on mode. In this way, we can detect any vehicle has arrived before the toll-plaza if we make a sensing gate just before the toll plaza.

RDM6300

Now, the RFID module U2 (RDM6300) is connected via UART. The micro-controller has Tx & Rx pin for UART module and the RDM6300 also have Tx and Rx pin. The Tx pin of RDM6300 is connected with the Rx pin of MCU. When RFID module detects a card ID, it prints that ID at its Tx pin and the micro-controller reads that ID through its UART module.


LCD

16X2 LCD needs 6 pins to connect with micro-controller which is done from RA0 to RA5 pin of PIC16F877A. Information is printed time to time on this LCD screen.


Servo motor for gate

The servo motor (SG90) which is working as our gate operator is connected to RD7 pin of the micro-controller. A pulse is generated at this pin to drive the servo motor.


Buzzer circuit

The buzzer BUZ1 is rated 12V. That is why we need a transistor Q1 to drive the buzzer. Both of our transistor is BC547 general purpose transistor.

Button circuit

The recharge button which is pulled up by a resistor R3 is connected to RD3 pin of the MCU. This pin is set as input and active low mode triggers the button more.

Finally the power supply unit of our project is designed with a step-down transformer which is converting the AC220V line into 12V ac. Then a bridge diode and a filter capacitor C1 makes it unregulated DC12V. This 12V is supplied to a linear voltage regulator LM7805. This voltage regulator supplying 5V regulated voltage to micro-controller and LCD and servo motor. A filter capacitor C2 is required just after the voltage regulator output to make it more smooth.

Flow chart:

Here is the flow chart of this project:

Flow Chart

Coding:

I used mikroC pro for PIC v7.6 to do the programming. Here is the code for our project:

/*******************************************************************************
*                Program for, RFID Parking System for Ctg.                     *
*                   Written by_ Engr. Mithun K. Das                            *
*                       MCU: PIC16F877A; X-Tal:8MHz                            *
*                           Date:24-05-2016                                    *
*******************************************************************************/
// LCD module connections
sbit LCD_RS at RB5_bit;
sbit LCD_EN at RB4_bit;
sbit LCD_D4 at RB3_bit;
sbit LCD_D5 at RB2_bit;
sbit LCD_D6 at RB1_bit;
sbit LCD_D7 at RB0_bit;

sbit LCD_RS_Direction at TRISB5_bit;
sbit LCD_EN_Direction at TRISB4_bit;
sbit LCD_D4_Direction at TRISB3_bit;
sbit LCD_D5_Direction at TRISB2_bit;
sbit LCD_D6_Direction at TRISB1_bit;
sbit LCD_D7_Direction at TRISB0_bit;
// End LCD module connections

void Lcd_COut(char row, char col, const char *cptr)
{
  char chr = 0;             //first, it is used as empty string
  Lcd_Out(row, col, &chr);  //nothing to write but set position.
  for ( ; chr = *cptr ; ++cptr ) Lcd_Chr_CP(chr); //out in loop
}
char rfid[13];
char i;
short vehicle = 0,vehicle_mask = 1;
unsigned int balance1 = 100,balance2 = 100,balance3 = 100,balance4 = 100,balance5 = 100;

void Disp_Balance(short row, short coloum,unsigned int bal)
{
   char msg_bl[] = "000TK";
   msg_bl[0] = bal/100 + 48;
   msg_bl[1] = (bal/10)%10 + 48;
   msg_bl[2] = bal%10 + 48;
   Lcd_Out(row,coloum,msg_bl);
   Delay_ms(100);
}

#define     Buzzer      RD6_bit
#define     Recharge    RD3_bit
#define     LED         RD2_bit
#define     ON          1
#define     OFF         0

void beep()
{
  Buzzer =  ON;LED = ON;Delay_ms(50);Buzzer = OFF;LED = OFF;Delay_ms(50);//set a pulse
}

void InitTimer1()
{
    T1CON         = 0x31;
    TMR1IF_bit    = 0;
    TMR1H         = 0x0B;
    TMR1L         = 0xDB;
    TMR1IE_bit    = 1;
    INTCON        = 0xC0;
}

unsigned int clk=0,servo_clk=0,ddd=0;
void Interrupt() iv 0x0004 ics ICS_AUTO
{
    if (TMR1IF_bit)
    {
         TMR1IF_bit = 0;
         TMR1H         = 0x0B;
         TMR1L         = 0xDB;
         clk = servo_clk;
         RD7_bit = 0;
         for(ddd=0;ddd<clk;ddd++)
         {
             Delay_us(1);
             RD7_bit = 1;
         }
         RD7_bit = 0;
    }
}

void Delay2Sec()
{
   unsigned int d;
   for(d=0;d<2000;d++)
   {
      Delay_ms(1);
   }
}

bit a,b,c,d;
int number=0;
char space[]="00";

void main() 
{
 TRISA = 0xFF;//all input
 TRISD3_bit = 1;//set as input
 TRISD7_bit = 0;
 TRISD6_bit = 0;
 ADCON1 = 0x07;//all digital selection
 ADCON0 = 0x00;//ADC Off
 InitTimer1();
 servo_clk = 240;
 beep();
 Lcd_Init();               // Initialize LCD
 Lcd_Cmd(_LCD_CLEAR);      // Clear display
 Lcd_Cmd(_LCD_CURSOR_OFF); // Cursor off
 Lcd_COut(1,1,"RFID Parking"); // Write text in first row
 Lcd_COut(2,1,"System");
 Delay2Sec();
 UART1_Init(9600);         // Initialize UART, 9600 baud rate
 Delay2Sec();
 //rfid[12] = '\0';          // String Terminating Character
 Lcd_Cmd(_LCD_CLEAR);      // Clear display
 beep();beep();
 a=0;b=0;c=0;
 while(1)
 {
    
    out:
       if(vehicle)
       {
           vehicle = 0;
           beep();beep();
           Lcd_Cmd(_LCD_CLEAR);
           Lcd_COut(1,1,"Vehicle Arrived ");
           Delay2Sec();
           servo_clk = 240; //240 = close; 115 = open
           Lcd_Cmd(_LCD_CLEAR);
           top:
           Lcd_COut(1,1,"Reading RFID    ");
           vehicle_mask = 1;
           if(vehicle_mask)
           {
                 top1:
                 if(UART1_Data_Ready()) // If UART Data Ready
                 {
                     for(i=0;i<12;) // To Read 12 characters  of the card
                     {
                         if(UART1_Data_Ready())
                         {
                             rfid[i] = UART1_Read();
                             i++;
                         }
                     }
                     // Check For Errors
                     if((rfid[0] ^ rfid[2] ^ rfid[4] ^ rfid[6] ^ rfid[8] == rfid[10]) && (rfid[1] ^ rfid[3] ^ rfid[5] ^ rfid[7] ^ rfid[9] == rfid[11]))
                     {
                         beep();beep();
                         if(rfid[8]=='3' && rfid[9]=='6' && rfid[10]=='1' && rfid[11]=='A')//match 1
                         {
                             beep();//set a pulse
                             Lcd_COut(1,1,"CAT#1; T:15/-   ");
                             if(balance1>15)
                             {
                                if(a==0)balance1-=15;
                                Lcd_COut(2,1,"Bal. Avail:");
                                Disp_Balance(2,12,balance1);
                                Delay2Sec();
                                Lcd_Cmd(_LCD_CLEAR);
                                Lcd_COut(1,1,"Opening Gate");
                                Delay2Sec();
                                servo_clk = 115; //240 = close; 115 = open
                                Delay2Sec();Delay2Sec();
                                Lcd_Cmd(_LCD_CLEAR);
                                Lcd_COut(1,1,"Closing Gate");
                                Delay2Sec();
                                servo_clk = 240; //240 = close; 115 = open
                                beep();beep();
                                a=~a;
                             }
                             else
                             {
                                Lcd_COut(2,1,"Low Balance");
                                Delay2Sec();
                             }
                         }
                         else if(rfid[8]=='3' && rfid[9]=='8' && rfid[10]=='0' && rfid[11]=='F')//match 2
                         {
                             beep();//set a pulse
                             Lcd_COut(1,1,"CAT#2; T:25/-   ");
                             if(balance2>25)
                             {
                                if(b==0)balance2-=25;
                                Lcd_COut(2,1,"Bal. Avail:");
                                Disp_Balance(2,12,balance2);
                                Delay2Sec();
                                Lcd_Cmd(_LCD_CLEAR);
                                Lcd_COut(1,1,"Opening Gate");
                                Delay2Sec();
                                servo_clk = 115; //240 = close; 115 = open
                                Delay2Sec();Delay2Sec();
                                Lcd_Cmd(_LCD_CLEAR);
                                Lcd_COut(1,1,"Closing Gate");
                                Delay2Sec();
                                servo_clk = 240; //240 = close; 115 = open
                                beep();beep();
                                b=~b;
                             }
                             else
                             {
                                Lcd_COut(2,1,"Low Balance");
                                Delay2Sec();
                             }
                         }
                         else if(rfid[8]=='C' && rfid[9]=='D' && rfid[10]=='3' && rfid[11]=='2')//match 2
                         {
                             beep();//set a pulse
                             Lcd_COut(1,1,"CAT#3; T:35/-   ");
                             if(balance3>35)
                             {
                                if(c==0)balance3-=35;
                                Lcd_COut(2,1,"Bal. Avail:");
                                Disp_Balance(2,12,balance3);
                                Delay2Sec();
                                Lcd_Cmd(_LCD_CLEAR);
                                Lcd_COut(1,1,"Opening Gate");
                                Delay2Sec();
                                servo_clk = 115; //240 = close; 115 = open
                                Delay2Sec();Delay2Sec();
                                Lcd_Cmd(_LCD_CLEAR);
                                Lcd_COut(1,1,"Closing Gate");
                                Delay2Sec();
                                servo_clk = 240; //240 = close; 115 = open
                                beep();beep();
                                c=~c;
                             }
                             else
                             {
                                Lcd_COut(2,1,"Low Balance");
                                Delay2Sec();
                             }
                         }
                         else
                         {
                            beep();beep();beep();//set a pulse
                            Lcd_COut(1,1,"UNREGISTERED ID ");
                            Delay2Sec();
                            servo_clk = 240; //240 = close; 115 = open
                            goto top;
                         }
                         vehicle_mask = 0;
                         vehicle = 0;
                         goto out;
                     }
                     else
                     {
                         Lcd_COut(2,1,"Error           ");
                         Buzzer =  ON;Delay_ms(80);Buzzer = OFF;//set a pulse
                         goto top;
                     }
                 }
                 else
                 {
                    goto top1;
                 }
            }
       }
       else
       {
           Lcd_COut(1,1,"Waiting for  ");
           Lcd_COut(2,1,"Vehicle arrival ");
           number = 10-(a+b+c);
           space[0] = number/10 + 48;
           space[1] = number%10 + 48;
           Lcd_Out(1,15,space);
           if(RA0_bit==0)vehicle = 1;
           servo_clk = 240; //240 = close; 115 = open
           if(!Recharge)
           {
              beep();
              Lcd_Cmd(_LCD_CLEAR);      // Clear display
              Lcd_COut(1,1,"Recharge_");
              Delay2Sec();
              Lcd_Cmd(_LCD_CLEAR);      // Clear display
              Lcd_COut(1,1,"Reading RFID    ");
              Delay2Sec();
              beep();
              recharge:
              if(UART1_Data_Ready()) // If UART Data Ready
              {
                     for(i=0;i<12;) // To Read 12 characters  of the card
                     {
                         if(UART1_Data_Ready())
                         {
                             rfid[i] = UART1_Read();
                             i++;
                         }
                     }
                     // Check For Errors
                     if((rfid[0] ^ rfid[2] ^ rfid[4] ^ rfid[6] ^ rfid[8] == rfid[10]) && (rfid[1] ^ rfid[3] ^ rfid[5] ^ rfid[7] ^ rfid[9] == rfid[11]))
                     {
                         beep();beep();
                         Lcd_Cmd(_LCD_CLEAR);      // Clear display
                         Lcd_COut(1,1,"RFID:");
                         Lcd_Out(2,1,rfid);
                         //do balance cutting
                         Delay2Sec();
                         Lcd_Cmd(_LCD_CLEAR);      // Clear display
                         if(rfid[8]=='3' && rfid[9]=='6' && rfid[10]=='1' && rfid[11]=='A')//match 1
                         {
                              beep();//set a pulse
                              Lcd_COut(1,1,"Cat # 1");
                              Lcd_COut(2,1,"Recharge: 100/-");
                              Delay2Sec();
                              balance1+=100;
                              Lcd_Cmd(_LCD_CLEAR);
                              Lcd_COut(1,1,"Cat # 1");
                              Lcd_COut(2,1,"Bal. Avail:");
                              Disp_Balance(2,12,balance1);
                              Delay2Sec();
                              Lcd_Cmd(_LCD_CLEAR);
                              beep();beep();

                         }
                         else if(rfid[8]=='3' && rfid[9]=='8' && rfid[10]=='0' && rfid[11]=='F')//match 2
                         {
                              beep();//set a pulse
                              Lcd_COut(1,1,"Cat # 2");
                              Lcd_COut(2,1,"Recharge: 100/-");
                              Delay2Sec();
                              balance2+=100;
                              Lcd_Cmd(_LCD_CLEAR);
                              Lcd_COut(1,1,"Cat # 2");
                              Lcd_COut(2,1,"Bal. Avail:");
                              Disp_Balance(2,12,balance2);
                              Delay2Sec();
                              Lcd_Cmd(_LCD_CLEAR);
                              beep();beep();
                         }
                         else if(rfid[8]=='C' && rfid[9]=='D' && rfid[10]=='3' && rfid[11]=='2')//match 2
                         {
                              beep();//set a pulse
                              Lcd_COut(1,1,"Cat # 3");
                              Lcd_COut(2,1,"Recharge: 100/-");
                              Delay2Sec();
                              balance3+=100;
                              Lcd_Cmd(_LCD_CLEAR);
                              Lcd_COut(1,1,"Cat # 3");
                              Lcd_COut(2,1,"Bal. Avail:");
                              Disp_Balance(2,12,balance3);
                              Delay2Sec();
                              Lcd_Cmd(_LCD_CLEAR);
                              beep();beep();
                         }

                         else
                         {
                            beep();beep();beep();//set a pulse
                            Lcd_COut(1,1,"UNREGISTERED ID ");
                            Delay2Sec();
                            servo_clk = 240; //240 = close; 115 = open
                            Lcd_Cmd(_LCD_CLEAR);      // Clear display
                            Lcd_COut(1,1,"Try again_");
                            Delay2Sec();
                            Lcd_Cmd(_LCD_CLEAR);      // Clear display
                            Lcd_COut(1,1,"Reading RFID    ");
                            Delay2Sec();
                            beep();
                            goto recharge;
                         }
                         goto out;
                     }
                     else
                     {
                         Lcd_COut(2,1,"Error           ");
                         Buzzer =  ON;Delay_ms(80);Buzzer = OFF;//set a pulse
                         goto recharge;
                     }
              }
              else
              {
                 goto recharge;
              }
           }
       }

 }//while(1)
}//void main
//

Download mikroC file of this project.

Code explanation:

Among other general functions, here is an important function to control the servo motor.

void InitTimer1()
{
    T1CON         = 0x31;
    TMR1IF_bit    = 0;
    TMR1H         = 0x0B;
    TMR1L         = 0xDB;
    TMR1IE_bit    = 1;
    INTCON        = 0xC0;
}

unsigned int clk=0,servo_clk=0,ddd=0;
void Interrupt() iv 0x0004 ics ICS_AUTO
{
    if (TMR1IF_bit)
    {
         TMR1IF_bit = 0;
         TMR1H         = 0x0B;
         TMR1L         = 0xDB;
         clk = servo_clk;
         RD7_bit = 0;
         for(ddd=0;ddd<clk;ddd++)
         {
             Delay_us(1);
             RD7_bit = 1;
         }
         RD7_bit = 0;
    }
}

This timer interrupt function is generating a periodic pulse of 2-20ms to drive the servo motor. As we know that the servo motor are drived by a pulse of 2-20ms duration to set the direction. We can set that pulse duration with the variable ‘servo_clk’ here.

if(UART1_Data_Ready()) // If UART Data Ready
                 {
                     for(i=0;i<12;) // To Read 12 characters  of the card
                     {
                         if(UART1_Data_Ready())
                         {
                             rfid[i] = UART1_Read();
                             i++;
                         }
                     }
                     // Check For Errors
                     if((rfid[0] ^ rfid[2] ^ rfid[4] ^ rfid[6] ^ rfid[8] == rfid[10]) && (rfid[1] ^ rfid[3] ^ rfid[5] ^ rfid[7] ^ rfid[9] == rfid[11]))
                     {
// ..other codes.. //
                        }
//..other codes..//
}

In this block, RFID tag is being read by UART module of micro-controller. After reading ID, checked the id for error. If there is no error, next step can be done.

if(rfid[8]=='3' && rfid[9]=='6' && rfid[10]=='1' && rfid[11]=='A')//match 1
{
   beep();//set a pulse
   Lcd_COut(1,1,"CAT#1; T:15/-   ");
   if(balance1>15)
   {
      if(a==0)balance1-=15;
      Lcd_COut(2,1,"Bal. Avail:");
      Disp_Balance(2,12,balance1);
      Delay2Sec();
      Lcd_Cmd(_LCD_CLEAR);
      Lcd_COut(1,1,"Opening Gate");
      Delay2Sec();
      servo_clk = 115; //240 = close; 115 = open
      Delay2Sec();Delay2Sec();
      Lcd_Cmd(_LCD_CLEAR);
      Lcd_COut(1,1,"Closing Gate");
      Delay2Sec();
      servo_clk = 240; //240 = close; 115 = open
      beep();beep();
      a=~a;
   }
   else
   {
      Lcd_COut(2,1,"Low Balance");
      Delay2Sec();
   }
}

In this part, ID is compared with an ID. As we are not using any external memory card or database, so we are comparing direct ID to find the vehicle ID.

After finding ID, a amount is charged according to the vehicle class. For an example, 15/- is cut from this id.

Recharging is almost in similar ways, I hope you’ll understand that easily.

Result:

Here is the simulation result of our project:

Simulation 1
Simulation 2

PCB diagram:

Here is the PCB diagram of this project what I used for this project. You can make one for yourself too.

PCB diagram

Download PCB files from here.

We made this project in real life and tested result is:

Test 1
Test 2
Test 3

Conclusion:

In this article, we have learned how to make a RFID based toll collecting system. I hope you have learned it well and can make one for yourself. If you need any help, feel free to contact with me. Thank you.


MKDas

Mithun K. Das; B.Sc. in EEE from KUET. Blog: https://labprojectsbd.com

0 Comments

Leave a Reply

Your email address will not be published. Required fields are marked *