开云体育

Locked RFID Connectivity #rfid


 

Michael,

Absolutely! The Mega has no issues keeping up with 12 readers connected. Also, unless a train is moving extremely fast, the readers can keep up with the passing tags. I do not think that the microcontroller is the issue you're having, but the high speeds of the tags passing over the readers. I find that quite interesting though since in testing I made sure to pass trains over the readers at speed and only very rarely was a tag "missed" by a reader. Of course, placement of tags should be thought out and distance between tags maximized. This usually translates to placing the tags as close to center on all rolling stock and engines. Granted, this isn't always feasible depending on how you are attaching tags and the tag type, but still.?

Steve,

You can always parse out the tag data in whatever way you choose from within the code on an Arduino or other microcontroller and pass it to JMR. The goal is to pass the tag data and reader identifier(s) to JMRI so that it recognizes things in such a way so as to automatically create the correct objects (Sensor, Reporter, ID Tag). I do suppose that you COULD write a script that would read the UID and then create/populate the aforementioned objects, but that seems excessive when you can just have the Arduino format the data for JMRI so that IT does the heavy lifting with the objects.

Tom


 

I feel like I should ask these questions off this site as to not bore everyone but here goes another question. I have two readers working one using a seeed lotus and the other using an arduino uno. I notice the lotus has 6 digital 4 pin connections. My original plan was to but a few more nanos and sensors. But I can cheaper buy a Ethernet connection and run them all off the lotus using your code. And uses the uno for something else………… as some one who has no clue what he is doing. Will this work??


 

Michael

Keep asking the questions, we're all learning here!


Tom

I only suggested a JMRI script in case the Arduino formatting wasn't suitable. It does make sense to let the Arduino do the work
So, the tags I use are the Mifare Ultralite types. They have a 7 byte UID. I have a sketch which reads the UID and sends it to the serial port. I can see this in PuTTy. All that is sent is the 7 byte UID, 14 characters. Now, question is, how do I modify the sketch so that the output is in a format JMRI will accept and create the correct objects?

The sketch I'm using is attached.

Look forward to your thoughts.

Steve


 

Michael,

Yes, using an Ethernet Shield can definitely work! I do not know much about the Lotus, but I shall look it up and educate myself. If it is simply another Arduino-type microcontroller and there are Ethernet Shields for it, then it shouldn't be a problem. Let me know!


Steven,

Thanks for the base sketch! So:

This is an Arduino sketch/program that demonstrates how to read data from a RFID tag or card using the MFRC522 RFID reader module on the Arduino SPI interface. The program uses the MFRC522 library, which can be found on GitHub.

The program initializes the SPI bus and the MFRC522 module in the setup function. It also initializes a MIFARE key that will be used to read/write data to/from the tag/card.

The loop function is where the program looks for new cards and reads the data from them. If a new card is detected, the program reads its serial number and stores it in an array. The program then prints the serial number in hexadecimal format to the serial monitor using the printHex function.

Finally, the program stops communication with the card and waits for another card to be presented. The program will continue to run in this loop until it is stopped manually.


So, the tags I use are the Mifare Ultralite types. They have a 7 byte UID. I have a sketch which reads the UID and sends it to the serial port. I can see this in PuTTy. All that is sent is the 7 byte UID, 14 characters. Now, question is, how do I modify the sketch so that the output is in a format JMRI will accept and create the correct objects?

To send RFID tag data to JMRI, you will need to use a specific format that the software can understand. JMRI expects RFID tag data to be sent in the format of a "RFID Sensor" message.
?
The message should contain the following information:
?
The sensor type, which should be "RFID"
The sensor address, which corresponds to the ID of the RFID reader that is sending the data
The state of the sensor, which should be either "ACTIVE" or "INACTIVE" depending on whether an RFID tag has been detected or not
The ID of the RFID tag that has been detected

Here's an example of what the message might look like:

RFID:RFIDReader1:ACTIVE:12345

In this example, "RFID" is the sensor type, "RFIDReader1" is the address of the RFID reader, "ACTIVE" indicates that an RFID tag has been detected, and "12345" is the ID of the detected RFID tag.


