Convert RFID reader data from Hexadecimal to decimal

Hi,

I am doing some testing with my WL-134 RFID reader.
The RFID reader output is HEX. And i would like to "convert" the string to base 10 before processing the tag data further.

Example from manual:

Module output:
02 31 37 31 41 39 32 35 33 41 33 34 38 33 30 30 31 30 30 30 30 30 30 30 30 30 30 07 F8 03
Equal ASCII:171A9253A34830010000000000a
We can find card nuber is 171A9253A3,country number is 483 (LSB First)
We can translate these number to Dec format,card number equal: 250000023921 ,
Country number equal 900

I have found several topics regarding HEX to base 10. But it seems that it wont work with my HEX string as the product is always 12 digits as base 10. And the Arduino is only showing me the greatest number "2147483647" (10 digits).

Code I have used for testing is:

  long decimal_answer = strtoul("3FC93A2346", NULL, 16);
  Serial.print (decimal_answer);

And it seems for me that the result in base 10 is ambigious therefore printing: 2147483647 instead of 273958970182

HEX conversion is OK when using HEX product less than or equal to "2147483647" (10 digits).

Do anyone have some tip here for how to work around this issue with a conversion of these "big" HEX - > DEC conversion?

What is the largest value that can be stored in an unsigned long? Is that more, or less, than the value you are trying to store in an unsigned long?

Hmm, didnt think about that..
The value I am trying to store is when testing is: 273958970182 , more than maximum for unsigned long. Would it be possible to do the conversion and store the result splited in 2? As the first 7 digits is my farmer ID and the last 5 digits is unique animal ID for each tag?

What is the specific reason why the farmer/animal ID number must be stored in a single value?

The hex string is not a numerical value, it's just a label, like "drawer 52", which may or may not be the 52nd drawer, treat it as a textual label, not as a numerical value that can be added, subtracted or multiplied by.

aarg:
What is the specific reason why the farmer/animal ID number must be stored in a single value?

If it is possible to store them in 2 variables separated that would be nice. But I don`t find a way to do that... And storing them in one single value doesent work as the number is to big...

edgemoron:
The hex string is not a numerical value, it's just a label, like "drawer 52", which may or may not be the 52nd drawer, treat it as a textual label, not as a numerical value that can be added, subtracted or multiplied by.

Sorry, but I dont know exactly what you mean.

The text written on the tag does not necessarily reflect the text read from the tag. Why do you think it is necessary to convert the text read from the tag to a number?

When you can answer that question, we can discuss how to do it, if it is reasonable to do it.

Obviously, if the text always contains 12 characters, and the characters are always digits (hex or decimal), then you could convert the first 6 characters to a number, and then convert the 2nd 6 characters to a number.

But why? Comparing one string to another is going to be conceptually clearer than comparing 4 numbers.

The text written on the tag does reflect the text read from the tag.
If I convert the HEX string: 3FC93A2346 to decimal using browser online converter i get the decimal number: 273958970182. The first 7 digits represents my "farmer ID" and the last 5 digits represent the unique animal tag for these tags.

The plan is to send each tags data to a server`s database. So the conversion to base 10 could off course be done on the server side. But i prefer to do the conversion on the arduino itself if that is possible. The final product of the HEX string in DEC would always be 12 characters.

Attached is the manual for the reader I am testing. It is the "Card Number" I am interested in converted to decimal.

E WL-134.doc (765 KB)

You could use a long long variable (or unsigned long long), and do the conversion yourself. It really isn't that difficult.

char tagData[] = "3FC93A2346";
unsigned long long tagNumb = 0;

   for(byte b=0; b<strlen(tagData); b++)
   {
      char tagDigit = tagData[b];
      byte digitVal = 0;
      if(tagDigit >= '0' && tagDigit <= '9')
         digitVal = tagDigit - '0';
      else if(tagDigit >= 'A' && tagDigit <= 'F')
         digitVal = tagDigit - 'A' + 10;

      tagNumb *= 16;
      tagNumb += digitVal;
   }

'3' --> 3
0 * 16 + 3 = 3

