Serial.read() to string?

Carriage Return
Look at the options for line ending in the Serial Monitor.

I see it, I selected it, but how do I use it?

Set it to Carriage Return and test for '\r' in the incoming serial data or set it to Newline and test for '\n'

See http://www.gammon.com.au/forum/bbshowpost.php?bbsubject_id=11425&page=1

So after looking at that code I made some litle modfications to my and here it is:

char inData[20]; // Allocate some space for the string
char inChar; // Where to store the character read
byte index = 0; // Index into array; where to store the character
String reads;
int words = LOW;


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


void loop()
{
   while(Serial.available() > 0)
   {
       if(index < 19) // One less than the size of the array
       {
           inChar = Serial.read(); // Read a character
           inData[index] = inChar; // Store it
           index++; // Increment where to write next
           inData[index] = '\0'; // Null terminate the string
       }
       words = HIGH;
   }
   
   for(int i=0; i<=index && inChar=='\n'; i++)
       {
         reads += inData[i];
         inData[i] = 0;
       }
   
   delay(10);
   if(words && inChar=='\n')
   {
     Serial.println(reads);
     words = LOW;
     reads = "";
   }
   
   
   index = 0;
   
}

Now the first word is on the right place but the second gets again scattered.
How can I fix that?

You're reading the data into a string (a null terminated array of chars). Why are you then creating a String (a memory fragmenting object) out of what you read? Why not just print the char array?

Pseudo code:

if there is a character to read
  read it
  if the character is a newline
    do something with the string
    clear the buffer
    reset the index
  else
    put the character into the buffer
    increment the index
    null terminate the buffer
  end if
end if

The idea of using a terminating character is, that while there is at least one character available you read it and, if it is not the terminator and you have not read as many characters as the target array will hold, you put it in the array, advance the index, put in the '\0' and read the next character then do the same thing again. When you get the terminating character or have read the maximum number of characters then you print the string in the target array.

There is no need to move what you have read into the target array (a C style, null terminated string, lowercase s) to a String (uppercase S) before you print it.

I moved it into a String object because I want to use functions that only strings have like reads.indexOf() or things like that.

pedroply:
I moved it into a String object because I want to use functions that only strings have like reads.indexOf() or things like that.

Don't.
There is a problem with the memory allocation and strings on the compiler used for the arduino. All those functions can be done by hand if you want.

OK, if you must, you must, but the same principle will apply. Read the string until it is complete, then copy it to the String.

What version of the IDE are you using ? The problems with Strings are supposedly fixed in 1.0.4 but, as Mike says, avoid Strings if you can.

I am using version 1.0.3 but I will update now and see what happens.
....
Nop, the same erro.

Grumpy_Mike:
All those functions can be done by hand if you want.

Not too difficult either (untested):

int char_indexOf(char *toSearch, char *toFind)
{
  int index = 0;
  while (toSearch[index] != '\0')
  {
    if (strncmp(toSearch+index, toFind, strlen(toFind)) == 0)
      return index;
    index++;
  }
  return -1;
}

pedroply:
I am using version 1.0.3 but I will update now and see what happens.
....
Nop, the same erro.

This is because the error is yours not the compiler's.

Might I suggest that you print stuff intelligently?

Serial.print("reads: [");
Serial.print(reads);
Serial.println("]");

will convey a LOT more information than

Serial.println(reads);

It just might even provide a clue or two.

Insulting and irrelevant replies removed.

  • moderator

Sorry for not being able to reply earlier but I have made some improvements :

This is because the error is yours not the compiler's.

I already suspected that

PaulS:
Might I suggest that you print stuff intelligently?

Serial.print("reads: [");

Serial.print(reads);
Serial.println("]");




will convey a LOT more information than 



Serial.println(reads);




It just might even provide a clue or two.

I already suspected that the problem was in the string, more precisely at the point of converting the char into the string and I made this little modification:

if(index < 19 && inChar!='\n') // One less than the size of the array -/ added the  "&& inChar!='\n'" so that it stops when it reages the last char.
       {
           inChar = Serial.read(); // Read a character
           inData[index] = inChar; // Store it
           index++; // Increment where to write next
           inData[index] = '\0'; // Null terminate the string
       }

But it wouldnt work becouse at the first time the code is running, the inChar is nothing so here is my last code:

char inData[50]; // Allocate some space for the string
char inChar = 'c'; // Where to store the character read
byte index = 0; // Index into array; where to store the character
String reads;
int words = LOW;


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


void loop()
{
   while(Serial.available() > 0)
   {
       if(index < 49 && inChar!='\n') // One less than the size of the array
       {
           inChar = Serial.read(); // Read a character
           inData[index] = inChar; // Store it
           index++; // Increment where to write next
           //inData[index] = '\0'; // Null terminate the string
       }
       words = HIGH;
   }
   
   for(int i=0; i<=index && inChar=='\n' && inData[i]!='\n'; i++)
       {
         reads += inData[i];
         inData[i] = 0;
       }
   
   delay(10);
   if(words && inChar=='\n')
   {
     Serial.print("reads: [");
     Serial.print(reads);
     Serial.println("]");
     words = LOW;
     reads = "";
   }
   
   
   index = 0;
   inChar = 'c'; // make it so that it is different from '\n' 
}

It got some errors like you type "test" and it only returns "est" or "arduino" and it returns "duino" but it works.

So the question then becomes, why are you testing the value of inChar before reading it?

Because if I don't test its value when the word I send finishes, it continues to add blank spaces to the string.

pedroply:
Because if I don't test its value when the word I send finishes, it continues to add blank spaces to the string.

What does that have to do with testing the value of a char before reading it? I'm not saying don't test the value, I'm saying read the value before you test it.

You really should restructure your code. The whole deal you are doing with the words variable is predicated on all of the information arriving within a single iteration of the loop, and is a workaround to avoid writing non blocking code. Look at the psuedo code I posted earlier; no need for a delay(), and less coding.

pedroply:
I moved it into a String object because I want to use functions that only strings have like reads.indexOf() or things like that.

It is easy.

// zoomkat 8-6-10 serial I/O string test
// type a string in serial monitor. then send or enter
// for IDE 0019 and later

int ledPin = 13;
String readString;

void setup() {
  Serial.begin(9600);
  pinMode(ledPin, OUTPUT); 
  Serial.println("serial on/off test 0021"); // so I can keep track
}

void loop() {

  while (Serial.available()) {
    delay(3);  
    char c = Serial.read();
    readString += c; 
  }

  if (readString.length() >0) {
    Serial.println(readString);

    if(readString.indexOf("on") >=0)
    {
      digitalWrite(ledPin, HIGH);
    }

    if(readString.indexOf("off") >=0)
    {
      digitalWrite(ledPin, LOW);
    }

    readString="";
  } 
}

Actually, the X3J11 C Standard says each compiler vendor is free to define the null termination character however they wish, as the committee envisioned systems in the future where some value other than 0 may be more efficient or appropriate. While I don't know of any compiler that doesn't allow 0 to be used for null, the better form that everyone recognizes is:

inData[index] = '\0';

as adding a null terminator to the inData[] array. However, a more portable way is:

inData[index] = NULL;

The Arduino compiler does recognize NULL, plus I think it makes any code a tad more readable. (Any compiler that supports the C Standard should have NULL defined.) I know...picky...picky...picky, but read through some of the other software posts and see how many errors would jump from the page if they simply used good formatting style and symbolic constants.