#include <SPI.h>
#include <MFRC522.h>
?
#define SS_PIN 10
#define RST_PIN 9
#define READER_ADDRESS 'A' // Address of the reader, can be any letter A-Z
?
MFRC522 rfid(SS_PIN, RST_PIN); // Instance of the class
?
MFRC522::MIFARE_Key key;?
?
// Init array that will store new NUID?
byte nuidPICC[4];
?
void setup() {?
? Serial.begin(9600);
? SPI.begin(); // Init SPI bus
? rfid.PCD_Init(); // Init MFRC522?
?
? for (byte i = 0; i < 6; i++) {
? ? key.keyByte[i] = 0xFF;
? }
?
?
}
?
void loop() {
?
? // Look for new cards
? if ( ! rfid.PICC_IsNewCardPresent())
? ? return;
?
? // Verify if the NUID has been read
? if ( ! rfid.PICC_ReadCardSerial())
? ? return;
?
? // Format data for JMRI
? String sensorType = "RFID";
? char sensorAddress = READER_ADDRESS;
? String sensorState = "ACTIVE";
? String tagID = "";
? for (byte i = 0; i < 4; i++) {
? ? tagID += String(rfid.uid.uidByte[i], HEX);
? }
?
? String message = sensorType + "," + sensorAddress + "," + sensorState + "," + tagID;
? Serial.println(message);
??
? rfid.PICC_HaltA();
? rfid.PCD_StopCrypto1();
}
?
In this modified code, we added a READER_ADDRESS constant that can be set to any letter A-Z, depending on how many readers are connected. We also changed the formatting of the message to match the "RFID Sensor" message format expected by JMRI. The sensorType is set to "RFID", the sensorAddress is set to the READER_ADDRESS constant, the sensorState is set to "ACTIVE" since a tag has been detected, and the tagID is built using a for-loop to concatenate each byte of the tag ID in HEX format. Finally, the entire message is constructed by concatenating the values of each field using commas as separators, and the message is sent to the serial port using Serial.println().

Granted, this very well may need some modifications or tweaks, but this is the general idea and principle. :-)


Tom


 

Tom

Many thanks for the sketch, I can see what we are trying to achieve and your help is much appreciated.

I uploaded the sketch and noticed a few oddities. In the Serial Monitor, the one tag readout was 'RFID,A,ACTIVE,47d64a'. Two other tags were 'RFID,A,ACTIVE,53184ead'. It was the same readout on PuTTy. What I noticed here was that the full tag UID was not read, but 3 bytes in the first case and 4 in the second. I sort of expected 7 bytes (14 characters).

I then tried it in JMRI and got nothing. The Rfid Command Window showed a series of hex pairs and msg unknown reply of length 16. Thinking about it, I'm not quite sure now of what connection I'm supposed to be using for this. In the Edit>Preferences>Connections I chose RFID, Direct Serial Connection. I then chose COM3 as the serial port, which it is and initially MERG Concentrator, A-H range, seeing as the reader id was 'A'. I set up a Reporter FRA and Sensor FSA, but didn't get anything. I did try the other connections, as in the various Generic Standalones, but still nothing. So, how should I be configuring the JMRI connection??

I feel we are very close to solving this and it just some little thing I might be missing.

Look forward to your thoughts.

Steve


 

Steve,

Try the following sketch. Without having that particular reader and tag type here, this is taking longer than it typically would. LOL! No worries though! We shall be victorious!?

#include <SPI.h>
#include <MFRC522.h>
?
#define SS_PIN 10
#define RST_PIN 9
?
MFRC522 rfid(SS_PIN, RST_PIN); // Instance of the class
?
MFRC522::MIFARE_Key key;
?
byte nuidPICC[7];
?
void setup() {
? Serial.begin(9600, SERIAL_8N1);
? SPI.begin(); // Init SPI bus
? rfid.PCD_Init(); // Init MFRC522
?
? for (byte i = 0; i < 6; i++) {
? ? key.keyByte[i] = 0xFF;
? }
}
?
void loop() {
? // Look for new cards
? if (!rfid.PICC_IsNewCardPresent())
? ? return;
?
? // Verify if the NUID has been read
? if (!rfid.PICC_ReadCardSerial())
? ? return;
?
? if (rfid.uid.size == 7) {
? ? // Mifare Ultralight detected
? ? for (byte i = 0; i < 7; i++) {
? ? ? nuidPICC[i] = rfid.uid.uidByte[i];
? ? }
? ? printHex(rfid.uid.uidByte, rfid.uid.size);
? ? Serial.println();
? ? rfid.PICC_HaltA();
? ? rfid.PCD_StopCrypto1();
?
? ? // Send RFID data to JMRI
? ? Serial.print("\r\n-C");
? ? for (byte i = 0; i < 7; i++) {
? ? ? if (i == 2) {
? ? ? ? Serial.print(':');
? ? ? }
? ? ? Serial.print(nuidPICC[i], HEX);
? ? }
? ? Serial.println("\r\n");
? }
}
?
void printHex(byte *buffer, byte bufferSize) {
? for (byte i = 0; i < bufferSize; i++) {
? ? Serial.print(buffer[i] < 0x10 ? "0" : "");
? ? Serial.print(buffer[i], HEX);
? }
}


 

