Serial monitor prints ascii (instead of letters)(update: now prints gibberish)

Hi there,

I want to send a String type var to the serial monitor that represents an input from the monitor.
Problem is, I'm getting the ascii number of each letter (not the letter itself).

Using the following program:

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

void loop() {
  if (Serial.available() > 0)
  {
    _command = Serial.read();
    Serial.print(_command);
  }
  //delay(1000);
}

for the input:

@0A 5000,900

the output is:

6448653253484848445748481310

Tried to convert it to char array, still, only numbers come out.
What am I doing wrong here? is it a settings issue?

Thanks.

_command should be declared a char.

DKWatson:
_command should be declared a char.

Alright, tried it with char array:

char _command[12];

void setup() {
  // put your setup code here, to run once:
  Serial.begin(9600);
  
}
void loop() {
  // put your main code here, to run repeatedly:
  if (Serial.available() > 0)
  {
    for(int i=0; i<12;i++)
    {
    _command[i] = Serial.read();
    Serial.println(_command[i]);
    }
  }
}

now I get gibberish (question marks)

Edit: The reason for the array is so I can manipulate and analyze the input.

Edit: The reason for the array is so I can manipulate and analyze the input.

The reason for the array is so that you can fill it WHEN THERE IS DATA AVAILABLE, NOT ALL AT ONCE.

You are waiting for at least one byte to arrive, and then assuming that that means that you can read all 12 of them. YOU CAN NOT READ DATA THAT HAS NOT ARRIVED.

Robin2 spent a lot of time writing up how to read serial data properly. Because you bulldozed off the dock without a clue how to swim, YOU get to find his post called Serial Input Basics - Updated.

Who said anything about an array? What are you reading into the array? Serial.available() will be non-zero as soon as it receives one character, then you immediately want to fill a 12 character array. With what? Walk before you run. And do a bit of home school. At least look through the Arduino language reference to see what the functions do. At the top of this page you see a drop down menu named RESOURCES, use it please.

As Paul said, you are testing whether one character is available and reading 12 whether or not 12 are available

Have a look at Serial input basics - updated

UKHeliBob:
As Paul said, you are testing whether one character is available and reading 12 whether or not 12 are available

Have a look at Serial input basics - updated

well this is easily solvable with putting a delay in the software. this is not what worries me.
what worries me is that at the end of the input, there's gibberish that I don't know where it comes from:

char _command[12];
void assaign()
{
  for (int i = 0; i < 12; i++) {
    _command[i] = Serial.read();
    Serial.println(_command[i]);
    delay(100);
  }
  Serial.println("finished printing");
}
void loop() {
  // put your main code here, to run repeatedly:
  if (Serial.available() > 0)
  {
    Serial.println("Starting printing");
    assaign();
    delay(1000);
    Serial.print(_command);
  }
  Serial.println("waiting");
  delay(5000);
  Serial.println("done waiting");
}

output:

waiting
done waiting
13:02:32.758 -> Starting printing
13:02:32.796 -> @
0
A

5
0
0
0
,
9
0
0
finished printing
@0A 5000,90 waiting
done waiting
13:02:39.982 -> Starting printing
13:02:39.982 ->

13:02:40.056 ->










finished printing

13:02:42.139 -> ⸮⸮⸮⸮⸮⸮⸮⸮⸮c@8waiting

well this is easily solvable with putting a delay in the software.

Make sure that you wait long enough. Two weeks should be enough.

A delay() is absolutely stupid as a solution.

Please post the complete program that produces the output in post #6

What have you got as the line ending in the Serial monitor, assuming that is where the input is coming from ?

UKHeliBob:
Please post the complete program that produces the output in post #6

What have you got as the line ending in the Serial monitor, assuming that is where the input is coming from ?

Please excuse me for such late answer.
Code:

char _command[12];
void assaign()
{
  for (int i = 0; i < 12; i++) {
    _command[i] = Serial.read();
    Serial.println(_command[i]);
    delay(100);
  }
  Serial.println("finished printing");
}
void setup() {
  Serial.begin(9600);

}

void loop() {
  if (Serial.available() > 0)
  {
    Serial.println("Starting printing");
    assaign();
    delay(1000);
    Serial.print(_command);
  }
  Serial.println("waiting");
  delay(5000);
  Serial.println("done waiting");
}

