(serial receive) HEX --> String

:) Hello everybody,

A sensor sends data back to the Arduino in this (HEX) format:

EF 01 FF FF FF FF 07 00 07 00 00 06 00 A8 00 BC

Now I want to receive this train of data and get the number "6" (in bold) out of it. At the position where the "06" is, comes different data each time. So I want to read that particular position.

Does anyone know how to do this? How do I get this train of data into a string? I've to use Serial.read(); but what else? (or maybe are there better ways?)

Thanks in advance,

Atmoz

You can use the below test code to start doing some parcing testing. You can copy your string and use ctrl v to paste it into the serial monitor, then send it to the arduino. The captured string will be sent back to the serial monitor.

// zoomkat 10-29-10 simple delimited ',' string parce 
// from serial port input (via serial monitor)
// and print result out serial port
// CR/LF could also be a delimiter
// for IDE 0019 and later

String readString;

void setup() {
  Serial.begin(9600);
}

void loop() {

  //expect a string like wer,qwe rty,123 456,hyre kjhg,
  //or like hello world,who are you?,bye!,
  while (Serial.available()) {
    delay(10);  //small delay to allow input buffer to fill

    char c = Serial.read();  //gets one byte from serial buffer
    if (c == ',') {
      break;
    }  //breaks out of capture loop to print readstring
    readString += c; 
  } //makes the string readString  

  if (readString.length() >0) {
    Serial.println(readString); //prints string to serial port out

    readString=""; //clears variable for new input
  }
}

S/he means 'parsing' in case you were wondering/googling ;)

Thanks for the fast reply! I'll test your program :)

Thanks!!

Hello,

With that procedure I can perfectly make a string from what's coming from the serial port! Thanks for that.

After I send (in HEX) EF01FFFFFFFF010003010005 to my device it replies with

EF01FFFFFFFF07000300000A (also HEX)

or

EF01FFFFFFFF07000302000C (also HEX)

How can I for example turn on a LED if a device sends the first code?

I mean, I know how to turn on the LED, but how do I "check" if the HEX input perfectly match?

With kind regards,

Atmoz

[edit]

I think it has to do something with combine HighByte and LowByte together... In my (working) demo application on the computer (Visual Basic) it works at that way. The program read 2 bytes every time and combines them together. How cam I manage that with Arduino code?

Where does the need to process strings come in? The sensor is not sending the hex data as strings, it it?

Even if it is, you are interested in certain characters from the array, not the whole array converted to a number, right?

Anyway, we need to see the code that you have for receiving the data.

If you want to make numbers out of the string “EF01FFFFFFFF07000302000C”, it seems to me that you would want to convert “EF” to a number, “01” to a number, “FF” to a number, etc.

Convert each character to a number. If the character is greater than ‘A’ and less than ‘F’, subtract ‘A’ and add 10. Otherwise, subtract ‘0’.

To convert a pair of characters to a single number, multiply the first value by 16 and add the second value.

EF01FFFFFFFF07000300000A (also HEX) or EF01FFFFFFFF07000302000C (also HEX) How can I for example turn on a LED if a device sends the first code? I mean, I know how to turn on the LED, but how do I "check" if the HEX input perfectly match?

Easiest to me seems to test the length of the string (have I got all chars) and just check the last char.

use http://arduino.cc/en/Reference/StringCompareTo to check 100% equality.

Two questions arise: Q: what to do when it is different from both? Q: What sensor are you using? do you have a datasheet URL? Curious what all those bits mean :)

Rob

The deveice is a "Fingerprint Scanner"

http://www.sparkfun.com/commerce/product_info.php?products_id=8881

http://www.sparkfun.com/datasheets/Sensors/Biometric/ARA-ME-2510.pdf (datasheet)

http://www.sparkfun.com/datasheets/Sensors/Biometric/fingerprint%20module-2510.doc (documentation)

