Serial read function

Hello,

When I send a any character over the serial port, the "Serial.read()" function return the sent character and some empty value. The following code print back the first sent character over the serial port. Example, if you send the character "a", some times it will print the "a" character and some times an empty value.

How can I fix that?

Code:

const int buff_size = 20;
char buffer[buff_size];

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

void loop(){
int index = 0;

while(Serial.available()){
int inchar = Serial.read();
buffer[index] = inchar;
index++;

}

Serial.println(buffer[0]);

delay(2);
}

It sounds like you are appending carriage return and/or newline to what you are sending. Check the line ending dropdown in the serial monitor.

Only printing buffer when you have received something would be a useful change to make, too.

There is no such thing as an empty value. Every value has a value.

Try printing the numeric representation of the characters along with the characters themselves to see what the extra values are and provide a hint as to where they are coming from.

Hello,

I tried on windows and the problem didn´t happen. I´ll check the carriage return configuration on the arduino terminal. Thank you very much for your help, I appreciate it.

Elimeléc

It shows up better when you use code tags. Sorry, the IDE still hasn’t caught up with that.
If you Quote this, you will see the code tags in the edit window.
The # button over the window will generate a set of code tags, less typing.

Also get used to using Tools->Auto Format Ctrl-T
Use it often as you write and you will save on balancing parenthesis.
Putting all parenthesis on the same level makes them easier to check.

Use spaces to make code easier to read, it will save on eyestrain.

What happens is that Serial data arrives slower than the Serial.available() loop runs so next char not there yet becomes “all done, time to print”.

Serial.println( buffer[ 0 ] ); only prints the char in [ 0 ]

Ahhhh, WTH, it’s easier to code than to explain using English (illogical talky-language).

What’s missing below is the PROGMEM F macro to save RAM on that first print, sorry but I’m not used to it yet. Someone please?

const byte buff_size = 20; // int uses 2 bytes, don't practice wasting RAM
char buffer[ buff_size ];

byte  state = 0; // 0 is ready for data, 1 is entry finished
byte  index = 0; // saves allocating over and over

void setup()
{
  Serial.begin( 9600 );
  Serial.println( "Serial capture and print.\n" ); // so you know it's working
}


void loop()
{
  switch ( state )
  {
  case 0 :

    while( Serial.available())
    {
      char inchar = Serial.read(); 

      if (( inchar == 13 ) || ( inchar == 10 ))
      {
        state = 1; // end of line detected, do not add to buffer
      }
      else
      {
        buffer[ index ] = inchar;
        index++;

        if ( index == buff_size )
        {
          state = 1; // always leave the last char of buffer == 0
        }
      }
    }
    break;

  case 1 :

    if ( strlen( buffer ))
    {
      Serial.println( buffer ); // buffer is a pointer to buffer[]

      for ( index = 0; index < buff_size; index++ ) // clear the buffer
      {
        buffer[ index ] = 0;
      }
    }

    state = index = 0; // reset index and go back to read mode

    //      delay( 2 ); // you don't need this

    break;
  }

}

Hello, GoforSmoke

Thank you very much for your advice to prevent eye strain and making easy to read code, and most of all for your time.
What I’m writing is a NMEA checksum calculator, for some reason the code is working on the arduino simulator from virtronics, but not on the arduino uno board, here is my code:

Note: The square symbol shown in the for loop is: " tmp = tmp ^ buffer[ x]; ".

String buffer;

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

void loop(){

while(Serial.available() > 0){
char temp = Serial.read();
buffer += temp;
}

int start_with = buffer.indexOf(’$’);
int end_with = buffer.indexOf(’*’);
end_with–;
int cs;

char tmp = buffer[start_with];

for (int x=start_with+1; x<end_with; x++){
tmp = tmp ^ buffer;
cs = tmp;
}

Serial.print("CS = ");
Serial.println(cs,HEX);

buffer = “”;

}

You’ve -got- to stop using the IDE copy for forum edit tool; it’s crap, it makes a mess that doesn’t read right.

Instead make code tags using the edit window # button right above the smileys then highlight the code in the IDE and simply use plain old copy then paste that between the code tags.

If you Quote my post, you will see code tags, not the quote tags the broken copy for forum mess puts in. THEN we can see all of your code properly.

<=== these are CODE TAGS ===>

