Utilizing RFID Chips for Motor Control

Hello all,

I am currently working on a project that utilizes a 4x4 membrane keypad, a Parallax RFID scanner, some RFID chips, a Cyton DC motor driver, and a DC motor. The goal of this project is to have it so that when a numerical key is pressed on the keypad, the motor will run until a specific chip has been scanned by the RFID where at that point the motor will turn off until another key is pressed. So for example, numerical key 1 is assigned a specific chip ID, and when that key is pressed the motor will run at a set speed until that chip has been scanned. Then the motor will turn off.

So far I have managed to program a portion of what is needed so far, but I am having difficulties trying to incorporate the interaction between the RFID portion and the cutoff for the motor.

#include <Keypad.h>

#include <SoftwareSerial.h>

//Parallax RFID Reader
#define RFIDEnablePin 2 //Pin that enables reading. Set as OUTPUT and LOW to read an RFID tag
#define RFIDSerialRate 2400 //Parallax RFID Reader Serial Port Speed

//Using SoftwareSerial Library to locate the serial pins off the default set
//This allows the Arduino to be updated via USB with no conflict
#define RxPin 5 //Pin to read data from Reader 
#define TxPin 4 //Pin to write data to the Reader NOTE: The reader doesn't get written to, don't connect this line.
SoftwareSerial RFIDReader(RxPin, TxPin);

String RFIDTAG = ""; //Holds the RFID Code read from a tag
String DisplayTAG = ""; //Holds the last displayed RFID Tag

int pwm = 3; // declares digital pin 3 as PWM output
int dir = 1;
int r1 = 9;
int r2 = 8;
int r3 = 7;
int c1 = 13;
int c2 = 12;
int c3 = 11;
int c4 = 10;
int colm1;
int colm2;
int colm3;
int colm4;

int tag1 [] = {0x00, 0x00, 0x95, 0x8C, 0x92};

