rfid reader convert hex to dec

Hello everyone. I just got a rfid kit that appeared in an episode from Jeremy Blum videos.
I put the code that he wrote and it worked fine, I get values on the serial console. My problem is that I got this kit so I can replace a broken rfid reader from work. That reader gave me a decimal value, for example 0030016351256. The kit that I made with the arduino gives me something like F98018.
If I convert that to decimal than it's ok, it's the last part of the whole code read by the broken rfid reader. I can easily add the prefix to the output. But I don't know how to convert the data to a decimal value so I can instead print that.
```
*//Jeremy Blum's Arduino Tutorial Series - Episode 12 - RFID Cards
//Sample Code - RFID Code Reading
//http://www.jeremyblum.com
//Some Code Adapted from http://www.cooking-hacks.com
//Code Updated on 1/21/2012 to comply with Arduino 1.0 Changes

byte data[3];  //For holding the ID we receive
int val = 0;
void setup()
{
  // Start serial port 19200 bps
  Serial.begin(19200);
 
  // Setting Auto Read Mode - EM4102 Decoded Mode - No password
  // command: FF 01 09 87 01 03 02 00 10 20 30 40 37
  Serial.write(0xFF);  //Header
  Serial.write(0x01);  //Reserved
  Serial.write(0x09);  //Length (Command + Data)
  Serial.write(0x87);  //Command (0x87 sets auto mode behavior
  Serial.write(0x01);  //Data 1: Enable Auto-Read
  Serial.write(0x03);  //Data 2: Mode – Parity decoded – Manchester RF/64
  Serial.write(0x02);  //Data 3: Total number of block to be read (2)
  Serial.write((byte)0x00);  //Data 4: No password expected
  Serial.write(0x10);  //Data 5: Password byte 1
  Serial.write(0x20);  //Data 6: Password byte 2
  Serial.write(0x30);  //Data 7: Password byte 3
  Serial.write(0x40);  //Data 8: Password byte 4
  Serial.write(0x37);  //Checksum
 
  delay(500);
  Serial.flush();
  Serial.println();
  Serial.println("RFID module started in Auto Read Mode, Waiting for Card...");
}

void loop()
{
  val = Serial.read();
  while(val !=0xff)
  {
    val = Serial.read();
    delay(1000);
  }
    //we already read the header (0xff)
  Serial.read();            // reserved
  Serial.read();            // length
  Serial.read();            // command (indicates tag data)
  Serial.read();            // we discard data 1
  Serial.read();            // we discard data 2
  data[0] = Serial.read();    // we read data 3
  data[1] = Serial.read();    // we read data 4
  data[2] = Serial.read();    // we read data 5
  Serial.read();            // checksum
 
  // Indentify RFID Card
      Serial.print("Card found - Code: ");
  for (int i=0; i<3; i++)
  {
    if (data[i] < 16) Serial.print("0");
    Serial.print(data[i], HEX);
    }
  Serial.println();
}*
```

The last time I saw a question like this on here the decimal turned out to be an ASCII representation of the number of something. I forget now.

Can you get the output of the same card scanned on both the old and the new readers so that we can work out the correlation between the two outputs?

Bob808:
But I don't know how to convert the data to a decimal value so I can instead print that.
[/quote]
Pack the data into an unsigned long using bit shifts and addition.

   // Start serial port 19200 bps
   Serial.begin(19200);
   
   // Setting Auto Read Mode - EM4102 Decoded Mode - No password
   // command: FF 01 09 87 01 03 02 00 10 20 30 40 37
   Serial.write(0xFF);  //Header
   Serial.write(0x01);  //Reserved
   Serial.write(0x09);  //Length (Command + Data)
   Serial.write(0x87);  //Command (0x87 sets auto mode behavior
   Serial.write(0x01);  //Data 1: Enable Auto-Read
   Serial.write(0x03);  //Data 2: Mode – Parity decoded – Manchester RF/64
   Serial.write(0x02);  //Data 3: Total number of block to be read (2)
   Serial.write((byte)0x00);  //Data 4: No password expected
   Serial.write(0x10);  //Data 5: Password byte 1
   Serial.write(0x20);  //Data 6: Password byte 2
   Serial.write(0x30);  //Data 7: Password byte 3
   Serial.write(0x40);  //Data 8: Password byte 4
   Serial.write(0x37);  //Checksum
   
   delay(500);
   Serial.flush();
   Serial.println();
   Serial.println("RFID module started in Auto Read Mode, Waiting for Card...");

