Story Printer - Multiple RFID Reader and a Thermal Printer

Hi,

I'm making a children's story printer for a project but I'm really struggling with the coding using multiple RFID readers and I was hoping someone here may be able to point me in the right direction of what I need to understand to make my project work.

The idea is to use 3 RFID readers (MFRC522) that when they are all populated with an RFID tag the user will be able to push a button that will print out 3 images (like a comic strip) in the order they are placed on the RFID readers. So essentially each RFID tag will be assigned a bitmap - I have previously got the printer going with these. When each RFID has a tag on it the user will be able to press a button that will initialise the print.

I think I have the wiring sorted and I understand how to create the bitmaps and how to tell the printer to print them. It's just the coding for the RFID readers I am struggling with.

How do I make the RFID readers operate alongside each other to print different combinations?
How do I initially assign each RFID a reference name and string to be filled with the RFID tag?

Hopefully this makes sense I just need a bit of a push int he right direction as I haven't found much on using multiple RFID readers.

Thanks

The problem seems to be your requirement to know there are cards on all three sensors all the time. That leaves NO time for the program to do anything else.

Paul

Paul_KD7HB:
The problem seems to be your requirement to know there are cards on all three sensors all the time. That leaves NO time for the program to do anything else.

Paul

Hi Paul,

Thanks for your response. I'm not sure I fully understand what you mean. As in the way I want to organise things won't work? I'm really quite new to this!

Thanks

I think I have the wiring sorted

Prove it. Post a schematic so we can check.

How do I make the RFID readers operate alongside each other to print different combinations?

It is down to the coding and the wiring, so post your code, or a shorter code that shows your attempt at this.

I would wait for the button press and then read the readers one at a time. It is perfectly possible to do this. I did it with a different reader on an Arduino or the same reader with a Raspberry Pi, if any of those might help you I can post the links.

Hi Mike,

I have attached a diagram of my circuit. All the RFID readers share the same reset but have separate inputs from the SS pins - I appreciate this looks a little messy in the diagram so I have tried to keep colours consistent to see where each is headed.

The part I’m really stuck on is just where to start with the program. Here’s where I am at so far but my issue is not really knowing where to start!

#include <Adafruit_Thermal.h>

#include <require_cpp11.h>
#include <MFRC522.h>
#include <deprecated.h>
#include <MFRC522Extended.h>

// Globals
// No. Readers
const byte numReaders = 3;
// each reader has it's own SDA or SS pin
const byte ssPins[] = {2, 3, 4};
const byte resetPin = 8;
// Initialise an array MFRC522 instances representing each reader
MFRC522 mfrc522 [numReaders];
// 

// Printer Pins
#include "SoftwareSerial.h"
#define TX_PIN 6 // Arduino transmit  YELLOW WIRE  labeled RX on printer
#define RX_PIN 5 // Arduino receive   GREEN WIRE   labeled TX on printer

SoftwareSerial mySerial(RX_PIN, TX_PIN); // Declare SoftwareSerial obj first
Adafruit_Thermal printer(&mySerial);     // Pass addr to printer constructor
// Then see setup() function regarding serial & printer begin() calls.


