Need help to convert a string to bytes for I2C

Hello everybody, I am a real noob on Arduino trying to improve my skills.

I have this project where I need to configure a program that will send a string to Arduino such as : "F 01 00 00... " and the Arduino will have to convert this string as 6 bytes to send it via I2C.

I have trouble trying to convert a string to bytes, my tutor said that I should convert this string (01 00 00 etc...) to bytes (byte 1 = 01 , byte 2 = 00, etc...) in order to send them.

I hope you understood my problem :slight_smile:

Thank you guys in advance !

If you really have a (c-type) string aka an array of char then you already have bytes :wink:

lolilol78:
[...] a program that will send a string to Arduino

How?

lolilol78:
[...] such as : "F 01 00 00... " and the Arduino will have to convert this string as 6 bytes to send it via I2C.

I'm not seeing how that string should be 6 bytes... If it really is a string then it's 15 bytes. Or do you mean you get a string of 6 ascii converted and (ascii) space delimited hex-values?

How would YOU convert '0' and '1' to 1? Hint: What is '0' - '0'? What is '1' - '0'?

septillion:
If you really have a (c-type) string aka an array of char then you already have bytes :wink:
How?
I'm not seeing how that string should be 6 bytes... If it really is a string then it's 15 bytes. Or do you mean you get a string of 6 ascii converted and (ascii) space delimited hex-values?

Well I dont really understand what my tutor is asking but he wants me to configure a program that will have a line like "F 01 00 00 00 ff ff" and he wants me to convert this string to have byte 1 = 01 , byte 2 = 00 , etc...

he wants me to convert this string

So, use strtok() to find each token. When you have a string like "01", you can easily convert that to an int, using strtoul(). If you use the appropriate base, it will even handle the "ff".

PaulS:
So, use strtok() to find each token. When you have a string like "01", you can easily convert that to an int, using strtoul(). If you use the appropriate base, it will even handle the "ff".

Thanks for your answer and help Paul !

Then you have to understand that is an ascii string. From the looks of it with "F " as a start marker followed by hex ascii values.

But devil is in the details, ask that tutor EXACTLY what he wants to send. And how you get that data.

And what he wants you to send. Does he want you to just send that string? Or does he want you to split that string and convert that ascii to byte size values.

Cant seem to find good examples online for strtok()

Can someone explain me how to use it ? thanks

septillion:
Then you have to understand that is an ascii string. From the looks of it with "F " as a start marker followed by hex ascii values.

But devil is in the details, ask that tutor EXACTLY what he wants to send. And how you get that data.

And what he wants you to send. Does he want you to just send that string? Or does he want you to split that string and convert that ascii to byte size values.

I will ask him thank you for your help . As far as I know, he wants me to have a text file listing a list of strings , and each string will send bytes from Arduino to the FEE via I2C, in each channel ..

1)But:
a) send that string
b) or, send the ascii hex-values in that string

  1. where do those values come from?

  2. and what exactly is the layout?

septillion:
1)But:
a) send that string
b) or, send the ascii hex-values in that string

  1. where do those values come from?

  2. and what exactly is the layout?

It would take the "bytes" value from that string and convertt them to actual bytes and send them via I2C

These values would come from a text file generated before via a program i think (he just told me that)

for example ; the text file would contain :

F 01 00 00 00 ff ff
F 02 00 12 22 fh 01
F 03 32 22 33 22 33

so the arduino would receive these informations, would understand that if there is "F" as a start, it needs to send bytes, and then convert each of these 32 22 33 etc... to actual bytes to send via I2C.

But the first byte 01 or 02 represent the actual channel where the data will be sent to, for example 02 would send the bytes to the second channel of the FEE via I2C...

Hope I am clear :slight_smile:

Thank you guys

So you receive a text string of characters - F 03 32 22 33 22 33.

When the highlighted characters 32 are received, exactly what is to be sent out to represent those characters?

Maybe I'm just dense.

@dougp, I did assume hex but then I have no idea what "fh" should be...

But no matter what, you can use strtol() can do the job.

Think something like:

char inStr[20] = "F 02 00 12 22 fe 01";
byte outBytes[6];

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

  byte i = 0;
  char *pEnd = &inStr[1];
  while((i < sizeof(outBytes)) && 
        (*pEnd != '\0') && 
        (*pEnd != '\n'))
  {
    outBytes[i] = strtol(pEnd, &pEnd, 16);
    i++;
  }
  
  Serial.println(F("Bytes found: "));
  for(byte i = 0; i < sizeof(outBytes); i++){
    Serial.print(outBytes[i]);
    Serial.print(F(" 0x"));
    Serial.println(outBytes[i], HEX);
  }
}

