Looking for RFID sensore help

Ok, so I tested a few things and built a small wheel in my shop to verify the concepts. I went with a hall sensor because lots of ambient light was interfering with the IR sensor. The Hall works fine and on it's own with a simple tach code and I can get RPM on the serial port. That all works.

I also have the card reader working fine and it will read the cards as they should. Unfortunately they continue to read as the wheel spins. I was hoping my IF statement would keep the reader from reading until the wheel has stopped. The tach works and card reader works, I just cannot get them to work together. I just need to know when the wheel stops and take a reading.

#include <Keyboard.h>
#include <Wire.h>
#include <Adafruit_PN532.h>
#include <BlockNot.h>



// If using the breakout or shield with I2C, define just the pins connected
// to the IRQ and reset lines.  Use the values below (2, 3) for the shield!
#define PN532_IRQ   (6)
#define PN532_RESET (3)  // Not connected by default on the NFC Shield

// Uncomment just _one_ line below depending on how your breakout or shield
// is connected to the Arduino:


// Or use this line for a breakout or shield with an I2C connection:
Adafruit_PN532 nfc(PN532_IRQ, PN532_RESET);

BlockNot cardTimer0(5, SECONDS);
BlockNot cardTimer1(5, SECONDS); 
BlockNot cardTimer2(5, SECONDS);
BlockNot cardTimer3(5, SECONDS);
BlockNot cardTimer4(5, SECONDS);

float revolutions=0;
int rpm=0; // max value 32,767 16 bit
long  startTime=0;
long  elapsedTime;
int ledPin =12;


void setup(void) {

  Serial.begin(115200);
  while (!Serial) delay(10); // for Leonardo/Micro/Zero

  Serial.println("Hello!");

  nfc.begin();
   
  uint32_t versiondata = nfc.getFirmwareVersion();
  if (! versiondata) {
    Serial.print("Didn't find PN53x board");
    while (1); // halt
  }
  // Got ok data, print it out!
  Serial.print("Found chip PN5"); Serial.println((versiondata>>24) & 0xFF, HEX); 
  Serial.print("Firmware ver. "); Serial.print((versiondata>>16) & 0xFF, DEC); 
  Serial.print('.'); Serial.println((versiondata>>8) & 0xFF, DEC);
  
  // configure board to read RFID tags
  nfc.SAMConfig();
  
  Serial.println("Waiting for an ISO14443A Card ...");
}


void loop(void) {

revolutions=0; rpm=0;
startTime=millis();         
attachInterrupt(digitalPinToInterrupt(7),interruptFunction,RISING);
delay(1000);
detachInterrupt(7);                

//How many counts we've had from the hall effect sensor and calc the RPM
elapsedTime=millis()-startTime;     //finds the time, should be very close to 1 sec

if(revolutions>0)
{
  rpm=(max(1, revolutions) * 60000) / elapsedTime;        //calculates rpm
}
///lcd.setCursor(0,0);
String outMsg = String("RPM :") + rpm;
//fillMessage2DisplayWidth(outMsg);
//lcd.print(outMsg);
Serial.println(outMsg);

if ((rpm) > 0)
Serial.print ("Wheel Spinning"); 

else if ((rpm) == 0)
  Keyboard.begin();
 
  uint8_t success;
  uint8_t uid[] = { 0, 0, 0, 0, 0, 0, 0 };  // Buffer to store the returned UID
  uint8_t uidLength;                        // Length of the UID (4 or 7 bytes depending on ISO14443A card type)
    
  // Wait for an ISO14443A type cards (Mifare, etc.).  When one is found
  // 'uid' will be populated with the UID, and uidLength will indicate
  // if the uid is 4 bytes (Mifare Classic) or 7 bytes (Mifare Ultralight)
  success = nfc.readPassiveTargetID(PN532_MIFARE_ISO14443A, uid, &uidLength);
  
  if (success) {
    
    // Display some basic information about the card
    Serial.println("Found an ISO14443A card");
    Serial.print("  UID Length: ");Serial.print(uidLength, DEC);Serial.println(" bytes");
    Serial.print("  UID Value: ");
    nfc.PrintHex(uid, uidLength);
  }   
    if (uidLength == 4)
    {
      // We probably have a Mifare Classic card ... 
      uint32_t cardid = uid[0];
      cardid <<= 8;
      cardid |= uid[1];
      cardid <<= 8;
      cardid |= uid[2];  
      cardid <<= 8;
      cardid |= uid[3]; 
      Serial.print("Seems to be a Mifare Classic card #");
      Serial.println(cardid);
      
         
     if ((cardid == 1839898475 || 641164975 )&& cardTimer0.TRIGGERED){
      Keyboard.write('A');
 
     } 
     if ((cardid == 3335073343 || 3813925170)&& cardTimer1.TRIGGERED){
      Keyboard.write('B');
       
     }  
    if ((cardid == 2260681791 || 2796534086)&& cardTimer2.TRIGGERED){
      Keyboard.write('C'); 
       
    }  
    if ((cardid == 3329626431 || 1716831046)&& cardTimer3.TRIGGERED){  
      Keyboard.write('D');
       
    }   
    if ((cardid == 1186344511 || 3813206066)&& cardTimer4.TRIGGERED){
      Keyboard.write('E');
       
    }          
    Keyboard.end();      
     Serial.println("");
  }
}
void interruptFunction() //interrupt service routine
{  
  revolutions++;
}