Are you using Serial to talk to the RFID reader OR to the PC? Both is the wrong answer.

   val = Serial.read();
   while(val !=0xff)
   {
     val = Serial.read();
     delay(1000);
   }

Why are you NOT using Serial.available() to determine when there is something to read?

    //we already read the header (0xff)
   Serial.read();             // reserved
   Serial.read();             // length
   Serial.read();             // command (indicates tag data)
   Serial.read();             // we discard data 1
   Serial.read();             // we discard data 2
   data[0] = Serial.read();    // we read data 3
   data[1] = Serial.read();    // we read data 4
   data[2] = Serial.read();    // we read data 5
   Serial.read();             // checksum

As soon as there is a byte to read, read all 9 of them. What a load of crap.

PaulS:

   val = Serial.read();

while(val !=0xff)
   {
     val = Serial.read();
     delay(1000);
   }



Why are you NOT using Serial.available() to determine when there is something to read?

Serial.available() is pretty pointless there. You are interested in getting one specific value. If there is nothing to read Serial.read() returns -1. This is just the same as checking Serial.avaliable() before doing the read - especially as Serial.read() first calls Serial.available() and returns -1 if there is nothing available :wink:

That while loop is functionally equivalent to

int val = 0;
while (val != 0xFF) {
  while (Serial.available() == 0) {
    continue;
  }
  val = Serial.read();
}

or

int val = 0;
while (val != 0xFF) {
  if (Serial.available() > 0) {
    val = Serial.read();
  }
}

All do the same thing in different ways. Just like skinning that poor moggy.

Serial.available() is pretty pointless there. You are interested in getting one specific value.

Not really. If the device is supposed to return 9 bytes to be read (6 of which are simply discarded), the Arduino can be doing other things, until there are 9 (or more) bytes to be read.

The one second delay in the loop is pointless, too. That, and luck, are the only things "ensuring" that all 9 bytes arrive together.

The whole read-the-serial-data part of that application needs to be scrapped and written properly.

Thanks for the replies.
I must say that this is my first Arduino project. My only background in electronics is my hobby for audio amplifiers :slight_smile:
I just copied the code and made some minor adjustments so I get my 3 bites of data. I am just getting my hands wet with the programming language.
From the short time I spent with this code it seems that it always prints the same info so I don't have corrupted info on serial console.
I will post some examples with 2 cards read from the same type of rfid reader than I'm trying to replace and from arduino. The thing is that we have more readers used in our parking system, I can borrow one from the other control point to make some tests. The thing is that the company that we bought the system from is asking for 500 euro for one reader so I managed to get this deal for 10 times less :slight_smile: in fact the rfid reader is 35 euro and the xbee shield is 15 euro, but I intend to program a 328 and implement in the reader so I keep my arduino for more fun projects :slight_smile: Right now I need to get the code right so it spits the same format as the old reader. I will come back with the examples.

PaulS:

Serial.available() is pretty pointless there. You are interested in getting one specific value.

Not really. If the device is supposed to return 9 bytes to be read (6 of which are simply discarded), the Arduino can be doing other things, until there are 9 (or more) bytes to be read.

The one second delay in the loop is pointless, too. That, and luck, are the only things "ensuring" that all 9 bytes arrive together.

The whole read-the-serial-data part of that application needs to be scrapped and written properly.