Tom,

Thanks for the revised sketch. I'm afraid that didn't work either! I had some strange outputs on the Serial Monitor. The tag was read and displayed, but subsequent tags had a 'C' added and a colon after the first two bytes.?

I'm getting mighty confused here! Shouldn't be this difficult!

I've been trying to research a bit more. Are your 12 readers and Arduino using the Seeed connection in JMRI? I know you said you used the ethernet connection, is that into a network switch or directly into the back of the computer? Have you tried using the Serial output of your sketch?

Your first sketch gave an output of 'RFID, Reader ID, Sensor Active, tag id'. Do we need to have the 'RFID' element or indeed the 'Sensor'? if the Arduino is connected to the Seeed Rfid protocol? Surely the Seeed just sends a start of message, tag id then maybe a cr and lf? Is this how your 12 Reader sketch outputs the data??

I thought all we may have to do was use your original 12 reader sketch and replace the Seeed readers with RC522's, or is that a bit naive?

I'm also still not convinced that any of the JMRI Rfid connections can take a 7 byte UID. I think they were all written with 4 byte UID's in mind, perhaps someone could confirm this??

I'm away from home for a couple of days, so can't test anything at the moment.

Steve




 

Steve,

OK, so the issue on MY end is not having access to the same reader and tags so I can test as I go. The connection type you need to use, at least for now until we get this hashed out, is illustrated here:



First things first. Using your base sketch for the RC522 reader, create the connection as illustrated above. We need to get the RFID tags read and processed by JMRI. Once we can verify that JMRI can successfully process the tags (create Sensor, Reporter, ID Tag) then we can move on to multiple readers. Getting the 7-byte tags to work is the first order of business. With multiple readers connected to an Arduino, the hardware connection to JMRI, whether serial or network interface is a simple matter in the code. Also, the network interface connection type means that you would plug in the Arduino's ethernet cable to a switch, router, etc. on your network.

Tom


 

Steve,

My apologies... Use the following sketch to send the data back to JMRI over the serial connection you create above.?
?
#include <SPI.h>
#include <MFRC522.h>
?
#define SS_PIN 10
#define RST_PIN 9
?
MFRC522 rfid(SS_PIN, RST_PIN); // Instance of the class
?
MFRC522::MIFARE_Key key;?
?
// Init array that will store new NUID?
byte nuidPICC[4];
?
void setup() {?
? Serial.begin(9600, SERIAL_8N1);
? SPI.begin(); // Init SPI bus
? rfid.PCD_Init(); // Init MFRC522?
?
? for (byte i = 0; i < 6; i++) {
? ? key.keyByte[i] = 0xFF;
? }
?
?
}
?
void loop() {
? // Look for new cards
? if ( ! rfid.PICC_IsNewCardPresent())
? ? return;
?
? // Verify if the NUID has been read
? if ( ! rfid.PICC_ReadCardSerial())
? ? return;
?
? // Format the RFID data as a string
? String rfidString = "";
? for (byte i = 0; i < 4; i++) {
? ? rfidString += String(rfid.uid.uidByte[i], HEX);
? }
?
? // Send the RFID data as a string over the serial port
? Serial.println(rfidString);
?
? rfid.PICC_HaltA();
? rfid.PCD_StopCrypto1();
}


 

Steve,?

OK, last message about this! LOL! I am getting ahead of myself and making silly mistakes.