Where does the need to process strings come in? The sensor is not sending the hex data as strings, it it?

Even if it is, you are interested in certain characters from the array, not the whole array converted to a number, right?

Anyway, we need to see the code that you have for receiving the data.

If you want to make numbers out of the string "EF01FFFFFFFF07000302000C", it seems to me that you would want to convert "EF" to a number, "01" to a number, "FF" to a number, etc.

Convert each character to a number. If the character is greater than 'A' and less than 'F', subtract 'A' and add 10. Otherwise, subtract '0'.

To convert a pair of characters to a single number, multiply the first value by 16 and add the second value.

I'm not at home now, so I don't have code right now. But indeed, it isn't necesarry to process string. The only thing I want is to receive one of these 2 codes (after sending a match request, but that part does work already!) and verify wich code it is (the first code is a succesfull match, the second is a bad match, and then again the match request has to be send)

Easiest to me seems to test the length of the string (have I got all chars) and just check the last char.

use http://arduino.cc/en/Reference/StringCompareTo to check 100% equality.

Two questions arise: Q: what to do when it is different from both? Q: What sensor are you using? do you have a datasheet URL? Curious what all those bits mean Smiley

Rob

Hallo Rob,

http://www.sparkfun.com/commerce/product_info.php?products_id=8881

http://www.sparkfun.com/datasheets/Sensors/Biometric/ARA-ME-2510.pdf (datasheet)

http://www.sparkfun.com/datasheets/Sensors/Biometric/fingerprint%20module-2510.doc (documentation)

:)

With the computer test tool the Fingerprint Scanner works realy good!! A very cool peace of electronics!

Greetz,

Atmoz

Interesting device! I have worked with fingerprintdevices for printers and the quality of recognition was quite different in those days

One of the nicest applications was to assign different functions to different fingers. Opens lots of possibilities :)

Interesting device! I have worked with fingerprintdevices for printers and the quality of recognition was quite different in those days

One of the nicest applications was to assign different functions to different fingers. Opens lots of possibilities Smiley

Indeed nice to work with huh :wink:
Yep, I can imagine that the quality of the earlier scanners was poor, but that’s changed! It works surprisingly good!! What you say: every finger a own function. Nice!!

Coming back to my problem:

The Fingerprint Scanner waits for a match-request message. With the Arduino I’m able to send that with:

uint8_t cmd[]={0xEF,0x01,0xFF,0xFF,0xFF,0xFF,0x01,0x00,0x03,0x01,0x00,0x05};

Serial.write(cmd,12); // Scan commando

Then the Scanner replies with

EF01FFFFFFFF07000300000A // responce van module, match 3 ok!! - rechter middelvinger

or

EF01FFFFFFFF07000302000C // responce als match NIET oke is!!

I have checked this via a COM-port-sniffer program at my computer. (when there was no Arduino, only COMport from pc and Scanner). So that part works. Now I want to get rid of the computer and use the Arduino instead.

So it’s half working right now: I can send the Scan commando from Arduino to Scanner. What can I do to check if the Scanner sends the “Match OK” command?

With the COM-port-sniffer program I saw the above “string” in HEX!!
Therefore my code doesn’t work good:

    while (Serial.available()) {
       delay(10);  //small delay to allow input buffer to fill

       char c = Serial.read();  //gets one byte from serial buffer

       readString += c;
      } //makes the string readString

     if (readString.length() >0) {
        if (readString == 'EF01FFFFFFFF07000300000A')   //Match ID 3
           {   //do something with it...
            }
    }

Something like this?

char buffer[24];
int cnt = 0;
  
void setup()
{
  Serial.begin(9600);
  Serial.println("Start");
}

void loop(void)
{
  // read max 24 chars
  if ((cnt < 24) && Serial.available()) buffer[cnt++] = Serial.read();

  if (cnt == 24) 
  {
    if (strncmp(buffer,"EF01FFFFFFFF07000300000A", 24) == 0) 
    {
      Serial.println("Yes");
    } else {
      Serial.println("Enter another number");
    }
    Serial.flush();
    cnt = 0;
  }
  // do something   
}