input:

@0A 5000,900

output:

13:02:32.758 -> Starting printing
13:02:32.796 -> @
0
A

5
0
0
0
,
9
0
0
finished printing
@0A 5000,90 waiting
done waiting
13:02:39.982 -> Starting printing
13:02:39.982 ->

13:02:40.056 ->










finished printing

13:02:42.139 -> ⸮⸮⸮⸮⸮⸮⸮⸮⸮c@8waiting

You can see that there is another iteration, as if the data is sent twice.
For the second time, though, for some reason gibberish is what I get.

PaulS:
Make sure that you wait long enough. Two weeks should be enough.

A delay() is absolutely stupid as a solution.

Please guys, you have no clue what my intentions are for this piece of code
nor what is the bigger scheme here. Maybe I don't mind waiting 2 weeks for the
data to arrive? Maybe for now I'm trying to focus on the problem at hand, and then
I'll go ahead and try to do it more 'efficiently'. Maybe I don't need to care for efficiency at all
in this project. But how can you know? you guys never bothered to ask, and yet you show
such strong opinions and amazing sarcasm.

As previously pointed out, your code reads 12 characters after checking that at least one is available. Either read 1 when 1 is available and put it in the array until you have inserted 12 characters or read 12 characters when 12 are available and put them in the array.

The _command array has room for 12 characters but in order to print it there needs to be room for the termination '/0' of the string and you need to put it in the array.

UKHeliBob:
As previously pointed out, your code reads 12 characters after checking that at least one is available. Either read 1 when 1 is available and put it in the array until you have inserted 12 characters or read 12 characters when 12 are available and put them in the array.

The _command array has room for 12 characters but in order to print it there needs to be room for the termination '/0' of the string and you need to put it in the array.

Thank you, I'll look for it when I'm near the Arduino again

It looks like you are sending 13 characters when the line ending is included. The first 12 characters display correctly and the remaining one becomes the first of the next 12. Since you don't wait for all 12 to arrive before reading, most of what you get from .read() is -1 (0xFFFF) meaning "No character in buffer".

Do you ever want to receive a message that was not exactly 12 characters long?

Try this. It waits for 12 characters to arrive and then shows them in HEX and ascii.

char _command[13];  // You need room for the mandatory NULL terminator.


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


void loop()
{
  if (Serial.available() > 11)  // Wait for at least 12 characters to arrive
  {
    Serial.println("Starting printing");
    for (int i = 0; i < 12; i++)
    {
      _command[i] = Serial.read();
      Serial.print("0x");
      Serial.print((int) ((byte) _command[i]), HEX);
      Serial.print(": ");
      Serial.println(_command[i]);
      // delay(100);  // Not needed since we know al 12 have arrived.
    }
    Serial.println("finished printing");
    delay(1000);
    _command[12] = '\0';  // Mandatory NULL to treat the array as a string.
    Serial.println(_command);
  }
  Serial.println("waiting");
  delay(5000);
  Serial.println("done waiting");
}

johnwasser:
It looks like you are sending 13 characters when the line ending is included. The first 12 characters display correctly and the remaining one becomes the first of the next 12. Since you don't wait for all 12 to arrive before reading, most of what you get from .read() is -1 (0xFFFF) meaning "No character in buffer".

Do you ever want to receive a message that was not exactly 12 characters long?

Try this. It waits for 12 characters to arrive and then shows them in HEX and ascii.

char _command[13];  // You need room for the mandatory NULL terminator.

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

void loop()
{
 if (Serial.available() > 11)  // Wait for at least 12 characters to arrive
 {
   Serial.println("Starting printing");
   for (int i = 0; i < 12; i++)
   {
     _command[i] = Serial.read();
     Serial.print("0x");
     Serial.print((int) ((byte) _command[i]), HEX);
     Serial.print(": ");
     Serial.println(_command[i]);
     // delay(100);  // Not needed since we know al 12 have arrived.
   }
   Serial.println("finished printing");
   delay(1000);
   _command[12] = '\0';  // Mandatory NULL to treat the array as a string.
   Serial.println(_command);
 }
 Serial.println("waiting");
 delay(5000);
 Serial.println("done waiting");
}

Hi, thanks for the descriptive reply.
I'm receiving a different, pre-set commands lengths. To handle this, I can switch-case on Serial.available() so I'm not worried, and can send the data to different parsers functions.