To begin, the attach interrupt should be done only one time, and in the setup().
There is never a need to detach interrupts, unless you are going to assign a different function to be executed on an interrupt and you don't have that rare case.
There is no reason to make revolutions a float.
Think about checking for revolutions being tested about once per second. Disable interrupts, test revolutions for zero, set a flag if zero, zero revolutions and then enable interrupts again.
Paul

Well, yes I see your point about revolutions being a float. It would never be that big and I don't care about a decimal. I copied this code and modified it a bit, but left the interrupts as is because the sketch worked.

You are over my head with

Think about checking for revolutions being tested about once per second. Disable interrupts, test revolutions for zero, set a flag if zero, zero revolutions and then enable interrupts again.

Oh, use millis() to find when 1000 milliseconds had gone by in your loop() and then check the revs.
There are many examples. Likely to be one or two in the IDE examples. Fun!
Paul

ok, I have seen some tutorials on millis(), but they are mainly on blinking LED's or controlling brightness of an LED. I haven't seen anything that pertains to how i can control this reader.

I do see where a variable is called
success = nfc.readPassiveTargetID(PN532_MIFARE_ISO1443A, uid, &uidLength);
there is an IF statement that follows it and this seems to be where the data from the cards are read. How to stop the variable 'success'? This seems to start the reader, but i will obtain the data sheet and see if this can be done with a command.

I think you do not do anything about the card reading or anything like that until you know your 1 second or whatever has gone by with no rotation of the wheel. Only then are you sure the wheel has stopped moving. Then try to read the card.
Hope we are both dealing with the same logic!
Paul

Yes, that is exactly what needs to happen, but currently no matter what i have tried i cannot seem to get the code to stop reading the cards.

You can put in a "return;" instruction where you want loop() to not continue and start over at the top.

Let me see if I follow you correctly. The main loop is where the card reader is searching for cards and we only want that to happen when the wheel has stopped turning. Basically, the code should ignore the card ID's until the wheel has stopped.
If I create a loop ('while' function?) that just does nothing while the wheel is spinning. If it stops exits the wheelspin-loop and continues to the main void loop.

I have read about using 'goto' to get out of a 'while' loop, but it seems to be frowned upon in the C++ world.

Where you determine the wheel is still spinning, just "retun;" to exit the loop. No need to complicate things.

Well, I have gone down the RFID rabbit hole with a lot of work and not much to show for it. I switched gears today and used a QR code reader that has a USB interface that act like a keyboard when inserted into a laptop. This works great because I can print out QR codes that correspond to the keyboard commands that trigger my videos. All works great with the simple 'tachometer' code (below) and when the wheel has stopped turning I use a relay to set the trigger on the QR reader. this activates the read function on the device for 1/2 second. this works quite well and I tested it out today.

Now the PM's want me to play a different video loop when the wheel is spinning!!! So, I thought of using the other side of the SPDT relay to trigger an input pin on the Leonardo and use the Keyboard.print command to trigger my 'Wheel Spinning' video. I thought of using buttonState to check the state of the button and trigger the Keyboard command.

my problem is I get the Keyboard to print 'L' at startup, but it will not trigger again in the loop. My relay is going from High to low when engaged. High when wheel is stopped and Low when the wheel is turning.

What am I doing wrong?

#include <Keyboard.h>

int revolutions=0;
int rpm=0; // max value 32,767 16 bit
long  startTime=0;
long  elapsedTime;
int ledPin =12;                           //wheel turning indicator
int relayPin =11;                         //QR code reader trigger
const int relayPin_1 = 9;                //Keyboard trigger when wheel isn't turning                    
int previousButtonState = HIGH;          //to check state of relay_1
void setup() {
{
    pinMode(7, INPUT_PULLUP);           // set pin to input
    pinMode (ledPin,OUTPUT);            //LED is an output
    pinMode (relayPin, OUTPUT);         //Relay pin is output
    pinMode (relayPin_1, INPUT);        //Relay pin 1 in an input to trigger media player loop activated by buttonState
    Serial.begin(9600);
    Keyboard.begin();
}
}
 
void loop() {

int buttonState = digitalRead(relayPin_1); 
revolutions=0; rpm=0;
startTime=millis();         
attachInterrupt(digitalPinToInterrupt(7),interruptFunction,RISING);
delay(1000);
detachInterrupt(7);                

//How many counts we've had from the hall effect sensor and calc the RPM
elapsedTime=millis()-startTime;     //finds the time, should be very close to 1 sec

if(revolutions>0)
{
  rpm=(max(1, revolutions) * 60000) / elapsedTime;        //calculates rpm
}

String outMsg = String("RPM :") + rpm;
Serial.println(outMsg);


if ((rpm) == 0) 
 digitalWrite (ledPin, HIGH);
if ((rpm) == 0) 
 digitalWrite (relayPin, HIGH);
if ((rpm) > 0) 
 digitalWrite (ledPin, LOW); 
if ((rpm) > 0) 
 digitalWrite (relayPin, LOW);
 
if ((buttonState != previousButtonState)
     && (buttonState == LOW))
Keyboard.print ('L');

previousButtonState = buttonState;  

Keyboard.end();

}  

void interruptFunction() //interrupt service routine
{  
  revolutions++;
}

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.