RFID Controlling 2 Servos

Hello Forum!

I would love some programming help. It is my first sketch...it is pretty simple, but, is still not performing the way I intended it t perform.

My objective is to create an RFID triggered door lock. Basically it will turn two servos 90 degrees (closing the door) and hold for 5 seconds, when a tag is detected by the RFID sensor. Then, it will pull the servos back to starting position (opening the door). The sensor should continually search for the tag and close the door each time the tag is detected.

I have attached the code. The unintended result is the serial monitor never prints the tag ID as requested in the "if" statement...it immediately (as soon as I plug the USB into the UNO) prints the "else" command over and over.

I am sure it is a programming error. I certainly would appreciate any guidance you can give. Thank you!

Servo Connections:
Red to + on breadboard
Black to - on breadboard
Orange to A1 on Uno

RFID 20LA Connections:
GND to - on breadboard
RES to + on breadboard
VCC to + on breadboard
D0 to Tx on Uno
D1 to Rx on Uno

Breadboard Connections

  • to 5v on Uno
  • to GND on Uno

_2Servos_With_RFID_notworking.ino (3.94 KB)

Your hardware setup does not match your code. You say that the RFID reader is hooked up to the Uno hardware serial pins. This code:

#define txPin 3                             // assign pin 3 on the uno to the tx pin
#define rxPin 2                             // assign pin 2 on the uno to the rx pin
#define RFID_READ 0x01                      // NOT SURE WHY THIS IS NEEDED, added based on antoher sketch thatI saw
SoftwareSerial ID20LA(rxPin, txPin);    // NOT SURE WHY THIS IS NEEDED, added based on antoher sketch thatI saw

says that the reader is using SoftwareSerial on pins 2 and 3 (rxPin, txPin). See the reference on Software Serial Library to answer why those lines of code are needed.

Thank you for your reply, Blue Eyes.

The RFID reader needs to be hooked up to tx>1 and rx>0 slots on the Uno which are pins 2 and 3 per the datasheet.

I thought the software serial pins in my code referred also to the rx and tx pins on the Uno "SoftwareSerial ID20LA(rxPin, txPin);" It is probably because this is my first sketch and project, but, I'm not clear from your post what my code should be.

I tried changing the #define pins to 1 and 0 instead of 2 and 3 with no luck. I also tried removing the define commands entirely. No luck. The serial monitor immediately reads "it hit else" over and over. Before I even connect the ID20LA to the breakout board.

I would love to hear any suggestions you may have on how to correct the code so that it matches my hardware setup.

Thank you for your time.

The RFID reader needs to be hooked up to tx>1 and rx>0 slots on the Uno which are pins 2 and 3 per the datasheet.

Possibly some confusion between pin numbers on the chip and pin numbers on teh Arduino board.

The IDE requires the Arduino pin numbers to be used. Connect the RFID reader to Arduino pins 2 and 3 and use those numbers when creating the instance of SoftwareSerial. Make sure that you get Tx and Rx connections the right way round. Tx on the Arduino to Rx on the reader and vice versa.

Thank you, UKHeliBob!

I rewired it, but, am still getting "it hit else" on the serial monitor before I even put the RFID back on the breakout board. Once it is on the board and I scan the tag, nothing happens.

Originally
RFID D0 to Uno tx
RFID D1 to Uno rx
code read: SoftwareSerial ID20LA(rx, tx);

Now
RFID D0 to Uno pin 3
RFID D1 to Uno pin 2
code reads: softwareSerial ID20LA(2,3)

RFID D0 to Uno pin 3
RFID D1 to Uno pin 2

Those are strange names for the serial connections on the RFID board. Can you please provide a link to the RFID device that you are using.

Have you got a common GND connection between the Arduino and the RFID board ?

I should have added "breakout"

RFID breakout D0 to Uno Pin 3 (this is pin 9 on the actual RFID)
RFID breakout D1 to Uno pin 2 (this is pin 8 on the actual RFID)

