Serial read / parse hex data from Ascii in?

I for the life of me cant figure this out. I am inputting a string from the serial port that looks like..

t0x123,FF,00,01,01,D6,00,FF,F1

I need to take that data and make it into an array of int values. Right now I have it reading the data in as a char array for each character. The problem is is this format I cant do much as I need both values to do a sscanf. So how can I reformat this char array from...
char array 1 =

t
0
x
1
2
3
F
F 
etc...

to

char array 2 =

t
0x123
FF
00
01
etc..

so I can for loop a sscanf and get the hex int?

It's a very easy question. Take a look, for example to the function strtok():

I think the real question is how to I covert this..

String test1[] = "This,is,a,test";

to this...

char test2[] = "This,is,a,test";

I don't want to create an array.

My serial data input is built as a String.

// Serial input start
  if (Serial.available())  {
    char c = Serial.read();  //gets one byte from serial buffer
    if (c == '\r') {      
  // Handle serial input string start
      readSerialinput();
  // Handle serial input string end     
      readString=""; //clears readString      
     }  
    else {     
      readString += c; //builds readString
    }
  }  
// Serial input stop

First, by changing a bit your code you don't need to make the change that you are trying to do. So, can you post your entire code, so, I can do that change to you?

I cant really post all the code cuz its a huge project. I will try to explain better...

With the code above I am buffering the serial data to a String. The String will look like "t0x123,FF,00,01,01,D6,00,FF,F1" What I am trying to do is take this string and turn all those hex values int int values (decimal) so I can use them to control a hardware device via SPI. So basically I am using the "t" at the start to show its the one I want to send to SPI and I need to convert the string from that point. The problem would be an easy solution if it was not a string but a char containing the "t0x123,FF,00,01,01,D6,00,FF,F1" but its not. maybe you can show me with some simple code?

I can easily do what I want using this method (it would be in a for loop but show here long) to get my result if that string was converted to a char.

char test[] = "This,is,a,test";

    char *a;
    char *brkb;

    readString = strtok_r(test, "," ,&brkb);
    Serial.print("1: ");
    Serial.println(a);

    a = strtok_r(NULL, "," ,&brkb);
    Serial.print("2: ");
    Serial.println(a);
    
    a = strtok_r(NULL, "," ,&brkb);
    Serial.print("3: ");
    Serial.println(a);
    
    a = strtok_r(NULL, "," ,&brkb);
    Serial.print("4: ");
    Serial.println(a);

Instead of using hex you probably could just send the numeric values and convert the data to an integer for use.

//zoomkat 3-5-12 simple delimited ',' string parse 
//from serial port input (via serial monitor)
//and print result out serial port

String readString;
#include <Servo.h> 
Servo myservo;  // create servo object to control a servo 

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

  myservo.writeMicroseconds(1500); //set initial servo position if desired
  myservo.attach(7);  //the pin for the servo control 
  Serial.println("servo-delomit-test-22-dual-input"); // so I can keep track of what is loaded
}

void loop() {

  //expect a string like 700, or 1500, or 2000,
  //or like 30, or 90, or 180,

  if (Serial.available())  {
    char c = Serial.read();  //gets one byte from serial buffer
    if (c == ',') {
      if (readString.length() >0) {
        Serial.println(readString); //prints string to serial port out

        int n = readString.toInt();  //convert readString into a number

        // auto select appropriate value, copied from someone elses code.
        if(n >= 500)
        {
          Serial.print("writing Microseconds: ");
          Serial.println(n);
          myservo.writeMicroseconds(n);
        }
        else
        {   
          Serial.print("writing Angle: ");
          Serial.println(n);
          myservo.write(n);
        }

        //do stuff with the captured readString 
        readString=""; //clears variable for new input
      }
    }  
    else {     
      readString += c; //makes the string readString
    }
  }
}

You have a problem because you are using the "String" object. You can do the same thing using "char[]" variable type.
For your code:

// Serial input start
  if (Serial.available())  {
    char c = Serial.read();  //gets one byte from serial buffer
    if (c == '\r') {      
  // Handle serial input string start
      readSerialinput();
  // Handle serial input string end     
      readString=""; //clears readString      
     }  
    else {     
      readString += c; //builds readString
    }
  }  
// Serial input stop

If you define the variable readString that I believe that is declared like:

String readString;

As:

char readString[100];

You can do all you're doing, but with a array of chars instead of a String object.
Using this, the line:

      readString=""; //clears readString

must be modified to:

      strcpy(readString, ""); //clears readString

And the line:

readString += c; //builds readString

Must be modified to:

readString[count++]= c; //builds readString

Where the variable count is an integer counter counter defined like:

int count;

for example, next to the "string" variable.

Ok so my output would look like this is I used this method...

Serial data entered"t0x123,FF,00,01,01,D6,00,FF,F1"

output would be ( Just showing what they are filled with)...

char [0] = t
char [1] = 0
char [2] = x
char [3] = 1
char [4] = 2
char [5] = 3
char [6] = 4
char [7] = F
char [8] = F

So if thats the case and say I need char 7 and 8 to make a single int that = "FF" hex hex. How do I do that?

You can have a array that hold all the hex values, like:

   char hex_value[] = { '0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'A', 'B', 'C', 'D', 'E', 'F' };

Then, you can make a function to return the value in int of the char that you enter, like:

int hex2int(char hex) {
   for (int i=0; i < 16; i++) {
      if (hex_value[i] == hex) {
         return i;
      }
   }
   return 0;
}

And then you can use all this in your code, for example:

   int value = hex2int(char[7]) * 16 + hex2int(char[8]);

Without the real code this is a great mess, so, I hope you get the idea.

I guess the array part is where I am lost. I was able to covert to array simply by using

readString.toCharArray(char_array, str_len);

The problem I have is how to turn 2 separate array values into a single 2 digit hex like "FF"

Because the code is hard for me to just put up here. Let me explain. I am getting a string that looks like this "t0x123,FF,00,01,01,D6,00,FF,F1" I am trying to make a char array look like this...

char hex_value[] = { 't', '0x123', 'FF', '00', '01', '01', 'D6', '00', '00', 'FF', 'F1'};

so I can use something like this...

for (int i =  2 ; i <=10; i++)
      {
      sscanf( char_array[i];, "%x", & int_char_array[i];); 
      }

To give me something like this...

char hex_value[] = {'255', '0', '1', '1', '214', '0', '0', '255', '241'};

I don't remember how to use sscanf(). I don't remember to use this function or see it in any real application, but it can work.
The problem is that this:
(...)
I am trying to make a char array look like this...

char hex_value[] = { 't', '0x123', 'FF', '00', '01', '01', 'D6', '00', '00', 'FF', 'F1'};

(...)
[/quote]

can't be done with only one command like you want (unless that I know).

What I would do if I was in your place will be use the function strtok() to pick all the parts of the message, and then copy them to other string (or whatever).

BTW, this:

char hex_value[] = { 't', '0x123', 'FF', '00', '01', '01', 'D6', '00', '00', 'FF', 'F1'};

Is not a string, and I don't think that it work with sscanf(). To sscanf() is better the original string. See how the sscanf() function works:

Going a dif way and still getting frustrated...

Trying to just do the math by hand and I am getting a crazy result I don't understand.

int i = 6*16^0;
int x = 13*16^1;
int z =  i + x ;
Serial.println(z,HEX);
Serial.println(i,DEC);
Serial.println(x,DEC);

Maybe someone can tell me why the result is

131
96
209

When it should be

D6
6
208

nevermind on the last part I figured it out...

int i = 6* pow(16, 0);
int x = 13* pow(16, 1);
int z =  i + x ;
Serial.println(z,HEX);
Serial.println(i,DEC);
Serial.println(x,DEC);

That works.

I am just gonna do this by hand in long form I guess.

pow(16, 0) = 1
pow(16, 1) = 16

And this is the same hat I did in:

int value = hex2int(char[7]) * 16 + hex2int(char[8]);

This is kinda where I am going with this because I have it working. Wish there was a better way to do it. I will be turning it mostly into loops as this was just a test more less. "readString" is the serial buffer coming in. This code will decode the 2 digits after the "t" and echo them back as the Hex value as well as the dec value. Now I can use those values to talk to the spi hardware. I will do this for all 8 hex data values. Maybe this will hell you understand exactly what I need. like I say this works but its more less a hack.

int str_len = readString.length() + 1;        // Length (with one extra character for the null terminator)
char char_array[str_len];                     // Prepare the character array (the buffer)  
readString.toCharArray(char_array, str_len);  // Copy string to char (serial buffer)


//Serial.println(readString);
int a1;
if (char_array[1] >= 48 && char_array[1] <= 57) {
  a1 = (char_array[1] - 48)* pow(16, 1);
}else if (char_array[1] >= 65 && char_array[1] <= 70){
  a1 = (char_array[1] - 55)* pow(16, 1);
}else{
  a1 = 0;
}

int b1;
if (char_array[2] >= 48 && char_array[2] <= 57) {
  b1 = (char_array[2] - 48)* pow(16, 0);
}else if (char_array[2] >= 65 && char_array[2] <= 70){
  b1 = (char_array[2] - 55)* pow(16, 0);
}else{
  b1 = 0;
}

int c1 =  a1 + b1 ;
Serial.println("");
Serial.print("Hex:");
Serial.println(c1,HEX);
Serial.print("Dec:");
Serial.println(c1,DEC);
Serial.print("a1:");
Serial.println(a1,DEC);
Serial.print("b1:");
Serial.println(b1,DEC);

I am getting a string that looks like this "t0x123,FF,00,01,01,D6,00,FF,F1"

Really? What sends mixed character sets like that? What is "t0x123"? The hex is not sent in a single consistant format like "FF" or "0xFF"? Anyhow the below bit of code might be of use.

str = "0x1d";
int n;
sscanf (str,"%x",&n);
Serial.prinln(n, BYTE);

zoomkat:

I am getting a string that looks like this "t0x123,FF,00,01,01,D6,00,FF,F1"

Really? What sends mixed character sets like that? What is "t0x123"? The hex is not sent in a single consistant format like "FF" or "0xFF"? Anyhow the below bit of code might be of use.

str = "0x1d";

int n;
sscanf (str,"%x",&n);
Serial.prinln(n, BYTE);

That only works on a char. The problem i have is parsing a char to be 2 digits not one. If the data was "F" it would be fine buts its "FF". I was thinking along the lines of using the sscanf on each char and then doing the math I posted to convert the 2 digits into a single int. I need the double digits to be output as decimal. I know the format is a bit weird but its what it is and I need to figure it out. Really I only need the 8 data values after the "t0x123"

byte n;

void setup() {
  Serial.begin(115200);
  char s[] = {"32"};
  n = hexToByte( s[0] );
  Serial.println (n);
  n = ( n * 16 ) + hexToByte( s[1] );
  Serial.println (n);
}

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

byte hexToByte (char c) {
  if ( (c >= '0') && (c <= '9') ) {
    return c - '0';
  }
  if ( (c >= 'A') && (c <= 'F') ) {
    return (c - 'A')+10;
  }
}

Can someone tell me why I cant define an array index as a input for this...

This works...

        char s[] = "F";
        int n;
        sscanf (s,"%x",&n);
        Serial.println(n,HEX);  
        Serial.println(n,DEC);

This does not

        int n;
        sscanf (char_array[1],"%x",&n);
        Serial.println(n,HEX);  
        Serial.println(n,DEC);

I get invalid conversion from 'char' to const char*'