'F' --> 5 + 10 = 15
3 * 16 + 15 = 63

and so on.

PaulS:
You could use a long long variable (or unsigned long long), and do the conversion yourself. It really isn't that difficult.

char tagData[] = "3FC93A2346";

unsigned long long tagNumb = 0;

for(byte b=0; b<strlen(tagData); b++)
  {
      char tagDigit = tagData[b];
      byte digitVal = 0;
      if(tagDigit >= '0' && tagDigit <= '9')
        digitVal = tagDigit - '0';
      else if(tagDigit >= 'A' && tagDigit <= 'F')
        digitVal = tagDigit - 'A' + 10;

tagNumb *= 16;
      tagNumb += digitVal;
  }




'3' --> 3
0 * 16 + 3 = 3

'F' --> 5 + 10 = 15
3 * 16 + 15 = 63

and so on.

Thank you Paul... How do i use this conversion? And I am not sure if I agree/understand your "example" in the end... Shouldn't`t it be:
(3x 16^9) + (15x 16^8) + (12x 16^7) .....etc

How do i use this conversion?

Create a function to do the conversion. The function takes a char * (a pointer to the string to convert) and returns an unsigned long long.

Call the function wherever you have a string to convert to a numeric value.

Shouldn't`t it be:

No.
The first digit is a '3', with a value of 3. The value so far is 3.
The next digit is processed. Its a 'F', with a value of 15. 3 * 16 is 48. 48 + 15 is 63.
Repeat for each digit...

Work it out for yourself. Or, write a simple sketch to call the function with the string I showed, and print the result. I don't have an Arduino with me, or I'd show the intermediate values and the result.

Hmm... when using the "unsigned long long" Arduino IDE wont let me compile:

call of overloaded 'print(long long unsigned int&)' is ambiguous...

When changing to unsigned long it would print, but then "tagNumb" only consists of 10 digits again...

Post the code.

Attached is the test code.

char tagData[] = "3FC93A2346";
unsigned long long tagNumb = 0;
 
void setup() {
  // put your setup code here, to run once:
Serial.begin(9600);
hexToNumber();
Serial.print(tagNumb);
}

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

}


void hexToNumber()
{


   for(byte b=0; b<strlen(tagData); b++)
   {
      char tagDigit = tagData[b];
      byte digitVal = 0;
      if(tagDigit >= '0' && tagDigit <= '9')
         digitVal = tagDigit - '0';
      else if(tagDigit >= 'A' && tagDigit <= 'F')
         digitVal = tagDigit - 'A' + 10;

      tagNumb *= 16;
      tagNumb += digitVal;
      
   }
 
}

call of overloaded 'print(long long unsigned int&)' is ambiguous...

This is always followed by a list of overloads the compiler thinks might work. That list is missing from your post.

I'm pretty sure it knows how to print a sighed long long. You don't really need unsigned, even though the values you get can never be negative.

Attached is the log from when compiling.
Same error happends even when removing unsigned..
"unsigned long" works but not long long

Arduino:1.8.3 (Mac OS X), Kort"Arduino/Genuino Uno"