I am using the ID-20LA

Common ground - yes. I have the ground running from the breakout board to the negative on my breadboard. And the negative on the breadboard to gnd on arduino uno and negative on the breadboard to the black wire on the servo. (I have only one servo actually hooked up for testing).

The datasheet says

Pin9 is active when the output format is set to ASCII and it outputs complementary (inverted) ASCII
data output.

Which mode have you got selected - controlled by pin 7

I'm not sure how to tell which format.
I have pin 7 on the RFID / FORM on the breakout wired to ground on the breadboard which is connected to GND on the Uno

According to the datasheet, wiring pin 7 of the reader should give you ASCII output. Section 4 of the datasheet describes the format of the data output and it is not just simple ASCII.

Can you please post the latest version of your complete program here rather than as an attachment. Please use [­code][­/code] tags when you do so.

#include <Servo.h>                      // adds the servo library
#include <SoftwareSerial.h>         // allows two way communication with rx and tx pins

// all constants defined below. They are used here to set pin numbers:
Servo ServoLeft;                          // creates a servo object to control the servo on the viewer's left
Servo ServoRight;                        // creates a servo object to control the servo on the viewer's right
#define txPin 3                            // assign pin 3 on the uno to the tx pin
#define rxPin 2                            // assign pin 2 on the uno to the rx pin
#define RFID_READ 0x01             // NOT SURE WHY THIS IS NEEDED, added based on another sketch
SoftwareSerial ID20LA(2,3);         // allows 2way communication with rx and tx

// all variables defined below.
char ID;                                    // creates a variable to store the tag ID

void setup()
{
  Serial.begin(9600);                               // connects to the serial port with baud rate of 9600
  ID20LA.begin(9600);                            // NOT SURE WHY THIS IS NEEDED, different than serial.begin?
  Serial.print("RFID reader starting up");  // added this just to see if I am getting this far in the code
  ServoLeft.attach(A1);                           // turns a A1 into a servo driver to control the left servo
  ServoRight.attach(A2);                         // turns a A2 into a servo driver to control the right servo    
  ServoLeft.write(0);                               // puts servo in initial starting degree of 0
  ServoRight.write(0);                             // puts servo in initial starting degree of 0
  pinMode(txPin,OUTPUT);                       // defines the tx pin 3 as an output pin
  pinMode(rxPin,INPUT);                          // defines the rx pin 2 as an input pin
}
void supressAll()                           // NOT SURE WHY THIS IS NEEDED, added based on another sketch
{
  if(ID20LA.available() > 5)           
  {
    ID20LA.read();
    supressAll();          
  }
}

void loop () 
{
  if(ID20LA.available() > 0)        // if the serial receives more than 0 characters of an ID tag
  {
    ID = ID20LA.read();             // read and store all the characters in the variable 
    Serial.print(ID);                   // print the tag ID in serial monitor so I know it was read successfully
    ServoLeft.write(-45);            // turn left servo counterclockwise by 45 degrees (open left door)
    ServoRight.write(-45);          // turn viewer's right servo counterclockwise by 45 degrees (open right door)
    delay(5000);                       // wait 5 seconds for servos to reach their positions and have a short delay   
    ServoLeft.write(45);             // turn viewer's left servo clockwise by 45 degrees (close left side of door)
    ServoRight.write(45);           // turn viewer's right servo clockwise by 45 degrees (close right side of door)
   }
  else 
  {
    Serial.print("It hit else");            // added this so I know when the if statement was skipped
  }
}
void supressAll()                           // NOT SURE WHY THIS IS NEEDED, added based on another sketch
{
  if (ID20LA.available() > 5)
  {
    ID20LA.read();
    supressAll();
  }
}

[code]#define RFID_READ 0x01             // NOT SURE WHY THIS IS NEEDED, added based on another sketch

Not needed. Delete it

[/code]
Get rid of this function. You don't call it and even if you did the Arduino would crash because the function calls itself recursively with no exit.