void setup()
{
  // RFID reader SOUT pin connected to Serial RX pin at 2400bps
  RFIDReader.begin(RFIDSerialRate);

  // Set Enable pin as OUTPUT to connect it to the RFID /ENABLE pin
  pinMode(RFIDEnablePin, OUTPUT);

  // Activate the RFID reader
  // Setting the RFIDEnablePin HIGH will deactivate the reader
  // which could be usefull if you wanted to save battery life for
  // example.
  digitalWrite(RFIDEnablePin, LOW);

  Serial.begin(9600);           // set up Serial library at 9600 bps

  pinMode(r1, OUTPUT);
  pinMode(r2, OUTPUT);
  pinMode(r3, OUTPUT);
  pinMode(c1, INPUT);
  pinMode(c2, INPUT);
  pinMode(c3, INPUT);
  pinMode(c4, INPUT);
  pinMode(pwm, OUTPUT);
  pinMode(dir, OUTPUT);
  digitalWrite(c1, HIGH);
  digitalWrite(c2, HIGH);
  digitalWrite(c3, HIGH);
  digitalWrite(c4, HIGH);
  digitalWrite(pwm, LOW);
}
void loop()
{
  if (RFIDReader.available() > 0) // If data available from reader
  {
    ReadSerial(RFIDTAG);  //Read the tag number from the reader. Should return a 10 digit serial number
  }

  //This only displays a tag once, unless another tag is scanned
  if (DisplayTAG != RFIDTAG)
  {
    DisplayTAG = RFIDTAG;
    Serial.println(RFIDTAG);
  }

  digitalWrite(r1, LOW);
  digitalWrite(r2, HIGH);
  digitalWrite(r3, HIGH);
  colm1 = digitalRead(c1);
  colm2 = digitalRead(c2);
  colm3 = digitalRead(c3);
  colm4 = digitalRead(c4);
  if (colm1 == LOW)      //checks whether key "1" is pressed.
  { analogWrite(pwm, 42); // writes "42" (duty cycle 16%).
    delay(200);
  }
  else
  {
    if (colm2 == LOW)     //checks whether key "2" is pressed.
    { analogWrite(pwm, 84); // writes "84" (duty cycle 32%).
      delay(200);
    }
    else
    {
      if (colm3 == LOW)     //checks whether key "3" is pressed
      { analogWrite(pwm, 126); // writes "126" (duty cycle 48%).
        delay(200);
      }
      else
      {
        if (colm4 == LOW)     // checks whether key "A" is pressed.
        { digitalWrite(pwm, LOW); // makes pin 3 LOW (duty cycle 0%).Motor OFF.
          delay(200);
        }
      }
    }
  }

  digitalWrite(r1, HIGH);
  digitalWrite(r2, LOW);
  digitalWrite(r3, HIGH);
  colm1 = digitalRead(c1);
  colm2 = digitalRead(c2);
  colm3 = digitalRead(c3);
  colm4 = digitalRead(c4);
  if (colm1 == LOW)      // checks whether key "4" is pressed.
  { analogWrite(pwm, 168); //writes "168" (duty cycle 64%).
    delay(200);
  }
  else
  {
    if (colm2 == LOW)     // checks whether key "5" is pressed.
    { analogWrite(pwm, 202); // writes "202" (duty cycle 80%).
      delay(200);
    }
    else
    {
      if (colm3 == LOW)     // checks whether key "6" is pressed.
      { analogWrite(pwm, 244); // writes "244" (duty cycle 96%).
        delay(200);
      }
      else
      {
        if (colm4 == LOW)       // checks whether key "B" is pressed.
        { digitalWrite(pwm, HIGH); //makes pin 3 HIGH (duty cycle 100%). FULL POWER
          delay(200);
        }

      }
    }
  }

  digitalWrite(r1, HIGH);
  digitalWrite(r2, HIGH);
  digitalWrite(r3, LOW);
  colm1 = digitalRead(c1);
  colm2 = digitalRead(c2);
  colm3 = digitalRead(c3);
  colm4 = digitalRead(c4);
  if (colm1 == LOW)      // checks whether key "7" is pressed.
  { analogWrite(pwm, 168); //writes "168" (duty cycle 64%).
    delay(200);
  }
  else
  {
    if (colm2 == LOW)     // checks whether key "8" is pressed.
    { analogWrite(pwm, 202); // writes "202" (duty cycle 80%).
      delay(200);
    }
    else
    {
      if (colm3 == LOW)     // checks whether key "9" is pressed.
      { analogWrite(pwm, 244); // writes "244" (duty cycle 96%).
        delay(200);
      }
      else
      {
        if (colm4 == LOW)       // checks whether key "C" is pressed.
        { digitalWrite(pwm, HIGH); //makes pin 3 HIGH (duty cycle 100%). FULL POWER
          delay(200);
        }
      }
    }
  }
}

void ReadSerial(String &ReadTagString)
{
  int bytesread = 0;
  int  val = 0;
  char code[10];
  String TagCode = "";

  if (RFIDReader.available() > 0) {         // If data available from reader
    if ((val = RFIDReader.read()) == 10) {  // Check for header
      bytesread = 0;
      while (bytesread < 10) {              // Read 10 digit code
        if ( RFIDReader.available() > 0) {
          val = RFIDReader.read();
          if ((val == 10) || (val == 13)) { // If header or stop bytes before the 10 digit reading
            break;                         // Stop reading
          }
          code[bytesread] = val;           // Add the digit
          bytesread++;                     // Ready to read next digit
        }
      }
      if (bytesread == 10) {               // If 10 digit read is complete

        for (int x = 0; x < 10; x++)       //Copy the Chars to a String
        {
          TagCode += code[x];
        }
        ReadTagString = TagCode;          //Update the caller
        while (RFIDReader.available() > 0) //Burn off any characters still in the buffer
        {
          RFIDReader.read();
        }

      }
      bytesread = 0;
      TagCode = "";
    }
  }
}

