Convert Binary to ASCII? (But not for Serial...)

Ok- I apologize in advance if there is an obvious answer to this, but I haven't been able to find it yet.

I'm receiving a string from a Bluetooth Low Energy module. It sends it over (not via serial) in an ASCII code.

String GetStringFromBLE(){
unsigned char buf[16] = {
  0};
unsigned char len = 0;
while ( BLEMini.available())
  {
    receivedByte = BLEMini.read();    
    receivedChar = receivedByte;

    if (receivedChar != 0x0A)
    {
      if (len < 16) {
        buf[len++] = receivedChar;
      }
    } 
    else {
      
      for (int i = 0; i < len; i++){
        //SOMEHOW get each element of buf[] into a string (str)
      }
      
      return str;
   }
}

I can't figure out how to convert the ASCII code into it's proper string or char letter counterpart. (i.e. 104 should be 'h') I know that Serial.write() does this but I want it as a stored variable, not written to the serial. My gut is that this should be fairly simple but it seems to be escaping me. Thanks in advance for any advice or tips.

while ( BLEMini.available())

That isn't going to loop very many times.

Do you want you function to block?

If you've got a string, why would you want a String?

Have you looked at Nick Gammon's serial tutorial?

        //SOMEHOW get each element of buf[] into a string (str)

You already have the chars in the buf array and it is zero terminated. Is it not already a string ?

buf is not zero terminated, but with some simple code mods, it could be.

unsigned char buf[16] = {0};

Does this not set all elements of the array to zero ?

Nope.

What am I half remembering ? Are there any circumstances where all the elements of an array are initialised to zero in that way ? I am sure that I have seen mention of it.

A quick test shows that it seems to work but I appreciate that it may not be consistent behaviour. I am not sure how authoritative it is, but C++ Notes: Array Initialization seems to say that uninitalised elements of an array will be set to zero.

Sorry, I think you're correct - I thought it was only true of statics or globals.
OTOH, it's just as easy to zero terminate as you go along.

When you said 'Nope' I did wonder if it applied to special cases only. I agree, zero terminating as you add a character does seem more natural and is the obvious (and easy) thing to do.

Thank you both for your engagement!

I've read thru

per your suggestion, and I think(?) I understood most of it.

(I will definitely change my program so that I'm not trying to use 'blocking'.)

But I believe my question is slightly different. I'll see if I can explain it more clearly...

I'm getting an ASCII number instead of the actual character.

So if I send 'hello' over BLE to this code:

String GetStringFromBLE(){
unsigned char buf[16] = {0};
unsigned char len = 0;
while ( BLEMini.available())
  {
    receivedByte = BLEMini.read();    
    receivedChar = receivedByte;

    if (receivedChar != 0x0A)
    {
      if (len < 16) {
        buf[len++] = receivedChar;
      }
    } 
    else {
      
      for (int i = 0; i < len; i++){
        //SOMEHOW get each element of buf[] into a string (str)
        Serial.println(buf[i]);
      }
      
      return str;
   }
}

It will write:
104
101
108
108
111
13

rather than
h
e
l
l
o

I know that I could use Serial.write() instead of Serial.println(), but I'm not interested in writing it to the serial. I want to store it to a string var and be able to manipulate that string.

I hope I'm on the right line of inquiry and will review the Gammon tutorial again to see if there's something in there that I missed...

Thanks in advance for the help!

while ( BLEMini.available())
  {
    receivedByte = BLEMini.read();    
    receivedChar = receivedByte;

How are receivedByte and receivedChar defined? And, why the hell are they global? Get them into this function where they are used.

unsigned char buf[16] = {0};

Why unsigned?

Try making buf char, instead of unsigned char.

print converts the value it is given to an ascii string. write just writes it, as you already have the ascii you just need to write it.

Mark

print converts the value it is given to an ascii string.

Depends on what it is given. There are many print() methods.

OK print (as used by the OP) ...

Mark

crutchre:
I can't figure out how to convert the ASCII code into it's proper string or char letter counterpart. (i.e. 104 should be 'h') I know that Serial.write() does this but I want it as a stored variable, not written to the serial.

The question as stated doesn't make much sense and may imply that you've just understood what you're seeing.

When you store a character value in your code, it's stored as an ascii character code. If you type an 'h' character into the serial monitor and then read is from the serial port into a char variable, the value in the char variable is the number 104. If you then write the char value back to the serial port the IDE will receive a byte containing the number 104 and print the pattern of pixels that looks like 'h' on your screen.

If you receive an 'h' (ascii code 104) and do something with it which causes the string "104" to appear somewhere else then the problem is not with your character value, it's that the method you're using to output it is formatting the ascii character code as a decimal number before it displays it. That's a mistake in the way you're outputting the value, not a problem with the value itself.

PaulS - you called it. Specifying the char array (buf) as unsigned made it behave in a way that I didn't understand. Deleting the unsigned command solved it. (It was left over from some copied code).

Thank you everyone for the guidance and tips.

I'm certainly learning a lot as I go and appreciate the help.

It might be worth looking at the various classes you are using, to understand why singed char and unsigned char do not behave the same.

Serial is an instance of HardwareSerial, which derives from Stream, which derives from Print.

Print has several print() methods defined - one for (singed) char and one for unsigned char.

size_t Print::print(char c)
{
  return write(c);
}

size_t Print::print(unsigned char b, int base)
{
  return print((unsigned long) b, base);
}