For one thing, I don’t use String in AVR code (Most Arduino uses AVR chips) or PC code for that matter. It’s a wasteful indirect way to handle what C char array strings (note the lower case s) do simply and directly. Those who don’t understand what’s inside their code use String.

This code suffers from the exact same problem as the other. What happens is that Serial data arrives slower than the Serial.available() loop runs so next char not there yet becomes “all done, time to print”.

I copied your code in the post above as well as I could and added 2 comments to show where just that one problem is. The code I gave before fixes that proper.

String buffer;

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


void loop(){


// This while loop below runs way faster than serial data arrives, it will exit early

  while(Serial.available() > 0){
    char temp = Serial.read();
    buffer += temp;
  }

// end of the way faster loop, please don't "fix" it by adding delays!


  int start_with = buffer.indexOf('

Do you want to checksum everything between $ and * or do you want the $ and * included in the checksum?

Big question. Have you taken the time to walk through how the code I posted works? How it goes from state 0 to state 1, and what each state does? If you are not learning then why am I trying?

);
  int end_with = buffer.indexOf(’*’);
  end_with–;
  int cs;

char tmp = buffer[start_with];

for (int x=start_with+1; x<end_with; x++){
    tmp = tmp ^ buffer

;

cs = tmp;
  }

Serial.print("CS = ");
  Serial.println(cs,HEX);

buffer = “”;

}


Do you want to checksum everything between $ and * or do you want the $ and * included in the checksum?

Big question. Have you taken the time to walk through how the code I posted works? How it goes from state 0 to state 1, and what each state does? If you are not learning then why am I trying?

When I send a any character over the serial port, the "Serial.read()" function return the sent character and some empty value.

The below "println" you used has an added carriage return and line feed added to the end of the string sent. The bottom "print" does not add the carriage return and line feed.

Serial.println(buffer[0]);
Serial.print(buffer[0]);

zoomkat:

When I send a any character over the serial port, the "Serial.read()" function return the sent character and some empty value.

The below "println" you used has an added carriage return and line feed added to the end of the string sent. The bottom "print" does not add the carriage return and line feed.

Serial.println(buffer[0]);
Serial.print(buffer[0]);

When you print buffer[0], you ONLY print the char in buffer[0], not the whole buffer.
Lose the [0] to print the whole buffer.

Hello,

Of course I went throughout your code and ran it. Now I will use "byte" instead of "int" for numbers less than 255. I'll also use code tags.

I want to XOR the characters between the "$" and "*".

Thank you very much for your help.

Elimeléc

zibetto:
Hello,

Of course I went throughout your code and ran it. Now I will use "byte" instead of "int" for numbers less than 255. I'll also use code tags.

Good. It will make helping easier.

I want to XOR the characters between the "$" and "*".

Thank you very much for your help.

Elimeléc

Not done yet. I just wonder how much I need to show.

The code I made, it has a part that reads the serial chars as they arrive. In that part you can check each one. So when the code sees '$' and sets a global or static variable so that the next char and the next right up to '*' will be used for CRC right then.

if ( Serial.read() == '$' )
{
doCRC = 1; // the flag is set
}

.....

if ( doCRC == 1 )
{
// do the XOR with inchar or a copy of inchar as if it is a buffer char
}

How does that seem to you? You can have the CRC done before the whole entry is read.

Hi,

Thank you very much for your help, now the code is fully operational.

//$GPRMC,023405.00,A,1827.23072,N,06958.07877,W,1.631,33.83,230613,,,A*42

const byte buff_size = 80;
char buffer[buff_size];
byte index = 0;
byte start_with = 0;
byte end_with = 0;
byte CRC = 0;
boolean data_end = false;

void setup(){

  Serial.begin(9600);
  Serial.println("Serial communication initialized");

}


void loop(){

  while (Serial.available() > 0){
    char inchar = Serial.read();
    buffer[index]  = inchar;

    if( inchar == '

){
      start_with = index;
    }

if(inchar == ‘*’){
      end_with = index;
    }

index++;

if(inchar == ‘\n’ || inchar == ‘\r’){
      index = 0;
      data_end = true;
    }
  }

if (data_end == true){
    for (byte x = start_with+1; x<end_with; x++){
      CRC = CRC ^ buffer ;
    }
  }

if(CRC > 0){
    Serial.println(CRC,HEX);
    CRC = 0;
    data_end = false;
  }

}