Thanks for the answer/help Rob!!

But unfortunately it still doesn't work...

In the computer-program I do this to receive correctly from the Scanner:

Private Sub Form_Load()

' Fire Rx Event Every Two Bytes
MSComm1.RThreshold = 2

' When Inputting Data, Input 2 Bytes at a time
MSComm1.InputLen = 2
MSComm1.Settings = "9600,N,8,1"
MSComm1.DTREnable = False
MSComm1.CommPort = 3
MSComm1.PortOpen = True

End Sub




Private Sub MSComm1_OnComm()
Dim sData As String ' Holds our incoming data
Dim lHighByte As Long   ' Holds HighByte value
Dim lLowByte As Long    ' Holds LowByte value
Dim lWord As Long       ' Holds the Word result


If MSComm1.CommEvent = comEvReceive Then

    sData = MSComm1.Input ' Get data (2 bytes)

    lHighByte = Asc(Mid$(sData, 1, 1)) ' get 1st byte
    lLowByte = Asc(Mid$(sData, 2, 1))  ' Get 2nd byte
        
    Text3.Text = Text3.Text & " " & lHighByte & " " & lLowByte
    
    'Text2.Text = Text2.Text & " " & Hex$(lHighByte) & " " & Hex$(lLowByte)
    
    Text2.Text = Text2.Text & " " & (Hex$(lHighByte) + Hex$(lLowByte))
    
    ' Combine bytes into a word
    lWord = (lHighByte * &H100) Or lLowByte
    
    ' Convert value to a string and display
    Text1.Text = Text1.Text & CStr(lWord)
    
End If

Textbox 1, 2 and 3 are just for testing... But it has to do something with receive 2 bytes at once, and then combine those 2 so that a correct "char" or "bytes" appears.

Textbox 1, 2 and 3 are just for testing...

What are you actually seeing in those text boxes?

You don't have the luxury of reading multiple bytes at once on the Arduino, but then, it isn't necessary. The VB application is reading two bytes, and then splitting it into two separate bytes. The lHighByte and lLowByte values that is produces are exactly the same two bytes that you can read on the Arduino.

Could you add a counter in the Visual Basic program to see how many bytes are received?

Can you quote the litteral text from textbox2.text ?