void setup()
{

    // NOTE: SOME PRINTERS NEED 9600 BAUD instead of 19200, check test page.
  mySerial.begin(19200);  // Initialize SoftwareSerial
  //Serial1.begin(19200); // Use this instead if using hardware serial
  printer.begin();        // Init printer (same regardless of serial type)

    MFRC522.PCD_Init();  // Init MFRC522 card
  
  // Prepare key - all keys are set to FFFFFFFFFFFFh at chip delivery from the factory.
  for (byte i = 0; i < 6; i++) {
    key.keyByte[i] = 0xFF;
  
  char rfidreadertag1[] = "";
  char rfidreadertag2[] = "";
  char rfidreadertag3[] = "";

}

void loop() {
  // put your main code here, to run repeatedly:

}

As you can see I haven’t started in the loop yet. I want to have it so that when the RFID reader is scanned it will hold that value and then match that with a bitmap inside an if function. When it registers all those RFID readers as populated allow the user to press print.

I’m quite embaressed posting this - but I’m sure it’ll be quite clear I need some help!

Thanks

Story Printer Schematic_bb.pdf (1.11 MB)

Georgewph:
Hi Paul,

Thanks for your response. I’m not sure I fully understand what you mean. As in the way I want to organise things won’t work? I’m really quite new to this!

Thanks

I mean if you require the cards to be on the sensors continuously, the only way to determine that is to read the card continuously.

Paul

I don’t think this will work

MFRC522 mfrc522 [numReaders];

When you create an instance of something you create a reference to one object. For three readers you need three instance of the class.
So you need that three times either through a loop or a simple:-

MFRC522 mfrc522 [0];
MFRC522 mfrc522 [1]; 
MFRC522 mfrc522 [2];

Edit:- sorry I miss-remembered what I did back in 2016.
You also need a separate reset for each reader to prevent the reader init command resetting the other already initialised readers. You also need three init commands one for each instance.

I would also add decoupling to the reader’s power supply. Also note that the closer together readers are the less sensitive they are. You should not have them any closer together than three or four inches. The recommended distance so that they have no effect on each other is about a meter.

Thanks Grumpy_Mike. As it's quite important that the readers are close-ish together (right now they are about an inch apart). Otherwise the toy would be huge! Do you think this will be an issue. When I design the housing I could make the material between them very thick would that help with interference?

Or do you think I should approach the project another way?

Thanks

Do you think this will be an issue.

Yes I do.

When I design the housing I could make the material between them very thick would that help with interference?

Not really, unless you could line it with Mu metal foil. Readers work on the near magnetic field of the transmitter.

An other issue is the fact that the readers are 3V3 devices and need feeding with 3V3 and the signals need level shifting to 3V3 to prevent them being damaged.

This is a video of what I was able to achieve:- Mixed Up Robots on Vimeo
You can download a copy of The MagPi 47 July 2016 for free at their website.

That's awesome! It's really similar to what I want to achieve but I just need mine to print via a thermal printer.

Grumpy_Mike:
An other issue is the fact that the readers are 3V3 devices and need feeding with 3V3 and the signals need level shifting to 3V3 to prevent them being damaged.

I'm not sure I understand this part. I just understood that as long as the voltage remained 3V3 or below they should be ok?

I just understood that as long as the voltage remained 3V3 or below they should be ok?

If you have a 3V3 Arduino and reader then this is fine.

However, if you are using a 5V Arduino, the signals into the reader are 5V. This is above the 3V3 volts powering the reader. If you supply signals into a chip greater than the supply voltage of that chip, you forward bias the static protection diode and dump the excess into the power rail of the chip. This can cause damage and eventually lead to the chips failure.

Also the 3V3 signal from the reader when fed into the 5V input of an Arduino, is not sufficient to guarantee it registers as a logic one, it might work but it is out of spec.

So in short you need level translations from 5V to 3V3 for signals going from the Arduino to the reader, and 3V3 to 5V level converter for signals going from the reader to the Arduino.

Grumpy_Mike:
So in short you need level translations from 5V to 3V3 for signals going from the Arduino to the reader, and 3V3 to 5V level converter for signals going from the reader to the Arduino.

How does one go about making that conversion? As in what component is required? My issue is I'm not sure the wiring is even correct at the moment based on previous comments.

Also you mentioned having separate resets for each reader. I based my schematic and RFID wiring on this video - it's also where I got the code to recognise the 3 readers (sketch of circuit at at 3 minutes and code at 7.48). In this one all the readers use the same reset pin they just have separate SS pins.

Grumpy_Mike Would you by any chance have some time to help advise me on the wiring and structuring the code?

As a side note would this setup be better running each for 100ms at a time?

Well when I wanted to use multiple readers I built this:- RFID Sequencer
But the technology I used required about a quarter second start up time for reader and card combination.

Grumpy_Mike Would you by any chance have some time to help advise me on the wiring and structuring the code?

Sure that is what we are here for.

Grumpy_Mike:
Sure that is what we are here for.

Thanks, Grumpy_Mike. You've been a great help!

Grumpy_Mike:
Sure that is what we are here for.

Grumpy_Mike would you mind taking a look over my code:

#include <SPI.h>
#include <MFRC522.h>

#include "Adafruit_Thermal.h"
#include "T1.h"
#include "T2.h"
#include "SoftwareSerial.h"


#define RST_PIN   9     // Configurable, see typical pin layout above
#define RFID1_SS_PIN 2    // Configurable, see typical pin layout above
#define RFID2_SS_PIN 3
#define RFID3_SS_PIN 4

#define NR_OF_READERS   3

byte ssPins[] = {RFID1_SS_PIN, RFID2_SS_PIN, RFID3_SS_PIN};

MFRC522 mfrc522[NR_OF_READERS];   // Create MFRC522 instance.

#define TX_PIN 6 // Arduino transmit  YELLOW WIRE  labeled RX on printer
#define RX_PIN 5 // Arduino receive   GREEN WIRE   labeled TX on printer


SoftwareSerial mySerial(RX_PIN, TX_PIN); // Declare SoftwareSerial obj first
Adafruit_Thermal printer(&mySerial);     // Pass addr to printer constructor
// Then see setup() function regarding serial & printer begin() calls.


String readerTags[NR_OF_READERS];

void setup() {
  // This line is for compatibility with the Adafruit IotP project pack,
  // which uses pin 7 as a spare grounding point.  You only need this if
  // wired up the same way (w/3-pin header into pins 5/6/7):
  // pinMode(7, OUTPUT); digitalWrite(7, LOW);

  // NOTE: SOME PRINTERS NEED 9600 BAUD instead of 19200, check test page.
  mySerial.begin(19200);  // Initialize SoftwareSerial
  //Serial1.begin(19200); // Use this instead if using hardware serial
  printer.begin();        // Init printer (same regardless of serial type)

  SPI.begin();         // Init SPI bus

   for (uint8_t reader = 0; reader < NR_OF_READERS; reader++) {
    mfrc522[reader].PCD_Init(ssPins[reader], RST_PIN); // Init each MFRC522 card
    Serial.print(F("Reader "));
    Serial.print(reader);
    Serial.print(F(": "));
    mfrc522[reader].PCD_DumpVersionToSerial();
  }

  printer.println("Place the tokens in the slots, when each is filled press print!");
  
}


void loop() {

  for (uint8_t reader = 0; reader < NR_OF_READERS; reader++) {
    // Look for new cards
    

    if (mfrc522[reader].PICC_IsNewCardPresent() && mfrc522[reader].PICC_ReadCardSerial()){
     readerTags[reader] = "";
     for (byte i = 0; i < mfrc522[reader].uid.size; i++) {
            readerTags[reader] += String(mfrc522[reader].uid.uidByte[i], HEX);
      }
      Serial.print(reader);
      Serial.print(": ");
      Serial.print(readerTags[reader]);
      Serial.println(); 
      // Halt PICC
      mfrc522[reader].PICC_HaltA();
      // Stop encryption on PCD
      mfrc522[reader].PCD_StopCrypto1();
      
    }
    
  }

//if button pushed - Haven't put this in yet!
  
  if(readerTags[0] == "1990BA2B" && readerTags[1] == "4BBB7B0D" && readerTags[2] == "2B4F6F0D"){
    printer.printBitmap(T1_width, T1_height, T1_data);
  }
    else if (readerTags[0] == "ABDADE0D" && readerTags[1] == "FBF7B70D" && readerTags[2] == "BBF4700D"){
    printer.printBitmap(T2_width, T2_height, T2_data);
  }

    
    
  
}

Everything compiles ok but when I upload it the printer prints the line “Place the tokens in the slots, when each is filled press print!” the RFID readers don’t seem to run at all although they are all on. I have them currently just over 3 inches apart. They all share the same pins but have separate SS pins. They also all work individually as I have tried them with the example code in the MFRC522 library. Anything that stands out to you that I might’ve missed!

Thanks in advance!

Why have you got code for software serial, you never actually use it?

You are using the String libiary, this is not recommended on an Arduino due to its small amount of memory, it can lead to problems, if you want to use string you should use the string libiary instead, note the lower case initial letter.

Next you have:-

if( readerTags[0] == "1990BA2B".......

You can not compare Strings like that. Look up how to compare Strings.

Like many beginners you are trying to do everything in one function. You should break things down into individual functions for better clarity.

If you code is printing nothing in the loop function then it is your stonking big:-

if (mfrc522[reader].PICC_IsNewCardPresent() && mfrc522[reader].PICC_ReadCardSerial()){

That is always returning false. Take these two things and assign them to variables and then use variables in the if statement. That way you can print out these two variables before entering the "if" and see which one is returning false. Then you can investigate why it is. Unfortunately the example code for this libiary has a very poor programming style, and is not easy to follow.

I don't think this works like you might hope:-

MFRC522 mfrc522[NR_OF_READERS];   // Create MFRC522 instance.

You might want to look at this:-

Just because the libiary chucks out strings there is no need to keep the tokens as strings. I always convert these strings into actual numbers, of the "unsigned long int" type for 32 bit token codes or the "unsigned long long int" type for 64 or shorter codes.

Note how that video posted above uses bidirectional buffers to protect the RFID reader from the 5V Arduino signals. There is an awful lot of rubbish on the internet about connecting the reader direct to Arduino pins. The 522 chip is NOT 5V TOLERANT, because the data sheet dosn’t mention it being. Yes it might work to begin with but it will fail far faster than it otherwise would.

While a bidirectional buffer designed for I2C will work it is a bit of overkill, you can do it with simple restive dividers. The 3V3 output on Dout Pin 4 of the reader, is not actually sufficient, according to the specifications, to be recognised as a logic HIGH, it often works and can be directly connected without danger of any harm.

RFID reader to Arduino.jpg

@Grumpy_Mike I'm not sure if I have misunderstood your diagram but hooking up my RFID readers like this gives an issue in the multireader example inside the MFRC522 library written by Miguel Balboa. It essentially says they aren't connected properly and can't be read.

I am having slightly more luck as I can get two to work without any resistors fairly reliably - but I know you mentioned the reader might not last as long, I actually have three working with the example today but not with my printing code. Is there anyway you can show me a little more detail on how you would connect 3 readers in this way? As when I do it, it doesn't work. As a side note I have also been using a separate power supply to run the RFID readers as running them from the Arduino seems to never work.

OK, when you come back and say you made changes then we need to see those changes you have made, to check if they are correct or not.
That goes for both the schematic and the software.