/Applications/Arduino.app/Contents/Java/arduino-builder -dump-prefs -logger=machine -hardware /Applications/Arduino.app/Contents/Java/hardware -hardware /Users/sindrevr/Library/Arduino15/packages -hardware /Users/sindrevr/Documents/Arduino/hardware -tools /Applications/Arduino.app/Contents/Java/tools-builder -tools /Applications/Arduino.app/Contents/Java/hardware/tools/avr -tools /Users/sindrevr/Library/Arduino15/packages -built-in-libraries /Applications/Arduino.app/Contents/Java/libraries -libraries /Users/sindrevr/Documents/Arduino/libraries -fqbn=arduino:avr:uno -vid-pid=0X2A03_0X0043 -ide-version=10803 -build-path /var/folders/hp/rbw81k3140bd4nj_nlp9q75w0000gn/T/arduino_build_100732 -warnings=none -build-cache /var/folders/hp/rbw81k3140bd4nj_nlp9q75w0000gn/T/arduino_cache_979926 -prefs=build.warn_data_percentage=75 -prefs=runtime.tools.arduinoOTA.path=/Applications/Arduino.app/Contents/Java/hardware/tools/avr -prefs=runtime.tools.avr-gcc.path=/Applications/Arduino.app/Contents/Java/hardware/tools/avr -prefs=runtime.tools.avrdude.path=/Applications/Arduino.app/Contents/Java/hardware/tools/avr -verbose /Users/sindrevr/Dropbox/21 Aug arduino/test rfid/sketch_aug24a/sketch_aug24a.ino
/Applications/Arduino.app/Contents/Java/arduino-builder -compile -logger=machine -hardware /Applications/Arduino.app/Contents/Java/hardware -hardware /Users/sindrevr/Library/Arduino15/packages -hardware /Users/sindrevr/Documents/Arduino/hardware -tools /Applications/Arduino.app/Contents/Java/tools-builder -tools /Applications/Arduino.app/Contents/Java/hardware/tools/avr -tools /Users/sindrevr/Library/Arduino15/packages -built-in-libraries /Applications/Arduino.app/Contents/Java/libraries -libraries /Users/sindrevr/Documents/Arduino/libraries -fqbn=arduino:avr:uno -vid-pid=0X2A03_0X0043 -ide-version=10803 -build-path /var/folders/hp/rbw81k3140bd4nj_nlp9q75w0000gn/T/arduino_build_100732 -warnings=none -build-cache /var/folders/hp/rbw81k3140bd4nj_nlp9q75w0000gn/T/arduino_cache_979926 -prefs=build.warn_data_percentage=75 -prefs=runtime.tools.arduinoOTA.path=/Applications/Arduino.app/Contents/Java/hardware/tools/avr -prefs=runtime.tools.avr-gcc.path=/Applications/Arduino.app/Contents/Java/hardware/tools/avr -prefs=runtime.tools.avrdude.path=/Applications/Arduino.app/Contents/Java/hardware/tools/avr -verbose /Users/sindrevr/Dropbox/21 Aug arduino/test rfid/sketch_aug24a/sketch_aug24a.ino
Using board 'uno' from platform in folder: /Applications/Arduino.app/Contents/Java/hardware/arduino/avr
Using core 'arduino' from platform in folder: /Applications/Arduino.app/Contents/Java/hardware/arduino/avr
Warning: Board breadboard:avr:atmega328bb doesn't define a 'build.board' preference. Auto-set to: AVR_ATMEGA328BB
Detecting libraries used...
"/Applications/Arduino.app/Contents/Java/hardware/tools/avr/bin/avr-g++" -c -g -Os -w -std=gnu++11 -fpermissive -fno-exceptions -ffunction-sections -fdata-sections -fno-threadsafe-statics  -flto -w -x c++ -E -CC -mmcu=atmega328p -DF_CPU=16000000L -DARDUINO=10803 -DARDUINO_AVR_UNO -DARDUINO_ARCH_AVR   "-I/Applications/Arduino.app/Contents/Java/hardware/arduino/avr/cores/arduino" "-I/Applications/Arduino.app/Contents/Java/hardware/arduino/avr/variants/standard" "/var/folders/hp/rbw81k3140bd4nj_nlp9q75w0000gn/T/arduino_build_100732/sketch/sketch_aug24a.ino.cpp" -o "/dev/null"
Generating function prototypes...
"/Applications/Arduino.app/Contents/Java/hardware/tools/avr/bin/avr-g++" -c -g -Os -w -std=gnu++11 -fpermissive -fno-exceptions -ffunction-sections -fdata-sections -fno-threadsafe-statics  -flto -w -x c++ -E -CC -mmcu=atmega328p -DF_CPU=16000000L -DARDUINO=10803 -DARDUINO_AVR_UNO -DARDUINO_ARCH_AVR   "-I/Applications/Arduino.app/Contents/Java/hardware/arduino/avr/cores/arduino" "-I/Applications/Arduino.app/Contents/Java/hardware/arduino/avr/variants/standard" "/var/folders/hp/rbw81k3140bd4nj_nlp9q75w0000gn/T/arduino_build_100732/sketch/sketch_aug24a.ino.cpp" -o "/var/folders/hp/rbw81k3140bd4nj_nlp9q75w0000gn/T/arduino_build_100732/preproc/ctags_target_for_gcc_minus_e.cpp"
"/Applications/Arduino.app/Contents/Java/tools-builder/ctags/5.8-arduino11/ctags" -u --language-force=c++ -f - --c++-kinds=svpf --fields=KSTtzns --line-directives "/var/folders/hp/rbw81k3140bd4nj_nlp9q75w0000gn/T/arduino_build_100732/preproc/ctags_target_for_gcc_minus_e.cpp"
Kompilerer skisse...
"/Applications/Arduino.app/Contents/Java/hardware/tools/avr/bin/avr-g++" -c -g -Os -w -std=gnu++11 -fpermissive -fno-exceptions -ffunction-sections -fdata-sections -fno-threadsafe-statics -MMD -flto -mmcu=atmega328p -DF_CPU=16000000L -DARDUINO=10803 -DARDUINO_AVR_UNO -DARDUINO_ARCH_AVR   "-I/Applications/Arduino.app/Contents/Java/hardware/arduino/avr/cores/arduino" "-I/Applications/Arduino.app/Contents/Java/hardware/arduino/avr/variants/standard" "/var/folders/hp/rbw81k3140bd4nj_nlp9q75w0000gn/T/arduino_build_100732/sketch/sketch_aug24a.ino.cpp" -o "/var/folders/hp/rbw81k3140bd4nj_nlp9q75w0000gn/T/arduino_build_100732/sketch/sketch_aug24a.ino.cpp.o"
/Users/sindrevr/Dropbox/21 Aug arduino/test rfid/sketch_aug24a/sketch_aug24a.ino: In function 'void setup()':
sketch_aug24a:8: error: call of overloaded 'print(long long unsigned int&)' is ambiguous
 Serial.print(tagNumb);
                     ^
