Serial communications

I have a very simple program that appears to be able to do magic!

The full program is as follows;

I want to send commands to the audrino to control a stepper motor, essential the command structure will be three character followed by a maximum of 5 numbers, all terminated with a semicolon.

The program below works except for the fact that when I print the command array magically I get the full command CCCNNNNN even though its only a 3 character array with terminator!!!

Try it for yourself, all explanations are welcomed?

char cbuffer[9] = {’ ‘,’ ‘,’ ‘,’ ‘,’ ‘,’ ‘,’ ‘,’ ‘,’ ‘};
char command[3] = {’ ‘,’ ‘,’ ‘};
char cnumber[6] = {’ ‘,’ ‘,’ ‘,’ ‘,’ ‘,’ '};

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

void loop()
{
int i = 0;
while ( Serial.available( ) > 0 )
{
byte serialByte = Serial.read();
//Serial.println(serialByte);
if(i <=8)
{
cbuffer = char(serialByte);

  • }*

  • i++;*

  • }*

  • delay(500);*

  • //Copy the first three characters into the command array*

  • for(int j = 0; j <3; j++) command[j] = cbuffer[j];*

  • for(int j = 3; j <9; j++)*

  • {*

  • if(cbuffer[j] != ‘;’)*

  • {*

  • cnumber[(j-3)] = cbuffer[j];*

  • }*

  • else*

  • {*

  • break;*

  • }*

  • }*

  • Serial.println(command);*

  • Serial.println(cnumber);*

  • // Clear the cbuffer after reading*

  • for(int j = 0; j <=8; j++) cbuffer[j] =’ ';*
    }

When you are using arrays of characters as strings, the arrays of characters need to be NULL terminated. Yours are not.

When a function that expects a string is given an array of characters that is not NULL terminated, it does not know that. Since it expects a NULL as the terminator, it keeps printing characters until it finds a NULL. If this NULL is not within the bounds of the array, the function does not know that, or care.

I do believe code should be posted using the code post button, looks like a crosshash :slight_smile:

Beside the null termination thing…
Serial read return a int not a byte. a byte(unsigned) is 0 to 255,int (signed) is -32,768 to 32,767

char cbuffer[9] = {' ',' ',' ',' ',' ',' ',' ',' ',' '};
char command[3] = {' ',' ',' '};
char cnumber[6] = {' ',' ',' ',' ',' ',' '};


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

void loop()
{
     int i = 0;
     while ( Serial.available( ) > 0 )
     {
           byte serialByte = Serial.read();
           //Serial.println(serialByte);
           if(i <=8)
           {
                 cbuffer[i] = char(serialByte);
           }
           i++;
     }
     
     delay(500);
     
     //Copy the first three characters into the command array
     for(int j = 0; j <3; j++) command[j] = cbuffer[j];
     
     for(int j = 3; j <9; j++)
     {
           if(cbuffer[j] != ';')
           {
                 cnumber[(j-3)] = cbuffer[j];
           }
           else
           {
                 break;
           }
     }
     Serial.println(command);
     Serial.println(cnumber);
     
     // Clear the cbuffer after reading
     for(int j = 0; j <=7; j++) cbuffer[j] =' ';
     cbuffer[8] ='\n';
}

try this one instead

char cbuffer[] = {' ',' ',' ',' ',' ',' ',' ',' ',' '}; 
char command[] = {' ',' ',' '};
char cnumber[] = {' ',' ',' ',' ',' ',' '};


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

void loop()
{
     int i = 0;
     while ( Serial.available( ) > 0 )
     {
           int serialByte = Serial.read();
           //Serial.println(serialByte);
           if(i < 8)
           {
                 cbuffer[i] = char(serialByte);
           }
           i++;
     }
     
     delay(500);
     
     //Copy the first three characters into the command array
     for(int j = 0; j <3; j++) command[j] = cbuffer[j];
     
     for(int j = 3; j <9; j++)
     {
           if(cbuffer[j] != ';')
           {
                 cnumber[(j-3)] = cbuffer[j];
           }
           else
           {
                 break;
           }
     }
     Serial.println(command);
     Serial.println(cnumber);
     
     // Clear the cbuffer after reading
     for(int j = 0; j <=7; j++) cbuffer[j] =' ';
     cbuffer[8] ='\n';
}

Serial.read() should return a byte, as that is how much data it removes from the serial buffer. But, because all possible values that fit in a byte are valid, there is no way to indicate that there was nothing to read in the serial buffer, should the serial buffer be empty.

So, the return type for Serial.read() needs to be something larger that can contain all possible legal values and one illegal value (-1) that is used to indicate that an error occurred.

As long as Serial.read() occurs only after a Serial.available() call, as in the original code, storing the return value in a byte is OK.

Since bytes and chars are the same size, there is no need to cast the byte to a char before storing the value in the char array. An implicit cast occurs, if the explicit cast is not performed, with exactly the same results. The code is easier to read with either proper casts, (char), or no casts, than it is with the cast function, char(), in my opinion.

Thanks for the reply's so far and sorry for not posting my code correctly.

The byte versus int doesn't matter since the program only reads the serial stream when bytes are available etc...

The NULL terminator of my arrays is still an issue as follows;

If I try to NULL terminate them '\0' the program will not compile at all so there are two possible conclusions;

  1. My char arrays are automatically NULL terminated?
  2. My char arrays do not begin with an index of 0?
char myword[] = { 'H', 'e', 'l', 'l', 'o', '\0' };
char mynewword[5] = { 'H', 'e', 'l', 'l', 'o', '\0' };

error: too many initializers for 'char [5]'

I know that double quoted string are NULL terminated but single quoted characters are not. In any case I'm still having trouble getting to the bottom of this inconsistency. :-/

Thanks for the input so far, best regards

If you do not provide a size for an array, the size of the array is computed from the number of initializers present. Since a NULL terminated array of characters does not need to be explicitly initialized, just use the explicit declaration form:

char cbuffer[10];
char command[4];
char cnumber[7];

In setup(), add:

cbuffer[0] = '\0';
command[0] = '\0';
cnumber[0] = '\0';

In loop, don't forget to add a NULL after every character added to cbuffer, command, and cnumber.

interesting, here what on the docs

Returns the first byte of incoming serial data available (or -1 if no data is available) - int