Could you add this for loop into the code to see what’s received (just before the test?

if (cnt == 24)
  {
     for(int i=0; i<24; i++) Serial.print(buffer[i]); <<- this kline

Rob

What are you actually seeing in those text boxes?

text1.text =

61185655356553517952560255

text2.text =

 EF1 FFFF FFFF 73 A0 0FF

text3.text =

 239 1
 255 255
 255 255
 7 3
 10 0
 0 255

You don't have the luxury of reading multiple bytes at once on the Arduino, but then, it isn't necessary. The VB application is reading two bytes, and then splitting it into two separate bytes. The lHighByte and lLowByte values that is produces are exactly the same two bytes that you can read on the Arduino.

Okay! Thanks for clearing this up :)

Could you add a counter in the Visual Basic program to see how many bytes are received?

Can you quote the litteral text from textbox2.text ?

Could you add this for loop into the code to see what's received (just before the test?

I'll do this tonight.

Thanks for helping me out both of you!!

Greets,

Atmoz

P.S. above textboxes are being filled with that data with this Arduino code:

String readString;
int ledPin = 13;                 // LED connected to digital pin 13

boolean found = false;

//EF 01 FF FF FF FF 01 00 03 01 00 05 - zelfde als enroll c.q. commando om scannen te activeren!!

uint8_t cmd[]={0xEF,0x01,0xFF,0xFF,0xFF,0xFF,0x01,0x00,0x03,0x01,0x00,0x05};

void setup() {
  Serial.begin(9600);
  pinMode(ledPin, OUTPUT);      // sets the digital pin as output
  digitalWrite(ledPin, LOW);    // sets the LED off

}

void loop() {

     while (Serial.available()) {
       delay(10);  //small delay to allow input buffer to fill

       char c = Serial.read();  //gets one byte from serial buffer

       readString += c;
      } //makes the string readString

    Serial.print(readString);

         readString=""; //clears variable for new input

  }

(just to see how I must check the string or data on the Arduino, because he must do this "check" later, instead of the computer).

(So I now simulate the FingerScanner with the computer program).

Seeing your VB output it becomes clear what the code should look like: (you receive 12 bytes instead of 24 as I assumed) ==> A quick retry of my earlier posted code.

byte buffer[12];
int cnt = 0;
  
void setup()
{
  Serial.begin(9600);
  Serial.println("Start");
}

void loop(void)
{

  // read max 12 bytes
  if ((cnt < 12) && Serial.available()) buffer[cnt++] = Serial.read();

  if (cnt == 12)  // all bytes read...
  {
    // assume the arrays are the same
    boolean same = true;

    // the ans array holds the right answer
    byte ans[]={0xEF,0x01,0xFF,0xFF,0xFF,0xFF,0x07,0x00,0x03,0x00,0x00,0x0A};

    for (int i=0; i< 12 && same; i++) same = (buffer[i] != ans[i]);

    if (same)
    {
      Serial.println("Yes");
    } else {
      Serial.println("Enter another number");
    }
    Serial.flush();
    cnt = 0;
  }
  // do something  
}

Thanks Rob, for your good help!!

Unfortunately I getting always “Enter another number” back.
Even if I send exactly “EF01FFFFFFFF07000300000A” with the computer program:

(yellow is send by computer to Arduino)

With kind regards & good night,

Atmoz

Oh, btw: I changed

 for (int i=0; i< 12 && same; i++) same = (buf[i] != ans[i]);

to

for (int i=0; i< 12 && same; i++) same = (buffer[i] != ans[i]);

:wink:

I've uploaded the computer-test-tool: http://www.lumatronix.nl/Project1.exe

If button "Match ID 3 OK!" is pressed it sends

"EF01FFFFFFFF07000300000A"

If button "No Match" is pressed it sends

"EF01FFFFFFFF07000302000C"

Those 2 datastreams I want to receive and test in the Arduino.

It shouldn't be to hard, but unfortunately it doesn't work till now :'(

(and off course there is NO virus or other mall-ware in the *.exe I hope you trust me on that :))

Thanks again for watching en helping me out!!

With kind regards,

Atmoz

[edit]

P.S. check post above this one with the screenshot...

Change this line

for (int i=0; (i< 12) && same; i++) same = (buffer[i] != ans[i]);

to

for (int i=0; (i< 12) && same; i++) same = (buffer[i] == ans[i]);

I rewrote the testloop to quit faster but did not test (stupid me) as I had no sensor and did not take time to simulate one. The previous version in fact tests that all bytes are unequal!

Hopes this helps

I rewrote the testloop to quit faster but did not test (stupid me) as I had no sensor and did not take time to simulate one. The previous version in fact tests that all bytes are unequal!

Hopes this helps

Thanks Rob!!

When I'm at home I'm directly gonna test it :) Looks like this must work now isn't it?! 8-) 8-)

I'm very curious...

  • another small question: If the Arduino is busy with controlling a stepper motor (for about 1 á 2 seconds) does it receive serial data in the meanwhile?

Because after the Arduino sends the "Scan" or "Get Match" command to the FingerScanner, then a stepper motor slides the Scanner under my fingertip. And just in that time the Scanner sends the "MATCH OK! (serial) signal to the Arduino...

So I'm hoping that the Arduino can do this things simultaneously!

Thanks and greets,

Atmoz