/Users/sindrevr/Dropbox/21 Aug arduino/test rfid/sketch_aug24a/sketch_aug24a.ino:8:21: note: candidates are:
In file included from /Applications/Arduino.app/Contents/Java/hardware/arduino/avr/cores/arduino/Stream.h:26:0,
                 from /Applications/Arduino.app/Contents/Java/hardware/arduino/avr/cores/arduino/HardwareSerial.h:29,
                 from /Applications/Arduino.app/Contents/Java/hardware/arduino/avr/cores/arduino/Arduino.h:232,
                 from /var/folders/hp/rbw81k3140bd4nj_nlp9q75w0000gn/T/arduino_build_100732/sketch/sketch_aug24a.ino.cpp:1:
/Applications/Arduino.app/Contents/Java/hardware/arduino/avr/cores/arduino/Print.h:65:12: note: size_t Print::print(const __FlashStringHelper*) <near match>
     size_t print(const __FlashStringHelper *);
            ^
/Applications/Arduino.app/Contents/Java/hardware/arduino/avr/cores/arduino/Print.h:65:12: note:   no known conversion for argument 1 from 'long long unsigned int' to 'const __FlashStringHelper*'
/Applications/Arduino.app/Contents/Java/hardware/arduino/avr/cores/arduino/Print.h:66:12: note: size_t Print::print(const String&) <near match>
     size_t print(const String &);
            ^
/Applications/Arduino.app/Contents/Java/hardware/arduino/avr/cores/arduino/Print.h:66:12: note:   no known conversion for argument 1 from 'long long unsigned int' to 'const String&'
/Applications/Arduino.app/Contents/Java/hardware/arduino/avr/cores/arduino/Print.h:67:12: note: size_t Print::print(const char*) <near match>
     size_t print(const char[]);
            ^
/Applications/Arduino.app/Contents/Java/hardware/arduino/avr/cores/arduino/Print.h:67:12: note:   no known conversion for argument 1 from 'long long unsigned int' to 'const char*'
/Applications/Arduino.app/Contents/Java/hardware/arduino/avr/cores/arduino/Print.h:68:12: note: size_t Print::print(char)
     size_t print(char);
            ^
