Noob question about serial communication

Hey,

I know it is seriously big noob question but i can't figured it out where my problem is.

My target is to get a string with serial communication an use it as a simple string. In some projects this works but now i want build a new one and this dosen't work well.

So i started with a easy code an now i am very confuesed :slight_smile:

 String input = "";
 char current ;
   
void setup() {
  
 Serial.begin(9600);
  while (!Serial) {
    ; // wait for serial port to connect. Needed for Leonardo only
  }
}

void loop() {
 
  while(Serial.available()){
  
  current = Serial.read();
  input = input + current;
  
  }
   
  if(input != ""){
  Serial.println(input);
   input == "";
  }
}

So thats the code not very impressive but impresive enough to confuse me :slight_smile:

I think if there is a serial communication the Arduino will stuck in the while loop until the transmission ends and put every received char at the end of the input char. After communication ends my if will check it and if there is a value in input it will send it back and clear it.

But the Arduino didn't stuck in the while loop and repeat the main loop everytime so input only hold one char at the time.

So i need help to understand where my problem is.

thx a lot

You need to understand that serial is slow - at 9600 that's only 960 characters per second.
That is an age to a 16MHz processor, so as soon as there are no characters that read, it exits the while loop.
Which is most of the time.

My target is to get a string with serial communication an use it as a simple string.

So, you start by creating a String. A String and a string are not the same thing. Not even close.

I think if there is a serial communication the Arduino will stuck in the while loop until the transmission ends and put every received char at the end of the input char.

True, but since serial data arrives slowly, but is read quickly, it won't be "stuck" in that while loop long.

After communication ends my if will check it and if there is a value in input it will send it back and clear it.

Yes.

But the Arduino didn't stuck in the while loop and repeat the main loop everytime so input only hold one char at the time.

Serial data arrives slowly. It is read quickly. There is nothing wrong with the code. There IS something wrong with your expectations.

If you want to read and store the data until some terminating marker arrives, you must change the code to NOT clear the String unless if contains the terminating marker. And, don't print it until then, either.

so you mean i should send an delimter to end the transmission instead of the Serial.available statement?

Shouldn't be necessary with delimiters and only makes things a whole lot more complex than they need to be, here, try this:

String input = "";
   
void setup() {
  
 Serial.begin(9600);
  while (!Serial) {
    ; // wait for serial port to connect. Needed for Leonardo only
  }
}

void loop() {
 
  while(Serial.available() > 0){ // While there is more to be read, keep reading
    input += (char)Serial.read();
    delay(1); // This is needed to prevent ... weirdness :) 
  }
  
 // TADA! Now, if there was a burst of characters on the port they are all
 // contained in your input string so you can now use that string in your code :) 
 
 // Your code can go here
   
  if(input != ""){
  Serial.println(input);
   input == "";
  }
  
}

Now in that code where I have put the comment // Your code can go here
you can put some conditional statements to do stuff with your string before the last part of your code sets the input string back to "" (deletes it) so an example of doing stuff might be...

// Your code can go here
  if(input == "hello") { 
    Serial.println("Hey, you said hello! so I'm saying hello back :)");
  }
delay(1); // This is needed to prevent ... weirdness :)

Might work with the serial monitor, won't work with a terminal emulator.
You may want to rethink, with delimiters.

If you mean that a terminal emulator sends one character at a time while you write then you are correct, this will just receive one character at a time, you could build up a string and do conditional testing on it but this code is designed to receive a complete string of text all at once.

I have a terminal emulation program for the PC that can send a complete string of text, you need to click on the 'Send' tab and then write something in one of the boxes then click on the Send ASCII button to send that string of text all at once.

http://BTInterface.com/RealTerm.zip

You'll need to set the correct Baud rate (9600) and port.

Hope this helps

ian

You'll need to set the correct Baud rate (9600) and por

Or you could write it properly, lose the delay and not care about the line speed.

I don't really understand what you mean by that.

