Serial Port problem (inappropriate serial Output)

Hi!

I had written some codes to change a GPS u-blox 7 NEO settings! But I would like firstly to check whether I can create the vital sentence at serial port. So I wrote some codes. But there are some unexpected outputs in serial port.
check the codes please:

void loop() {
  if (Serial.available()) {
    int inByte = Serial.read();
    char payload[]= { 0xF0 , 0x03, 0 ,0 ,0 , 0, 0, 1};
    if (inByte==49){ //49 = ascii for 1! When I  send 1 to the arduino by serial port
     for (int i=0; i<8; i++){Serial.println(payload[i], HEX);}
    }
  }
}

as you can see by this code I would like the arduino print the payload variable in the serial port with HEX format but look at the output of the serial port

FFFFFFF0
3
0
0
0
0
0
1

the 6 Fs in the beginning of the output are extra! I do not know how they come and from where!

what is wrong here?

I don't know what is causing the "Fs"but this:

  if (inByte==49){ //46 = ascii for 1!  When I  send 1 to the arduino by serial port
 46 = ascii for 1!

FYI,
49 dec may be "1" but 46 decimal is "."

raschemmel:
I don't know what is causing the "Fs"but this:

  if (inByte==49){ //46 = ascii for 1!  When I  send 1 to the arduino by serial port
 46 = ascii for 1!

FYI,
49 dec may be "1" but 46 decimal is "."

this was my mistake in just comments. as you can see in the if statement it is correct!

Yes, I can read. I said it isn't related to your issue. I just thought you might want your comments to be correct.

Good way is to clean buffer before you are starting to use it - read all from serial port untill it si empty at first.

Budvar10:
Good way is to clean buffer before you are starting to use it - read all from serial port untill it si empty at first.

How do you do that on Arduino UNO?

when I change the char to int for the variable payload. it works well. why?

Oh yes, the problem is caused by 0xF0 constant conversion to unsigned long size of first argument of function println - it is fullfilled by FF. In case of int, the value is 0x00F0 and also different overloaded function println(int,int) is used.

Budvar10:
Oh yes, the problem is caused by 0xF0 constant conversion to unsigned long size of first argument of function println - it is fullfilled by FF. In case of int, the value is 0x00F0 and also different overloaded function println(int,int) is used.

actually I did not understand your point about char and conversions. and why FFFFF?

The function Serial.println(payload*, HEX) is translated by different way in dependance on type of variables in argument.*
If you look at Print.h and Print.cpp in Arduino core, there is several definitions of println. If payload is char - println(long,int) is used
and 0xF0 constant is aligned to long value 0xFFFFFFF0 and if payload is int (it means the fist value is 0x00F0) and println(int,int) is used instead.

It looks like a bug in the Println function. It works properly if you use define payload as byte rather than char.

The problem seems to arise with any char value greater than 127 DEC.

void setup()
{
  Serial.begin(9600);
  Serial.println("Starting");

  char payload[]= { 0x06, 0x79 , 0x80, 0 ,0 ,0 , 0, 1};

  for (byte i=0; i<8; i++){Serial.println(payload[i], HEX);}
  for (byte i=0; i<8; i++){Serial.println(payload[i], DEC);}

}

void loop() {
}

...R

Yes, I just append that it is because println(unsigned char, int) is defined but println(char, int) not.

Budvar10:
Yes, I just append that it is because println(unsigned char, int) is defined but println(char, int) not.

Why does that make the HEX output prepend all the Fs?

The DEC output works fine.

...R

It is deeper in lib code, to simplyfy: number is printed without leading zeros. Printig works digit by digit using division and modulo of number until zero of multiply division is obtained. See printNumber function in Print.cpp.

I think the answer lies in the way that negative numbers are represented in long and unsigned long variables.

0x82 represents 130 as an unsigned char or a byte but -126 as a char (which is a signed char).

When a char (which is treated by the compiler as a signed char = -126) is converted to a long (or unsigned long) it is stored as FFFFFF82

So ... not a bug but a feature :slight_smile:

Maybe we should generally be using unsigned char because it doesn't make much sense to me to consider a char has having a sign.

...R

The problem is not in negative or positive value but in variable type. For type char if you are calling println function there
is not defined function println(char,int) exactly, then compiler takes println(long,int).
Try this:

void setup()
{
  Serial.begin(9600);
  Serial.println("Starting");

  char payload[]= { 0x06, 0x79 , 0x80, 0 ,0 ,0 , 0, 1};

  for (byte i=0; i<8; i++){
      Serial.println(payload[i], HEX);
      Serial.println((unsigned char)payload[i], HEX);
   }

}

void loop() {
}

It seems as the same function call twice, but no. Fist is called version println(long, int) and second is called version println(unsigned char,int). Then, each negative value of char will be printed with many Fs in first call.
The solution should be also to add definition for println(char,int) into Print class.

Budvar10:
is not defined function println(char,int) exactly, then compiler takes println(long,int).

I understand that. However the "problem" arises from the way the compiler translates a char with a value above 127 into a long. It does not create a long with the same signed value as the char has.

I agree that a special println(char, int) could be written to deal with the situation.

However (and this shows my wish to have as little as possible to do with C/C++) it seems weird that the compiler actually has such a thing as a "signed" char. When would one ever use that?

...R

When you are using a char as a small int.

I think signed chars came along later. I think it is because the C committee wanted things to be symmetric. It is the same reason they added the unary '+' along with the unary '-'.

KeithRB:
When you are using a char as a small int.

Don't you use a byte for that?

...R

Originally, there was no 'byte' type. You had chars and ints.