/Applications/Arduino.app/Contents/Java/hardware/arduino/avr/cores/arduino/Print.h:69:12: note: size_t Print::print(unsigned char, int)
     size_t print(unsigned char, int = DEC);
            ^
/Applications/Arduino.app/Contents/Java/hardware/arduino/avr/cores/arduino/Print.h:70:12: note: size_t Print::print(int, int)
     size_t print(int, int = DEC);
            ^
/Applications/Arduino.app/Contents/Java/hardware/arduino/avr/cores/arduino/Print.h:71:12: note: size_t Print::print(unsigned int, int)
     size_t print(unsigned int, int = DEC);
            ^
/Applications/Arduino.app/Contents/Java/hardware/arduino/avr/cores/arduino/Print.h:72:12: note: size_t Print::print(long int, int)
     size_t print(long, int = DEC);
            ^
/Applications/Arduino.app/Contents/Java/hardware/arduino/avr/cores/arduino/Print.h:73:12: note: size_t Print::print(long unsigned int, int)
     size_t print(unsigned long, int = DEC);
            ^
/Applications/Arduino.app/Contents/Java/hardware/arduino/avr/cores/arduino/Print.h:74:12: note: size_t Print::print(double, int)
     size_t print(double, int = 2);
            ^
exit status 1
call of overloaded 'print(long long unsigned int&)' is ambiguous

You could try using sprintf() with %llu as the format specifier, to convert the value back to a string, and print() the string.

Yup, for what ever reason the Serial.print() method does like 'unsigned long long' or 'uint64_t'. Paul's 'sprintf()' idea works. Or, you could split it apart:

//char tagData[] = "3FC932346A";
char tagData[] = "3FC93A2346";
char decimalForm[16];
unsigned long long tagNumb = 0;
uint32_t farmerID, animalID;
 
void setup() {
  // put your setup code here, to run once:
Serial.begin(9600);
hexToNumber();
Serial.print((uint32_t) ((tagNumb>>32) & 0xFFFFFFFF), HEX);
Serial.println((uint32_t) (tagNumb & 0xFFFFFFFF), HEX);
sprintf(decimalForm, "%llu", tagNumb);
Serial.println(decimalForm);
farmerID = tagNumb / 100000;
animalID = tagNumb - farmerID * 100000;
Serial.println(farmerID);
Serial.println(animalID);
}

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

void hexToNumber()
{
   for(byte b=0; b<strlen(tagData); b++)
   {
      char tagDigit = tagData[b];
      byte digitVal = 0;
      if(tagDigit >= '0' && tagDigit <= '9')
         digitVal = tagDigit - '0';
      else if(tagDigit >= 'A' && tagDigit <= 'F')
         digitVal = tagDigit - 'A' + 10;
      tagNumb *= 16;
      tagNumb += digitVal;
      
   } 
}

Did you get anywhere with this ? I have the same chip and would love to hear of your success or problems :slight_smile:

@

sindrevr:
Hi,

I am doing some testing with my WL-134 RFID reader.
The RFID reader output is HEX. And i would like to "convert" the string to base 10 before processing the tag data further.

Example from manual:

Module output:
02 31 37 31 41 39 32 35 33 41 33 34 38 33 30 30 31 30 30 30 30 30 30 30 30 30 30 07 F8 03
Equal ASCII:171A9253A34830010000000000
We can find card nuber is 171A9253A3,country number is 483 (LSB First)
We can translate these number to Dec format,card number equal: 250000023921 ,
Country number equal 900

I have found several topics regarding HEX to base 10. But it seems that it wont work with my HEX string as the product is always 12 digits as base 10. And the Arduino is only showing me the greatest number "2147483647" (10 digits).

Code I have used for testing is:

  long decimal_answer = strtoul("3FC93A2346", NULL, 16);

Serial.print (decimal_answer);




And it seems for me that the result in base 10 is ambigious therefore printing: 2147483647 instead of 273958970182

HEX conversion is OK when using HEX product less than or equal to "2147483647" (10 digits).

Do anyone have some tip here for how to work around this issue with a conversion of these "big" HEX - > DEC conversion?