I tried your code, and tried to notice what @UKHeliBob said about inserting the data
only after all 12 characters have arrived, yet if I send the same command twice I get a weird result:

waiting
done waiting
09:28:01.652 -> Starting printing
09:28:01.652 -> 0x40: @
09:28:01.687 -> 0x30: 0
09:28:01.687 -> 0x41: A
09:28:01.687 -> 0x20:
09:28:01.687 -> 0x35: 5
09:28:01.722 -> 0x30: 0
09:28:01.722 -> 0x30: 0
09:28:01.722 -> 0x30: 0
09:28:01.722 -> 0x2C: ,
09:28:01.757 -> 0x39: 9
09:28:01.757 -> 0x30: 0
09:28:01.757 -> 0x30: 0
09:28:01.757 -> finished printing
@0A 5000,900
09:28:02.730 -> waiting
done waiting
09:28:07.738 -> Starting printing
09:28:07.773 -> 0xD:

09:28:07.773 -> 0xA:
09:28:07.773 ->
09:28:07.773 -> 0x40: @
09:28:07.773 -> 0x30: 0
09:28:07.807 -> 0x41: A
09:28:07.807 -> 0x20:
09:28:07.807 -> 0x35: 5
09:28:07.842 -> 0x30: 0
09:28:07.842 -> 0x30: 0
09:28:07.842 -> 0x30: 0
09:28:07.842 -> 0x2C: ,
09:28:07.877 -> 0x39: 9
09:28:07.877 -> finished printing

09:28:08.817 -> @0A 5000,9
09:28:08.852 -> waiting

As you can see, the output comes wrong after sending it twice in a row (meaning, sending 1 time, receiving 1 time, then sending again - not to confuse with sending '@0A 5000,900@0A 5000,900')

Does the arduino reset the buffer after all of the data arrived? or is there a command to reset it?

Thanks.

We need to see the code that is producing the result you posted and also need to know exactly what is being sent

0xD is a carriage return and 0xA is a linefeed so it looks like the string of characters is terminated by them. So, if you read 12 characters then those 2 are still in the buffer next time you read from it.

No, the Arduino does not empty the buffer because it has no way of knowing that all of the required characters have been received. You can do it yourself by reading and discarding unwanted characters until no more are available or better still read and save each character until you get the "end of input" character(s) then process the received data.

UKHeliBob:
We need to see the code that is producing the result you posted and also need to know exactly what is being sent

0xD is a carriage return and 0xA is a linefeed so it looks like the string of characters is terminated by them. So, if you read 12 characters then those 2 are still in the buffer next time you read from it.

No, the Arduino does not empty the buffer because it has no way of knowing that all of the required characters have been received. You can do it yourself by reading and discarding unwanted characters until no more are available or better still read and save each character until you get the "end of input" character(s) then process the received data.

Hi,
as I mentioned I used for example the code @johnwasser provided:

char _command[13];  // You need room for the mandatory NULL terminator.


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


void loop()
{
  if (Serial.available() > 11)  // Wait for at least 12 characters to arrive
  {
    Serial.println("Starting printing");
    for (int i = 0; i < 12; i++)
    {
      _command[i] = Serial.read();
      Serial.print("0x");
      Serial.print((int) ((byte) _command[i]), HEX);
      Serial.print(": ");
      Serial.println(_command[i]);
      // delay(100);  // Not needed since we know al 12 have arrived.
    }
    Serial.println("finished printing");
    delay(1000);
    _command[12] = '\0';  // Mandatory NULL to treat the array as a string.
    Serial.println(_command);
  }
  Serial.println("waiting");
  delay(5000);
  Serial.println("done waiting");
}

Thanks for the elaborated answer! I'll make some kind of manager function for it.

UKHeliBob:
We need to see the code that is producing the result you posted and also need to know exactly what is being sent

0xD is a carriage return and 0xA is a linefeed so it looks like the string of characters is terminated by them. So, if you read 12 characters then those 2 are still in the buffer next time you read from it.

No, the Arduino does not empty the buffer because it has no way of knowing that all of the required characters have been received. You can do it yourself by reading and discarding unwanted characters until no more are available or better still read and save each character until you get the "end of input" character(s) then process the received data.

Thanks very much for the tip! works like a charm.