Go Down

Topic: Serial.read() to string? (Read 2267 times) previous topic - next topic

pedroply

So I decided to make some more advance "talking" with my arduino and I found a piece of code which I transform into this:

Code: [Select]

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; i++)
       {
         reads += inData[i];
         inData[i] = 0;
       }
   
   delay(10);
   if(words)
   {
     Serial.println(reads);
     words = LOW;
     reads = "";
   }
   
   
   index = 0;
   
}



the thing is that in the serial monitor the words that I wrote and send to the arduino get all scattered on the serial monitor separated by spaces like this:
                   test                                 test
test                              test                     t
est
something like that, how can I make it so that they come like:
test
test
test
...
???

Thanks

Grumpy_Mike

You need to wait for the string to finish by detecting a string terminated like a CR.
Only when the string is all in should you attempt to print it out.
You are thinking that if one byte of the string has arrive then they all have. They have not.

pedroply

Thanks for replying,
I understand the logic, but what is a CR?

UKHeliBob

Carriage Return
Look at the options for line ending in the Serial Monitor.
Please do not send me PMs asking for help.  Post in the forum then everyone will benefit from seeing the questions and answers.

pedroply

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

UKHeliBob

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
Please do not send me PMs asking for help.  Post in the forum then everyone will benefit from seeing the questions and answers.

pedroply

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

Code: [Select]

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?

Arrch

#7
Apr 17, 2013, 10:46 pm Last Edit: Apr 17, 2013, 10:48 pm by Arrch Reason: 1
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:

Code: [Select]
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

UKHeliBob

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.
Please do not send me PMs asking for help.  Post in the forum then everyone will benefit from seeing the questions and answers.

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.

Grumpy_Mike


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.

UKHeliBob

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.
Please do not send me PMs asking for help.  Post in the forum then everyone will benefit from seeing the questions and answers.

pedroply

#12
Apr 17, 2013, 11:04 pm Last Edit: Apr 17, 2013, 11:13 pm by pedroply Reason: 1
I am using version 1.0.3 but I will update now and see what happens.
....
Nop, the same erro.

Arrch

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


Not too difficult either (untested):

Code: [Select]
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;
}

Grumpy_Mike


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.

Go Up