This is the sketch you should try. Ignore the last one. Create the RFID connection in JMRI first. This sketch is for the 7-byte tags.?this sketch sends the RFID data to JMRI over the serial connection in a format that JMRI can process. The line "Serial.println(rfidString);" sends the RFID data as a string over the serial port. As long as JMRI is listening on the same serial port and is configured to expect the same format of RFID data, it should be able to receive and process the data. The output string sent to JMRI for a typical 7-byte Mifare Ultralite RFID tag would be a 14-character hexadecimal string, with no prefix. Each byte of the tag's unique identifier (UID) would be represented by two hexadecimal characters in the output string, resulting in a total of 14 characters. We get this to work and the rest is fairly straightforward.?

This code uses the MFRC522 library to read RFID cards using an RC522 RFID reader. The code starts by defining the SS and RST pins for the RFID reader. It then creates an instance of the MFRC522 class with these pins.

In the setup function, the serial port is initialized and the SPI bus and MFRC522 reader are initialized. An array of bytes is also created to store the key used for authentication with the RFID card.

In the loop function, the code first checks if a new card is present by calling the PICC_IsNewCardPresent function. If no new card is present, the function returns and the code waits for a new card.

If a new card is present, the code calls the PICC_ReadCardSerial function to read the card's UID. The UID is then stored in an array of bytes.

The code then formats the UID data as a string and sends it over the serial port using the Serial.println function.

?

Finally, the code halts the card and stops the cryptographic communication with the card using the PICC_HaltA and PCD_StopCrypto1 functions.

?

#include <SPI.h>

#include <MFRC522.h>

?

#define SS_PIN 10

#define RST_PIN 9

?

MFRC522 rfid(SS_PIN, RST_PIN); // Instance of the class

?

MFRC522::MIFARE_Key key;?

?

// Init array that will store new NUID?

byte nuidPICC[7];

?

void setup() {?

? Serial.begin(9600, SERIAL_8N1);

? SPI.begin(); // Init SPI bus

? rfid.PCD_Init(); // Init MFRC522?

?

? for (byte i = 0; i < 6; i++) {

? ? key.keyByte[i] = 0xFF;

? }

}

void loop() {

? // Look for new cards

? if ( ! rfid.PICC_IsNewCardPresent())

? ? return;

?

? // Verify if the NUID has been read

? if ( ! rfid.PICC_ReadCardSerial())

? ? return;

?

? // Store the 7-byte UID in the nuidPICC array

? for (byte i = 0; i < 7; i++) {

? ? nuidPICC[i] = rfid.uid.uidByte[i];

? }

?

? // Format the RFID data as a string

? String rfidString = "";

? for (byte i = 0; i < 7; i++) {

? ? if (nuidPICC[i] < 0x10) {

? ? ? rfidString += "0";

? ? }

? ? rfidString += String(nuidPICC[i], HEX);

? }

?

? // Send the RFID data as a string over the serial port

? Serial.println(rfidString);

?

? rfid.PICC_HaltA();

? rfid.PCD_StopCrypto1();

}


 

I did also finally find the documentation on the MERG concentrator, which is excellent since now I know exactly how IT outputs data to JMRI. Since we are using an Arduino, we can format the outgoing RFID data any way we want. The information is found