Well, yes, the rest of the reading is rubbish, but when waiting for a specific start character to know when to start doing your serial reading (if, as in the code provided by the OP you don't need to do anything else), then Serial.available() is redundant. Yes, you want to use Serial.available() after you have that start character to get the rest of the packet, but you don't need it for detecting that start character.

You can just as well do:

void loop() {
  if (Serial.read() == 0xFF) {
    callFunctionToGetRestOfData();
  }
  // Do idle time processes
}

because at that moment in time you don't care how much is available, only if you have received the start character.

Yes, you could use Serial.available() to wait for a pre-defined number of characters to be available, but what if you don't know how many characters you will need to receive? Wrapping the Serial.read() in a Serial.available() in a situation like this just means you're doing two Serial.available()s.

Wrapping the Serial.read() in a Serial.available() in a situation like this just means you're doing two Serial.available()s.

Personally, I think that's still a good thing to do. For one thing, if you call Serial.read() only after knowing that there is something to read, you can use something other than int to store the one meaningful byte that is returned. Storing the value in a char or byte can often have advantages.

For another, using Serial.available() indicates that you know that there might not be data to read, which indicates an awareness of how serial data transmission works. In my mind, that's a good thing to show.

In any case, since all that Serial.available() is doing is returning the difference between two values, it's a fast call, so I wouldn't worry about the overhead of the (possibly extraneous) call.

ok it was stupid of me to read only 3 bytes. It seems that I need to read the whole 5 bytes. I got fooled as I had a new batch of cards that had the same prefix code.
I got one card from an older batch and a second card from a new batch. I read them with one of the original rfid readers and then with the arduino reader. Here's the results:
1st card - old reader - code: 0630003676890
1st card - arduino - code: 3F00381ADA
2nd card -old reader - code: 0030016365048
2nd card -arduino - code: 0300F9B5F8

Now if I take the first card code and convert to dec only the last part 381ADA I get 3676890, same as the last part of the old reader. Same thing for the 2nd card, F9B5F8 goes to 16365048. This had me fooled into thinking that the old reader just slapped 00300 in front of each code. I guess that's why some producers put a shorter code on the card, it's actually the last part if they are a whole batch, discarding the first 2 bytes or so. This is 125khz system by the way.
This is my setup with the xbee shield: http://www.cooking-hacks.com/index.php/arduino-rfid-module-1.html
Until I get to the conversion part I need to sort out the bytes of info, and they way the old reader is translating them.
I reverted the code to reading the whole 5 bytes:

//Jeremy Blum's Arduino Tutorial Series - Episode 12 - RFID Cards
//Sample Code - RFID Code Reading
//http://www.jeremyblum.com
//Some Code Adapted from http://www.cooking-hacks.com
//Code Updated on 1/21/2012 to comply with Arduino 1.0 Changes

 byte data[5];  //For holding the ID we receive
 int val = 0;
 void setup()
 {
   // Start serial port 19200 bps
   Serial.begin(19200);
   
   // Setting Auto Read ÂMode - EM4102 Decoded Mode - No password
   // command: FF 01 09 87 01 03 02 00 10 20 30 40 37
   Serial.write(0xFF);  //Header
   Serial.write(0x01);  //Reserved
   Serial.write(0x09);  //Length (Command + Data)
   Serial.write(0x87);  //Command (0x87 sets auto mode behavior
   Serial.write(0x01);  //Data 1: Enable Auto-Read
   Serial.write(0x03);  //Data 2: Mode – Parity decoded – Manchester RF/64
   Serial.write(0x02);  //Data 3: Total number of block to be read (2)
   Serial.write((byte)0x00);  //Data 4: No password expected
   Serial.write(0x10);  //Data 5: Password byte 1
   Serial.write(0x20);  //Data 6: Password byte 2
   Serial.write(0x30);  //Data 7: Password byte 3
   Serial.write(0x40);  //Data 8: Password byte 4
   Serial.write(0x37);  //Checksum
   
   delay(500);
   Serial.flush();
   Serial.println();
   Serial.println("RFID module started in Auto Read Mode, Waiting for Card...");
 }

 void loop()
 {
   val = Serial.read();
   while(val !=0xff)
   {
     val = Serial.read();
     delay(1000);
   }
    //we already read the header (0xff)
   Serial.read();             // reserved
   Serial.read();             // length
   Serial.read();             // command (indicates tag data)
   //Serial.read();             // we discard data 1
   //Serial.read();             // we discard data 2
   data[0] = Serial.read();    // we read data 3
   data[1] = Serial.read();    // we read data 4
   data[2] = Serial.read();    // we read data 5
   data[3] = Serial.read();    // we read data 5
   data[4] = Serial.read();    // we read data 5
   Serial.read();             // checksum
   
   // Indentify RFID Card
      Serial.print("Card found - Code: ");
   for (int i=0; i<5; i++)
   {
     if (data[i] < 16) Serial.print("0");
      Serial.print(data[i], HEX);
    }
   Serial.println();
 }
   Serial.write(0x30);  //Data 7: Password byte 3
   Serial.write(0x40);  //Data 8: Password byte 4
   Serial.write(0x37);  //Checksum
   
   delay(500);
   Serial.flush();
   Serial.println();
   Serial.println("RFID module started in Auto Read Mode, Waiting for Card...");

You STILL seem to think that you can talk to the PC and the RFID reader on the same line. You are probably confusing the hell out of your RFID reader, and are certainly sending the Serial Monitor stuff it can't handle.

What the hell is the flush() for? What version of the IDE are you using? Is flush() any more than "I don't know what this does, but it doesn't seem to hurt, so I'll slap it here" code?

   //Serial.read();             // we discard data 1
   //Serial.read();             // we discard data 2
   data[0] = Serial.read();    // we read data 3
   data[1] = Serial.read();    // we read data 4
   data[2] = Serial.read();    // we read data 5
   data[3] = Serial.read();    // we read data 5
   data[4] = Serial.read();    // we read data 5

Yeah, right. If you are going to have useless code and comments, at least the useless comments should be accurate.

I'm using 1.0.5 for mac
Listen, I don't think you read my previous posts. I just said that I'm a complete beginner and this is my first project. I COPIED the code. If you want to lash out just send an email to the original coder, his name is in the code!
If you have a bad day, or if you're generally like this please move on to another topic. I got into this project after I saw read/saw how welcoming the Arduino community is. So far you've been no help and I see that you're playing smart with me. Either you can help me or don't post anymore.

Bob808:
So far you've been no help

That's completely false. He has helped, your skin is too thin that you are getting distracted by the tone of his comments, rather than their content.

@Bob808
I used to work for a company that made RFID readers, it fact I designed some for them. On some readers they apply an encoding algorithm so that the number they spit out is not the number that is read from the card but is derived from it.
It might be that your reader is one of those sorts, if so then you can never get the same number because those algorithms are secret. In that way they can charge you a lot of money for a reader if you need it to be compatible with the rest of the system.
Can you post a link to the type of reader you are trying to replace.

Then it helps to get the right code set up to actually read what you have got. There is a lot of bad code out there and just because you copied it from some place without understanding it will not make it work.
You need to talk to the reader with one set of serial lines and talk to the monitor with another set. As the Uno has only on set of serial lines you need to use a software program to emulate another set. This can be done with a library called softwareSerial which is now part of the Arduino IDE. So if you code does not use this method then it will not do what you want it to.
If you have an arduino Mega then that has four sets of serial lines with no library needed but your code must use the separate lines.

I'm doing this in my spare time so I didn't manage to modify the code, I only restored the reading of all 5 bytes (not bits as I thought before) so I get a complete reading of the codes from these cards.
Tomorrow I will try to open one of the old readers and see what's inside. I will look over your sugestions and see what I can do. Indeed the Uno has only one serial and I must see if that screws with the output.
I very much appreciate and respect someone with more knowledge than me, but I do have a problem with the way someone presents himself/herself.

After a closer inspection of the rfid module I noticed that it has JP3 on it without a connector soldered. There's sda, scl and gnd there. Would it be easier to connect to arduino via i2c? Either that or I discard the shield and connect the module's rx/tx pins to software serial pins on arduino. This seems like a really nice project to learn :slight_smile:
Here's the schematic of the rfid module:
http://www.cooking-hacks.com/skin/frontend/default/cooking/pdf/arduino_rfid.pdf

Would it be easier to connect to arduino via i2c

Well it would free up the serial port for printing out the results. You would need to add pull up resistors to the I2C lines and write code that talked to the RFID reader through I2C.

Either that or I discard the shield and connect the module's rx/tx pins to software serial pins on arduino.

Yes that is another option.

I chose to do it the i2c way.
First I removed the 328 from the uno, put the jumpers on USB position on xbee shield and downloaded the sm125 software from sonmicro site. It's a config utility for this chip. There I activated i2c and also did some tests with 3 cards that I had. It spit out:
1st card - FF 01 06 10 03 00 F9 80 18 AB
2nd card- FF 01 06 10 03 00 F9 72 66 EB
3rd card - FF 01 06 10 03 00 F9 B5 F8 C0
First byte is the header and is always FF, second byte 01 is reserved and no use currently, third byte is the lenght of the payload data - 06 (it's command+rfid code lenght), fourth is the command byte - 10, next 5 bytes are the rfid tag - 03 00 F9 B5 F8 and the last byte is the checksum for all the packet.
So judging by the first card data it seems that my previous results with the original code that I copied are consistent.
I will now try to write the code for i2c use.
If I cannot work out the way the old rfid reader was translating the code I will use a dirty method and slap the prefix of the batch in front of the last 3 bytes of the code. I made some tests and the only difference between all my cards (about 200) is the last 3 bytes. This way if I ever buy a new batch I only need to adjust the code to put the new prefix that those cards come with. I also looked into the database and the first batch of cards had the same prefix for the whole lot. This and translating from HEX to decimal :slight_smile: I will post back later after I've made some progress.

You might be interested in these two functions:-

long  tokenInVar(){
  long number = 0;
       for(int i=0; i<8; i++) number = (number << 4) | convertFromHex(int(token[i]));
   return(number);
}

long int convertFromHex(int ascii){ 
  if(ascii > 0x39) ascii -= 7; // adjust for hex letters upper or lower case
  return(ascii & 0xf);
}

This assumes you have a char array called token with a succession of HEX ASCII characters in it. The first function will return a long int with the token code in it. If you want more bits ( which you do ) change from a long to a long long, as well as the number of times round the for loop.

I finally cracked the code!
Ok, so I managed to write the code for i2c, it's far from perfect and I need to sort out some details but it's all good.
Rfid tags have 5 bytes of data that I'm going to name A B C D and E for this explanation. With my code I can extract those bytes and display them on the console. They way this reader works on i2c is that after it read the tag you send it a command to give you that info. It gives it in two 5 bytes packets. First 5 bytes are the tag's first 4 bytes and a "there's more" byte. The second 5 byte packet contains the last byte from the 5 byte tag data and 3 more blank bytes and the last "there's nothing more" byte. I strip the 5th byte from the first packet and the last 4 bytes from the last packet and I get my 5 byte info on screen, HEX type.
Now, my problem was that the first two bites weren't consistent with the data that my old reader spat out so I figured I could just get the last 3 bytes and have my code glue the prefix in front of them but now I managed to understand what the old reader was doing. And I did this while trying to understand how to convert hex to dec. The problem is that the hex data is isolated in 5 bytes, it doesn't come as a whole HEX. The old reader was "gluing" the last C-D-E bytes and then translated them as a whole hex. Now I discovered that the first 2 bytes, A and B, were translated as individual hex numbers. So for example if I take my previous examples:

1st card - 3F 00 38 1A DA tag with old reader giving me - 0630003676890
2nd card- 03 00 F9 B5 F8 tag with old reader giving me - 0030016365048

3F is 63, 00 is 0 and and 381ADA is 3676890
same for second card
03 is 3, 00 is 0 and F9B5F8 is 16365048. Seems like I need to separately convert the first two bytes from hex to dec, then "glue" the last 3 bytes together and translate that whole hex into dec. All that and slap a "0" in front of all codes :slight_smile:
Now all that's left is finishing the code.