void loop(){
  
}

Do note, there is NO check to see if a value fits a byte. It does terminate if there are more than 6 values OR if the string ended befor 6 values with a '\0' (NULL char) or '\n' (new line).

lolilol78:
Can someone explain me how to use it ? thanks

Given: char s[3] = {'0', '1', '\0'};

What token could be derived from the above string? We hope to get an answer from the poster who has introduced this here in this thread.

I am sorry for confusions guys, no matter what characters are in the line, it is just the principle that i dont get of converting characters from a string to actual bytes... My tutor told me that the first byte (for channel selection like 01 or 02 etc...) needs to be done with atoi ? and the other ones need to be done with atohex.

For example, if the parameter of one byte is "FA" in the string , it would give 4641 in hex, and then convert this FA into 11111010 (i dont know if this is true lol) to actually send the byte via I2C.

I hope I am clear guys sorry for confusion

needs to be done with atoi ?

You would NOT use atoi() if the string contained a representation in any base other than 10.

and the other ones need to be done with atohex.

IF that is what your instructor said, your instructor needs to provide you with the atohex() function he/she expects you to use.

For example, if the parameter of one byte is "FA" in the string , it would give 4641 in hex

What have you been smoking? FA16 = 25010

lolilol78:
of one byte is "FA" in the string , it would give 4641 in hex

No, "FA" is just the ASCII representation of 0x46 0x41 (two bytes*). But you don't need to convert between the two, the two are different representations of the same thing. Like one, één, uno, eins, une etc are just different representations (/languages) of the same.

And if you want that ASCII hex(?) string converted to a single byte value (250 aka 0xFA aka 0b11111010, again, all the same, different representation!) you can just have a look at Reply #13.

atoi() only works with 10-base numbers. atohex() is just a made up function name :wink:

*Only if it's a part of a string, "FA" alone would be 3 bytes (0x46 0x41 0x00) aka it includes a null character.

septillion:
No, "FA" is just the ASCII representation of 0x46 0x41 (two bytes*). But you don't need to convert between the two, the two are different representations of the same thing. Like one, één, uno, eins, une etc are just different representations (/languages) of the same.

And if you want that ASCII hex(?) string converted to a single byte value (250 aka 0xFA aka 0b11111010, again, all the same, different representation!) you can just have a look at Reply #13.

atoi() only works with 10-base numbers. atohex() is just a made up function name :wink:

*Only if it's a part of a string, "FA" alone would be 3 bytes (0x46 0x41 0x00) aka it includes a null character.

Thank you for your answer, still a bit confusing for a noob like me haha. I will check with my tutor and probably get back to the forum, thanks guys :slight_smile:

It's indeed a concept a lot of newbies don't get. But it is very similar to language.

On a micro everything is stored as bits which on an Ardruino Uno are grouped per byte aka 8-bit. For example, the decimal 5 is stored as 0b00000101 where 0b just indicates we're talking bits. But in writing it's just like the number 5 is build up of a horizontal line, a vertical line and a have circle.

But if we talk about 5, we can also represent it as 'five'. It does not matter (at least not for the meaning) if you write "I at 5 apples" or "I at five apples". But even, if you specifically indicate, you could write it in a different representation aka language. "I at vijf apples". It still has the same meaning as long as you understand (or look up) the meaning of 'vijf'.

Same goes for representation in code. You can have 42 (integer), 0x2A (leading 0x indicating), 052 (leading 0 indicating octal) or '' (surrounding single quotes indicating ascii character) or 0b00101010 (leading 0b indicating binary). But the way you write it, the compiler will know the representation and sees what you want. But all representations will give the same bit's set/cleared! 42 == 0x2A == 052 == '' = 0b00101010, only represented in a different way in the code. In the machine instructions they do not differ.

But, unlike micro's, we prefer text instead of number and so does the serial monitor. Every byte send to it will be interpreted as ASCII. So if we want to see 0x2A printed as "2A" (surrounding double quotes indicating a string aka array of char ASCII*) we need to extend that value into two ASCII character, a '2' and a 'A' (which can also be represented by two hex as 0x32 and 0x41 or two decimals 50 and 65, each filling a byte.

But you simply want it the other way. :smiley: atoi() can do that for ASCII represented integers ("1234" for example) but is clueless what to do with a character 'A'. strtol() can handle all from 2-base (binary) up to 36-base ASCII.

*I know I say ASCII but it's actually UTF8. But for simplicity, let's not worry about it...