I was thinking of trying to code the RFID portion into the if loops of each of key. Say that if chip X has been scanned then digitalWrite(pwm, LOW). Is this a right way of going about it? Any help will be appreciated. Thank you!

 if (colm1 == LOW)      //checks whether key "1" is pressed.
  { analogWrite(pwm, 42); // writes "42" (duty cycle 16%).
    delay(200); }

Why are you not using the Keypad library?

Why ARE you using delay()?

Where do you care what you read from the RFID reader?

You can't use pin 1 as the direction pin AND for talking to the PC (using Serial).

Is this a right way of going about it?

Yes, but your code for determining which key on the keypad should do JUST that. It should NOT turn any motor on. It should NOT read the RFID tag.

Ok, so I programmed it differently. The keypad works fine; it activates the motor when a valid key is pressed, but will not stop even if the correct chip has been scanned by the scanner.

#include <Keypad.h>
#include <SoftwareSerial.h>
#include <stdlib.h>

//Parallax RFID Reader
#define RFIDEnablePin 2 //Pin that enables reading. Set as OUTPUT and LOW to read an RFID tag
#define RFIDSerialRate 2400 //Parallax RFID Reader Serial Port Speed
#define SLEEP 200 //Default sleep duration for RF reader

//Using SoftwareSerial Library to locate the serial pins off the default set
//This allows the Arduino to be updated via USB with no conflict
#define RxPin 5 //Pin to read data from Reader 
#define TxPin 4 //Pin to write data to the Reader NOTE: The reader doesn't get written to, don't connect this line.
SoftwareSerial RFIDReader(RxPin, TxPin);

#define Num_Chips 7
#define ROWS  4 // Four rows
#define COLS  4 // Four columns
#define RFID_CODE 10 //size of RFID tag

int pwm = 3;

// Define the Keymap
char keys[ROWS][COLS] =
{
  {'1', '2', '3', 'A'},
  {'4', '5', '6', NO_KEY},
  {'7', NO_KEY, NO_KEY, NO_KEY},
  {NO_KEY, NO_KEY, NO_KEY, NO_KEY}
};

// Define Array of Strings for RFID tags
String chips[Num_Chips] = {"0000958C92", "0000934267", "0000955FD0", "0000928EB5", "0000934425", "000093242A", "000093815C"};

//Placeholder
String target = "";

//Variables used in RFID scanning
int bytesRead, val;

//Storage for RFID codes during scanning
char code[RFID_CODE];

// Connect keypad ROW0, ROW1, ROW2 and ROW3 to these Arduino pins.
byte rowPins[ROWS] = { 9, 8, 7, 6 };

// Connect keypad COL0, COL1 and COL2 to these Arduino pins.
byte colPins[COLS] = {13, 12, 11, 10 };

// Create the Keypad
Keypad kpd = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );

void setup()
{
  // RFID reader SOUT pin connected to Serial RX pin at 2400bps
  RFIDReader.begin(RFIDSerialRate);

  // Set Enable pin as OUTPUT to connect it to the RFID /ENABLE pin
  pinMode(RFIDEnablePin, OUTPUT);

  // Activate the RFID reader
  // Setting the RFIDEnablePin HIGH will deactivate the reader
  // which could be usefull if you wanted to save battery life for
  // example.
  digitalWrite(RFIDEnablePin, LOW);

  Serial.begin(9600);           // set up Serial library at 9600 bps

  digitalWrite(pwm, LOW);
}

void loop()
{
  char key = kpd.waitForKey();
  if (key != NO_KEY)
  {
    startMotor();
    target = chips[(key - '0') - 1]; //Get the ID string for the toolbox associated with the key pressed
    scanRFID();
  }
}


//Starts the motor forward at half speed
void startMotor()
{
  digitalWrite (pwm, HIGH);
  analogWrite(pwm, 255);
}

//Disables the motor
void stopMotor()
{
  digitalWrite (pwm, LOW);
}