Armed with this information, even though the MERG RFID readers and/or concentrator use 125KHz 4-byte tags, we should be able to still use the Mifare Ultra Lite 7-byte tags. I cannot find any specific information within the JMRI docs regarding limitations on tag sizes, but IF there is one (let's say 4-bytes), then we will need to rethink our approach. There doesn't seem to be anything that would prevent the use of 7-byte Mifare Ultra Lite RFID tags. The protocol appears to be generic enough to handle most Mifare tags.

?

That being the case, I wrote a sketch that should allow you to use the RC522 reader and Ultra Lite tags, but instead of the Olimex/MOD-RFID1356MIFARE connection type in JMRI, you can use the MERG Concentrator type since the sketch formats the tag data sent to JMRI in the same way the MERG concentrator does. This is the great thing about Arduino. You can make it emulate almost anything.

#include <SPI.h>

#include <MFRC522.h>

?

#define SS_PIN 10

#define RST_PIN 9

?

MFRC522 rfid(SS_PIN, RST_PIN); // Instance of the class

?

MFRC522::MIFARE_Key key;?

?

// Init array that will store new NUID?

byte nuidPICC[7];

?

void setup() {?

? Serial.begin(9600, SERIAL_8N1);

? SPI.begin(); // Init SPI bus

? rfid.PCD_Init(); // Init MFRC522?

?

? for (byte i = 0; i < 6; i++) {

? ? key.keyByte[i] = 0xFF;

? }

}

?

void loop() {

? // Look for new cards

? if ( ! rfid.PICC_IsNewCardPresent())

? ? return;

?

? // Verify if the NUID has been read

? if ( ! rfid.PICC_ReadCardSerial())

? ? return;

?

? // Store the 7-byte UID in the nuidPICC array

? for (byte i = 0; i < 7; i++) {

? ? nuidPICC[i] = rfid.uid.uidByte[i];

? }

?

? // Calculate the XOR checksum

? byte checksum = nuidPICC[0];

? for (byte i = 1; i < 7; i++) {

? ? checksum = checksum ^ nuidPICC[i];

? }

?

? // Output the tag data in the required format

? Serial.write(0x02); // STX

? Serial.write('A'); // Reader ID (change as necessary)

? for (byte i = 0; i < 7; i++) {

? ? byte b = nuidPICC[i];

? ? Serial.write((b >> 4) + (b > 9 ? 'A' - 10 : '0')); // Convert high nibble to hex character

? ? Serial.write((b & 0x0F) + ((b & 0x0F) > 9 ? 'A' - 10 : '0')); // Convert low nibble to hex character

? }

? Serial.write((checksum >> 4) + (checksum > 9 ? 'A' - 10 : '0')); // Convert high nibble of checksum to hex character

? Serial.write((checksum & 0x0F) + ((checksum & 0x0F) > 9 ? 'A' - 10 : '0')); // Convert low nibble of checksum to hex character

? Serial.write(0x0D); // CR

? Serial.write(0x0A); // LF

? Serial.write(0x3E); // ETX

?

? rfid.PICC_HaltA();

? rfid.PCD_StopCrypto1();

}


This sketch outputs the tag data in the required format, with the reader ID set to 'A'. If you have multiple readers, you'll need to modify the reader ID accordingly for each reader (and a few other things). We can have up to 8 readers connected to one Arduino when using the MERG concentrator connection type.



Tom


 

Tom,

You seem to have been very busy! However, your final sketch using the MERG Concentrator format seems to be the best bet. I'm away with work at the moment, but will give this a go as soon as I get back. Looking at it and the MERG link, I think it should work this time.

If it doesn't, then I'm thinking it will be the UID size. There are two ways around this. One would be to modify the JMRI source code to accept 7 bytes. The other and perhaps easier, would be to read the 4 bytes from elements 4 and 5 of the eeprom. This is where data, such as the loco's dcc address can be written to on the MERG CANRC522, and also what that module reads. So it would just be a case of telling the Arduino sketch to read a different part of the tag and we would have 4 byte data.

However, bear with me until I'm home and we'll see what happens.

Thanks again very much for your help.

Steve


 

Hi,

There is a chance that at very high train speeds in OO and O gauge that the UID from a NTAG213/215/216 tag may not be read due to the way the tags communicate with RFID modules.

The design of the experimental MERG CANRC522 does not seem to suffer from this problem up to 120 scale MPH in N, OO and O (it reads/writes 4 bytes from I think the first 4 bytes of user EEPROM on the tag).

RFID modules with long antennas may give better performance with trains at high speeds as the tag may be in the communication zone for longer. However there is a trade off as longer antennas could cause problems with interference from tags on other vehicles in the same train. There is a very large model railway using long antennas on their RFID modules but they run their wagons as groups of three with one tag on the middle wagon so the length of the antenna is less of a problem.

Longer tags may also help at higher train speeds but at the moment there are limited shapes and sizes of ready to buy 13.56Mhz RFID tags. Again interference with tags on train vehicles in front and behind may be a problem.

PS The 125khz tags used by the MERG 'first generation' RFID have a 5 byte UID.

Regards

Nick (helping in MERG with research and testing low cost, reliable future RFID solutions for model railways)


 

Nick,

Thanks for the info! Do you happen to have the documentation for the MERG CANRC522? I want to see how the RFID tag data is parsed and formatted? (the 4 bytes of the EEPROM) before sending it to JMRI.

Tom


 

Steve,

OK, so this sketch should work for you using an Arduino Mega (or Uno if you change the pin assignments) with UP TO 8 readers attached. If you connect less than 8, that should be fine too. This sketch absolutely outputs the tag data back to JMRI using the MERG Concentrator connection type. IF this doesn't work, then we can explore getting the 7-bytes down to 4, but like I said, I cannot find any mention of a 4-byte tag limitation in the JMRI docs.
?
?
// Import Libraries
#include <SPI.h>? // SPI library for communicating with the MFRC522 reader
#include <MFRC522.h>? // MFRC522 library for reading RFID cards
?
// Define the SS (Slave Select) and RST (Reset) pins for each reader
#define SS_PIN_1 10? // Slave Select pin for reader 1
#define RST_PIN_1 9? // Reset pin for reader 1
?
#define SS_PIN_2 8? // Slave Select pin for reader 2
#define RST_PIN_2 7? // Reset pin for reader 2
?
#define SS_PIN_3 6? // Slave Select pin for reader 3
#define RST_PIN_3 5? // Reset pin for reader 3
?
#define SS_PIN_4 4? // Slave Select pin for reader 4
#define RST_PIN_4 3? // Reset pin for reader 4
?
#define SS_PIN_5 2? // Slave Select pin for reader 5
#define RST_PIN_5 A0? // Reset pin for reader 5
?
#define SS_PIN_6 A1? // Slave Select pin for reader 6
#define RST_PIN_6 A2? // Reset pin for reader 6
?
#define SS_PIN_7 A3? // Slave Select pin for reader 7
#define RST_PIN_7 A4? // Reset pin for reader 7
?
#define SS_PIN_8 A5? // Slave Select pin for reader 8
#define RST_PIN_8 A6? // Reset pin for reader 8
?
// Create an array of MFRC522 objects (one for each reader)
MFRC522 rfid[8] = {
? MFRC522(SS_PIN_1, RST_PIN_1),? // Instance of the class for reader 1
? MFRC522(SS_PIN_2, RST_PIN_2),? // Instance of the class for reader 2
? MFRC522(SS_PIN_3, RST_PIN_3),? // Instance of the class for reader 3
? MFRC522(SS_PIN_4, RST_PIN_4),? // Instance of the class for reader 4
? MFRC522(SS_PIN_5, RST_PIN_5),? // Instance of the class for reader 5
? MFRC522(SS_PIN_6, RST_PIN_6),? // Instance of the class for reader 6
? MFRC522(SS_PIN_7, RST_PIN_7),? // Instance of the class for reader 7
? MFRC522(SS_PIN_8, RST_PIN_8)? ?// Instance of the class for reader 8
};
?
// Create a MIFARE_Key object for the authentication key
MFRC522::MIFARE_Key key;
?
// Create an array to store the new UID for each reader
byte nuidPICC[8][7];
?
// Create an array of reader IDs (A for reader 1, B for reader 2, etc.)
byte readerIDs[8] = {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H'};
?
void setup() {?
? // Initialize serial communication with the computer
? Serial.begin(9600, SERIAL_8N1);
?
? // Initialize the SPI bus
? SPI.begin();
?
? // Initialize each MFRC522 reader
? for (byte i = 0; i < 8; i++) {
? ? rfid[i].PCD_Init();
? }
?
? // Set the authentication key to 0xFF for all 6 key bytes
? for (byte i = 0; i < 6; i++) {
? ? key.keyByte[i] = 0xFF;
? }
}
?
void loop() {
? // Loop through each reader
? for (byte reader = 0; reader < 8; reader++) {
? ? // Check if a new card is present and read its serial number if so
? ? if (rfid[reader].PICC_IsNewCardPresent() && rfid[reader].PICC_ReadCardSerial()) {
?
? ? ? // Store the 7-byte UID in the nuidPICC array for the current reader
? ? ? for (byte i = 0; i < 7; i++) {
? ? ? ? nuidPICC[reader][i] = rfid[reader].uid.uidByte[i];
? ? ? }
?
? ? ? // Calculate the XOR checksum for the UID bytes
? ? ? byte checksum = nuidPICC[reader][0];
? ? ? for (byte i = 1; i < 7; i++) {
? ? ? ? checksum = checksum ^ nuidPICC[reader][i];
? ? ? }
?
? ? ? // Send the UID with the appropriate reader ID and checksum
? ? ? Serial.write(readerIDs[reader]);? // write reader ID
? for (byte i = 0; i < 7; i++) {
? if (i == 0) {
? ? Serial.write(readerIDs[reader]);? // write reader ID instead of STX at the beginning
? }
? Serial.write(nuidPICC[reader][i]);? // write UID bytes
}
? Serial.write(checksum);? // write XOR checksum
? Serial.write('>');? // replace ETX with '>'
? ? }
? }
}


Tom


 

I hope you folks don't mind, I'm following this thread with some interest as I would like to do similar, unfortunately I have little to no experience with RFID nor Arduinos.

I'm saving all the email traffic about this.

John


On Fri, Mar 24, 2023 at 5:34?PM Thomas Seitz <thomas.seitz@...> wrote:
Steve,

OK, so this sketch should work for you using an Arduino Mega (or Uno if you change the pin assignments) with UP TO 8 readers attached. If you connect less than 8, that should be fine too. This sketch absolutely outputs the tag data back to JMRI using the MERG Concentrator connection type. IF this doesn't work, then we can explore getting the 7-bytes down to 4, but like I said, I cannot find any mention of a 4-byte tag limitation in the JMRI docs.
?
?
// Import Libraries
#include <SPI.h>? // SPI library for communicating with the MFRC522 reader
#include <MFRC522.h>? // MFRC522 library for reading RFID cards
?
// Define the SS (Slave Select) and RST (Reset) pins for each reader
#define SS_PIN_1 10? // Slave Select pin for reader 1
#define RST_PIN_1 9? // Reset pin for reader 1
?
#define SS_PIN_2 8? // Slave Select pin for reader 2
#define RST_PIN_2 7? // Reset pin for reader 2
?
#define SS_PIN_3 6? // Slave Select pin for reader 3
#define RST_PIN_3 5? // Reset pin for reader 3
?
#define SS_PIN_4 4? // Slave Select pin for reader 4
#define RST_PIN_4 3? // Reset pin for reader 4
?
#define SS_PIN_5 2? // Slave Select pin for reader 5
#define RST_PIN_5 A0? // Reset pin for reader 5
?
#define SS_PIN_6 A1? // Slave Select pin for reader 6
#define RST_PIN_6 A2? // Reset pin for reader 6
?
#define SS_PIN_7 A3? // Slave Select pin for reader 7
#define RST_PIN_7 A4? // Reset pin for reader 7
?
#define SS_PIN_8 A5? // Slave Select pin for reader 8
#define RST_PIN_8 A6? // Reset pin for reader 8
?
// Create an array of MFRC522 objects (one for each reader)
MFRC522 rfid[8] = {
? MFRC522(SS_PIN_1, RST_PIN_1),? // Instance of the class for reader 1
? MFRC522(SS_PIN_2, RST_PIN_2),? // Instance of the class for reader 2
? MFRC522(SS_PIN_3, RST_PIN_3),? // Instance of the class for reader 3
? MFRC522(SS_PIN_4, RST_PIN_4),? // Instance of the class for reader 4
? MFRC522(SS_PIN_5, RST_PIN_5),? // Instance of the class for reader 5
? MFRC522(SS_PIN_6, RST_PIN_6),? // Instance of the class for reader 6
? MFRC522(SS_PIN_7, RST_PIN_7),? // Instance of the class for reader 7
? MFRC522(SS_PIN_8, RST_PIN_8)? ?// Instance of the class for reader 8
};
?
// Create a MIFARE_Key object for the authentication key
MFRC522::MIFARE_Key key;
?
// Create an array to store the new UID for each reader
byte nuidPICC[8][7];
?
// Create an array of reader IDs (A for reader 1, B for reader 2, etc.)
byte readerIDs[8] = {'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H'};
?
void setup() {?
? // Initialize serial communication with the computer
? Serial.begin(9600, SERIAL_8N1);
?
? // Initialize the SPI bus
? SPI.begin();
?
? // Initialize each MFRC522 reader
? for (byte i = 0; i < 8; i++) {
? ? rfid[i].PCD_Init();
? }
?
? // Set the authentication key to 0xFF for all 6 key bytes
? for (byte i = 0; i < 6; i++) {
? ? key.keyByte[i] = 0xFF;
? }
}
?
void loop() {
? // Loop through each reader
? for (byte reader = 0; reader < 8; reader++) {
? ? // Check if a new card is present and read its serial number if so
? ? if (rfid[reader].PICC_IsNewCardPresent() && rfid[reader].PICC_ReadCardSerial()) {
?
? ? ? // Store the 7-byte UID in the nuidPICC array for the current reader
? ? ? for (byte i = 0; i < 7; i++) {
? ? ? ? nuidPICC[reader][i] = rfid[reader].uid.uidByte[i];
? ? ? }
?
? ? ? // Calculate the XOR checksum for the UID bytes
? ? ? byte checksum = nuidPICC[reader][0];
? ? ? for (byte i = 1; i < 7; i++) {
? ? ? ? checksum = checksum ^ nuidPICC[reader][i];
? ? ? }
?
? ? ? // Send the UID with the appropriate reader ID and checksum
? ? ? Serial.write(readerIDs[reader]);? // write reader ID
? for (byte i = 0; i < 7; i++) {
? if (i == 0) {
? ? Serial.write(readerIDs[reader]);? // write reader ID instead of STX at the beginning
? }
? Serial.write(nuidPICC[reader][i]);? // write UID bytes
}
? Serial.write(checksum);? // write XOR checksum
? Serial.write('>');? // replace ETX with '>'
? ? }
? }
}


Tom


 

Hi Tom,

The CANRC522 sends the 4 bytes from the user EEPROM formatted just as the 4 bytes as stored in the user EPROM. The first two bytes are the DCC/vehicle address and the last two bytes are for user data.
At present in JMRI I think for the first two bytes decimal values 0 to 10239 represent long DCC addresses and 10240 to (2^16) -1 are vehicle addresses. I have some member of my club who still use short DCC addresses so I would like in the future to consider having a small range from 10240 to accommodate those.

The format on a CBUS message from the CANRC522 is DDES DevHi, DevLo, 00, Data 0, Data 1, Data 2 , Data3.

If you select CANRC522/CANRCOM in the reporters table then I think JMRI processes the first two bytes as the DCC/vehicle address and data bytes 3 and 4 as two separate variables.

Regards

Nick


 

Tom,

Looking forward to trying these sketches tonight when I get home. I'm pleased Nick gave you the details of the CANRC522 formatting. If our 7 byte UID read system doesn't work for some reason, then the CANRC522 4 byte system seems like the way to go to get around any JMRI data length limitations. However, I'm not sure how we would get this data in as the current CANRC522 system is a CAN Bus system. It is just data and as far as I know it is similar to Loconet data.

In fact the latter system has some advantages. The first 2 bytes are the dcc loco address. Once this is picked up by JMRI, we can use it with scripts or whatever to control that loco, speed it up, slow it down, stop it etc. The second 2 bytes, which I call 'User data' can be used for many things. Some examples are triggering specific train announcements, automatic route setting, activating 3rd rail sparking etc. In fact anything you want!

I am particularly interested in the multiple reader sketch. I was originally envisiging four readers, but up to eight is good. I notice on the web that some people have had problems with multiple readers. Well, some do, some don't. It seems that the quality of the cheap Chinese readers can be very variable and I think this maybe what's happening. Some have observed multiple readers do better with level shifters in circuit, as the Arduino is 5v and the readers 3.3v. Others suspect multiple readers have too much of a power drain on the Arduino and powering the readers separately is better, connecting the grounds together of course. Some have even used multiplexers to switch between readers and put the MISO line in a tristate state.?

Anyway, we'll see what happens and I need to order some more MFRC522's to test the multiple reader scenario!

Again, thanks for all your help on this.

Steve


 

John,

Welcome on board! I hope what we are trying to do here is of some interest to you and hopefully something you might be able to successfully use. Look forward to your input.

Steve


 

Tom,?

I have been asked by a few interested O Gauge modellers about RFID? The Seeed 125kHz and MFRC522 are okay for N and OO/HO gauges, but possibly not enough read distance for O Gauge. I have come across a PN5180 reader that has a much greater read distance and is backwards compatible with ISO14443 A tags. Have you come across these at all?

Steve