0

I have two characters, that I get by Bluetooth.
char a = SerialBT.read();
char b = SerialBT.read();

According to the Arduino Reference, decoded data stored in a char gets encoded to ASCII text.
I want to combine them in an Intenger, but the following methods don't work:

int c = a + b;

int c = (int)a + (int)b;

int c = (a - 48) + (b - 48);

and

String c;
c.setCharAt(0, a);
c.setCharAt(1, b);

Thank you

10
  • 2
    The sentence “decoded data stored in a char gets encoded to ASCII text” makes no sense: a and b contain the received data as is, with no encoding/decoding whatsoever applied. All the methods you show should work, but do different things. What exactly are you trying to achieve by “combining” the characters? Please, show an example of the data you have and the result you want. – Edgar Bonet Sep 10 '20 at 17:10
  • 1
    What do you mean by “it don't work”? What numeric value would you expect c to have? – Edgar Bonet Sep 10 '20 at 18:22
  • 1
    I expect it to be in ASCII value. – Python Schlange Sep 10 '20 at 18:23
  • 1
    "What do you mean by “it don't work”?" - I get a decimal value, not a ASCII one. Sorry, I didn't write it clearly. – Python Schlange Sep 10 '20 at 18:23
  • 1
    @PythonSchlange You still didn't really explain, what you receive and what you want. Are you receiving ASCII encoded data (like the Serial Monitor does)? Or are you receiving simple integers? And what value in what type do you expect as output? The string "4950"? An integer with value 4950? Or are 49 and 50 the decimal values of the two bytes of an integer value? – chrisl Sep 10 '20 at 18:25
3

OK, so after the lengthy requests for clarifications, it appears that you are receiving a number in ASCII decimal ("12") and want to parse it into an integer.

You may use the parseInt() method of the serial object, like:

int c = SerialBT.parseInt();

This can however make you program quite slow, as parseInt() uses a timeout to know when to stop expecting more digits.

If you already have read the bytes, you can combine them with simple arithmetics:

int c = 10 * (a - '0') + (b - '0');

Note that '0' is the same as 48, only it makes more explicit the intent of your code.

1
  • Thank you so much! It's working now. But I recieve a decimal number, just for clearance. – Python Schlange Sep 10 '20 at 18:39
1

Use an AND mask to convert the character to a digit:

int c = 10 * (a & 0x0F) + (b & 0x0F);

When ASCII was invented, the digits 0 to 9 were encoded in hexadecimal as 30 to 39 to enable easy conversion to/from digits and characters.

To convert a digit to ASCII, OR the byte with 0x30:

byte digit = 5;
char character = digit | 0x30;

To convert a character to a digit, AND it with 0x0F:

char character = '5';
byte digit = character & 0x0F;

These logical operators are faster and more efficient than mathematical operations + and -.

32
  • 1
    In what way are these operators faster and more efficient? A binary & and a subtraction both take a single clock cycle for an AVR. I.m.o this will only make your code less readable (make it less clear what it is actually doing). – StarCat Sep 10 '20 at 19:23
  • 1
    Note also that the byte() conversion has no effect, as it is undone by the subsequent integral promotion. You can simply write character & 0x0f. – Edgar Bonet Sep 10 '20 at 19:40
  • 1
    Re “speed and efficiency”: I doubt you will save a mere picojoule by replacing a subtraction by a bitwise and. You must provide actual measurement data if you want to argue that the difference in energy consumption between subi and andi is at least measurable, let alone relevant in real life. Re “packing the byte into the assembly instruction”: this makes no sense. Semantically, character & byte(0x0F) means int(character) & int(byte(0x0F)), per the rules of the language. Practically, you get the same generated assembly whether you cast or not. – Edgar Bonet Sep 10 '20 at 20:42
  • 1
    What's your point? How is this relevant to the discussion? The same “packing” (called an “immediate” operand) applies to the subtraction instruction subi. And you get the same assembly instruction whether you use a cast to byte or not. – Edgar Bonet Sep 10 '20 at 21:37
  • 1
    @EdgarBonet, I just compiled the test in AVR gcc 9.2.0. It used lds r24,digit, ori r24,lo8(48) for the byte while it uses lds r24,int_digit, lds r25,int_digit+1, ori r25,3 for the int. So it, too, honours the typecasts. What compiler are you using that doesn't honour the typecasts? – tim Sep 11 '20 at 0:23

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.