//This method checks to see if the RFID reader has found the desired tag, if not it continues to run until it does
void scanRFID()
{
  if (Serial.available() > 0) // if data available from reader
  {
    if ((val = Serial.read()) == 10) // check for header
    {
      bytesRead = 0;
      while (bytesRead < 10) // read 10 digit code
      {
        if ( Serial.available() > 0) //Reads if data is available
        {
          val = Serial.read();
          if ((val == 10) || (val == 13))
          { // if header or stop bytes before the 10 digit reading
            break;                       // stop reading
          }
          code[bytesRead] = val;         // add the digit
          bytesRead++;                   // ready to read next digit
        }
      }
      if (bytesRead == RFID_CODE) // if 10 digit read is complete
      {
        Serial.print(code);
        Serial.print("The target code is ");
        Serial.print(target);
        if (strcmp(code, target.c_str()) == 0) //Tag read is equal to the desired tag
        {
          bytesRead = 0;
          stopMotor();
          return;
        }
      }
      bytesRead = 0;

      digitalWrite(RFIDEnablePin, HIGH);        // deactivate the RFID reader for a moment so it will not flood
      delay(SLEEP);                       // wait for a bit
      digitalWrite(RFIDEnablePin, LOW);     // Activate the RFID reader
      scanRFID();                           //Desired TAG not found, continuing scan
    }
  }
}

That code for reading the RFID data will never work. It assumes that serial data arrives instantly. That is NEVER the case.

If you plan to read n characters, you must wait for there to be n characters to read. If you plan to read data as it arrives, you must plan for there to be many calls to the function that reads the data.

Okay cool. I got the program to work now. Here’s the latest version of the program.

#include <Keypad.h>
#include <SoftwareSerial.h>

//Parallax RFID Reader
#define RFIDEnablePin 2 //Pin that enables reading. Set as OUTPUT and LOW to read an RFID tag
#define RFIDSerialRate 2400 //Parallax RFID Reader Serial Port Speed
#define SLEEP 200 //Default sleep duration for RF reader

//Using SoftwareSerial Library to locate the serial pins off the default set
//This allows the Arduino to be updated via USB with no conflict
#define RxPin 5 //Pin to read data from Reader 
#define TxPin 4 //Pin to write data to the Reader NOTE: The reader doesn't get written to, don't connect this line.
SoftwareSerial RFIDReader(RxPin, TxPin);

#define Num_Chips 7
#define ROWS  4 // Four rows
#define COLS  4 // Four columns
#define RFID_CODE 10 //size of RFID tag

int pwm = 3;
boolean scanning = false;

// Define the Keymap
char keys[ROWS][COLS] =
{
  {'1', '2', '3', 'A'},
  {'4', '5', '6', NO_KEY},
  {'7', NO_KEY, NO_KEY, NO_KEY},
  {NO_KEY, NO_KEY, NO_KEY, NO_KEY}
};

// Define Array of Strings for RFID tags
String chips[Num_Chips] = {"0000958C92", "0000934267", "0000955FD0", "0000928EB5", "0000934425", "000093242A", "000093815C"};

//Placeholder
String target = "";

//Variables used in RFID scanning
int bytesRead, val;

//Storage for RFID codes during scanning
char code[RFID_CODE];

// Connect keypad ROW0, ROW1, ROW2 and ROW3 to these Arduino pins.
byte rowPins[ROWS] = { 9, 8, 7, 6 };

// Connect keypad COL0, COL1 and COL2 to these Arduino pins.
byte colPins[COLS] = {13, 12, 11, 10 };

// Create the Keypad
Keypad kpd = Keypad( makeKeymap(keys), rowPins, colPins, ROWS, COLS );


//Starts the motor forward at half speed
void startMotor()
{
  digitalWrite (pwm, HIGH);
  for (int motorValue = 0 ; motorValue <= 200; motorValue += 5)
  {
    analogWrite(pwm, motorValue);
    delay(30);
  }
}