#define txPin 3                            // assign pin 3 on the uno to the tx pin
#define rxPin 2                            // assign pin 2 on the uno to the rx pin

You give the pins names then don't use them here

SoftwareSerial ID20LA(2, 3);        // allows 2way communication with rx and tx

Using them makes things much clearer.

You do, however, use them here

 pinMode(txPin, OUTPUT);                      // defines the tx pin 3 as an output pin
  pinMode(rxPin, INPUT);                         // defines the rx pin 2 as an input pin

where they are not needed. Get rid of these 2 lines. SoftwareSerial will take care of the mode of the pins for you.

   ID = ID20LA.read();             // read and store all the characters in the variable

This line reads one character not the whole tag.

Try this program

#include <SoftwareSerial.h>         // allows two way communication with rx and tx pins

#define txPin 3                            // assign pin 3 on the uno to the tx pin
#define rxPin 2                            // assign pin 2 on the uno to the rx pin
SoftwareSerial ID20LA(rxPin, txPin);        // allows 2way communication with rx and tx
char ID;                                    // creates a variable to store the tag ID

void setup()
{
  Serial.begin(9600);                               // connects to the serial port with baud rate of 9600
  ID20LA.begin(9600);                               //starts the serial connection to the reader
  Serial.print("RFID reader starting up");  // added this just to see if I am getting this far in the code
}

void loop ()
{
  if (ID20LA.available())       // if a character is available from the reader
  {
    ID = ID20LA.read();             // read a single character from the reader
    Serial.println(ID);               // print the character in serial monitor
  }
}

Well, thanks to your help, I am closer than ever!
I added one servo command to your code, but am still not getting the right result.

The servo spins as soon as it is attached to A1. I need it to stay completely still until the tag is read. It jumps again once I put the RFID back on the breakout board. and then the serial monitor reads one character at a time with a 5 second delay between each character with no movement of the servo.

I think the issue is that the ID is being read one character at a time and I need it to wait until the entire ID is read and move the servo only once, after that entire character is received. I have to find a way to break the loop of it reading one character, going through the loop and starting over with the next character. But, I'm optimistic! You have gotten me very close!

Do you know of a command that will force the RFID to read the entire tag ID before moving on to the next line in the code?

Here is how the code looks now.

#include <SoftwareSerial.h>           // allows two way communication with rx and tx pins
#include <Servo.h>                       // includes library of commands for servo
Servo ServoLeft;                            // names the servo "ServoLeft"

#define txPin 3                             // assign pin 3 on the uno to pin D1 on the breakout or pin 8 on RFID
#define rxPin 2                             // assign pin 2 on the uno to pin D0 on the breakout or pin 9 on RFID
SoftwareSerial ID20LA(rxPin, txPin);  // allows 2way communication with rx and tx
char ID;                                          // creates a variable to store the tag ID

void setup()
{
  Serial.begin(9600);                 // connects to the serial port with baud rate of 9600
  ID20LA.begin(9600);               // starts the serial connection to the reader
  Serial.print("RFID starting");    // added this just to see if I am getting this far in the code
  ServoLeft.attach(A1);              // tells Uno to send commands to the servo via analog pin A1 
}

void loop ()
{
  if (ID20LA.available())             // once all characters are received when a tag is scanned by the RFID
  {
    ID = ID20LA.read();             // read and store all characters from the tag in a varaible called ID
    Serial.println(ID);                 // print all characters of the ID in the serial monitor
    ServoLeft.write(-45);            // turn the left servo counterclockwise 45 degrees
    delay(5000);                       // wait 5 seconds
    ServoLeft.write(45);             // turn the left servo clockwise 45 degrees
  }
}

Do you know of a command that will force the RFID to read the entire tag ID before moving on to the next line in the code?

The point of my test program was to see what was being received from the reader, if anything. Which character is always at the end of the input when a tag is presented to the reader ? That can be used to determine that reading the tag is complete.