If...you...write...the...code...properly, you...won't...need...the...delay...and...your...code...will....work...with...any...line-speed.

Is that any clearer?

If by 'clearer' you mean 'moronic' then yes.

You come with lots of snarky comments about how the code should be written 'properly' yet you don't actually provide any code.

How about you write a better one then we can all bask in your superior greatness.

yet you don't actually provide any code.

Not on this occasion, no, though I have in the past.
My recollection was that it produced less object code than the "equivalent" String-based solution, and didn't have any delays.
Next time I'm in front of a PC, I'll see if I can find it again.

Cool, my reference to setting the baud rate (to 9600) was for the terminal emulator program, there is a 'port' tab where you choose the port (which can incidentally be a bluetooth virtual serial port) and in my experience if you have the PC's port set to one baudrate and the Arduino's serial port set to another you get:

gobbledeygook

:slight_smile:

Very simple serial code that will echo what is sent from the serial monitor back to the serial monitor.

//zoomkat serial echo test 7-31-2011

char input; // incoming serial data

void setup() {
  Serial.begin(9600);	// set serial port at desired value
  Serial.println("serial echo test 0021"); // echo test
  Serial.println();
   }

void loop() {
  if (Serial.available() > 0) { // check for serial buffer input
    input = Serial.read(); // read the incoming byte:

    Serial.print(input); // print the input
    //Serial.println(); // print new line for better reading
    }
  }

Cool code zoomcat.
I find that it's always good to take it down to as simple as possible so that the user can understand it and get on and do something that works before they lose interest. They can always change it later if they need to.

In this case LordN1kon states that his objective is:

My target is to get a string with serial communication an use it as a simple string.

So he needs an array of chars, that'll be a String then :slight_smile:
Your nice'n easy code demonstrates how to receive each char as it comes through the serial port and from there it should be easy to build up a string which can then be used as he needs.

I think a String is an expensive proposition as far as memory goes though so it will be interesting to see AWOL's technique.

So he needs an array of chars, that'll be a String then

No, he needs a null-terminated character array - that'll be a string.

I took this String-based code from earlier in the thread and compiled it for a 2009

String input = "";
   
void setup() {
  
 Serial.begin(9600);
  while (!Serial) {
    ; // wait for serial port to connect. Needed for Leonardo only
  }
}

void loop() {
 
  while(Serial.available() > 0){ // While there is more to be read, keep reading
    input += (char)Serial.read();
    delay(1); // This is needed to prevent ... weirdness :) 
  }
  
 // TADA! Now, if there was a burst of characters on the port they are all
 // contained in your input string so you can now use that string in your code :) 
 
 // Your code can go here
   
  if(input != ""){
  Serial.println(input);
   input == "";
  }
  
}

, and got a code size of 3962 bytes (IDE 1.0.5)

I took this

const byte MAX_LEN = 40;
char inputSentence [MAX_LEN + 1];
byte inputIndex = 0;
bool newInput;

void setup ()
{
   Serial.begin (9600);
   while (!Serial) {
    ; // wait for serial port to connect. Needed for Leonardo only
  }
}

void loop ()
{
  if (newInput && strlen (inputSentence)) {
    Serial.println (inputSentence);
    newInput = false;
    inputIndex = 0;
    inputSentence [0] = '\0';
  }
}

void serialEvent ()
{
  while (Serial.available() ) {
    char readChar = Serial.read ();
    if (readChar == '\n') {
      newInput = true;
    } else {
      if (inputIndex < MAX_LEN) {
        inputSentence [inputIndex++] = readChar;
        inputSentence [inputIndex] = '\0';
      }
    }
  }
}

non-String, non-delaying, non-memory fragmenting, line-speed agnostic code and compiled it, and got a code size of 2030 bytes - very close to half the size.

Small effort, big saving.

This looks really interesting and the memory saving is most impressive.

Having a play with it now.

Thanks AWOL!