//Disables the motor
void stopMotor()
{
  for (int motorValue = 200 ; motorValue >= 0; motorValue -= 5)
  {
    analogWrite(pwm, motorValue);
    delay(30);
  }
  digitalWrite (pwm, LOW);
}

void ReadSerial(String &ReadTagString)
{
  int bytesread = 0;
  int  val = 0;
  char code[10];
  String TagCode = "";

  if (RFIDReader.available() > 0) {         // If data available from reader
    if ((val = RFIDReader.read()) == 10) {  // Check for header
      bytesread = 0;
      while (bytesread < 10) {              // Read 10 digit code
        if ( RFIDReader.available() > 0) {
          val = RFIDReader.read();
          if ((val == 10) || (val == 13)) { // If header or stop bytes before the 10 digit reading
            break;                         // Stop reading
          }
          code[bytesread] = val;           // Add the digit
          bytesread++;                     // Ready to read next digit
        }
      }
      if (bytesread == 10) {               // If 10 digit read is complete

        for (int x = 0; x < 10; x++)       //Copy the Chars to a String
        {
          TagCode += code[x];
        }
        ReadTagString = TagCode;          //Update the caller
        while (RFIDReader.available() > 0) //Burn off any characters still in the buffer
        {
          RFIDReader.read();
        }

      }
      bytesread = 0;
      TagCode = "";
    }
  }
}

//This method checks to see if the RFID reader has found the desired tag, if not it continues to run until it does
void scanRFID()
{
  String tag, lastTag;
  while (scanning)
  {
    if (RFIDReader.available() > 0)
    {
      ReadSerial(tag);

      if (tag != "")
      {
        if (tag != lastTag)
        {
          lastTag = tag;
          Serial.println(tag);
        }
      }
      if (tag == target)
      {
        stopMotor();
        scanning = false;
      }
    }
  }
}


void setup()
{
  // RFID reader SOUT pin connected to Serial RX pin at 2400bps
  RFIDReader.begin(RFIDSerialRate);

  // Set Enable pin as OUTPUT to connect it to the RFID /ENABLE pin
  pinMode(RFIDEnablePin, OUTPUT);

  // Activate the RFID reader
  // Setting the RFIDEnablePin HIGH will deactivate the reader
  // which could be usefull if you wanted to save battery life for
  // example.
  digitalWrite(RFIDEnablePin, LOW);

  Serial.begin(9600);           // set up Serial library at 9600 bps

  digitalWrite(pwm, LOW);
}

void loop()
{
  char key = kpd.waitForKey(); //Blocks IO until a key is pressed
  if (key != NO_KEY) //If the key is a valid key
  {
    scanning = true;
    startMotor();
    target = chips[(key - '0') - 1]; //Get the ID string for the toolbox associated with the key pressed
    scanRFID();
  }
}

Thanks for the help!

void stopMotor()
{
  for (int motorValue = 200 ; motorValue >= 0; motorValue -= 5)
  {
    analogWrite(pwm, motorValue);
    delay(30);
  }
  digitalWrite (pwm, LOW);
}

That function really needs to be called slowMotorToStopped().

Here's the latest version of the program.

The next step is to get rid of all the Strings. There is NOTHING that that code is doing that needs the binary tag data as a String. Or even as a string.

Thanks for the suggestions. How difficult would it be to make one of the buttons a killswitch that stops the motor running mid cycle?

How difficult would it be to make one of the buttons a killswitch that stops the motor running mid cycle?

Simple. The Arduino will have NOTHING to do with that switch. A kill switch should NOT require that a computer notice that it is pressed. It should kill power without the computer needing to do anything.

Really glad to have found this thread, I have a project that is very similar in early stages.

PaulS: The next step is to get rid of all the Strings. There is NOTHING that that code is doing that needs the binary tag data as a String. Or even as a string.

Why wouldn't you use Strings? What would you use instead?