Arduino can't read Serial properly
Asked Answered
W

6

7

Alright, I've googled getting a string from Serial with Arduino and I've had no luck even copy and pasting examples.

I'm trying to get a string from the Serial. Here's my code:

void setup() {
    Serial.begin(9600);
    Serial.write("Power On");
}

void loop()
{
    while(!Serial.available());

    while (Serial.available() > 0) {
      Serial.write(Serial.read());
    }
    Serial.println();
}

And it's printing out character by character.

I also tried

char* read(int len) {
  while (!Serial.available());
  char str[len];
  int i = 0;
  while (i < len) {
    str[i] = '\0';
    int inByte = Serial.read();
    Serial.println(inByte);
    if (inByte == -1) {
        return str;
    } else {
      str[i++] = inByte;
    }
  }
  return str;
}

And it returns 1 character at a time (serial.print(inByte) gives -1 every other time). Why is the Serial splitting each character?

If I enter 'hello' and I call serial.read() it gives a character then says there's nothing, then gives another character and says there's nothing.

Workhouse answered 28/3, 2012 at 4:15 Comment(1)
Serial ports are very slow. You typically get just one byte at a time, then nothing for a while. You'll need to deal with that in your code, you are not doing so now.Eyla
W
12

I figured it out.

When you open a Serial with 9600 baud (Serial.begin(9600);), it's reading/writing at 9600 bytes per second. That means at fastest it can get just under 10 bytes per millisecond. I don't know what the operating speed is, but it seems like the Arduino gets alerted of and reads the first byte before the second one arrives. So, you must add a delay(1) to "wait" for another byte in the "same stream" to arrive.

String read() {
    while (!Serial.available()); //wait for user input
    //there is something in the buffer now
    String str = "";
    while (Serial.available()) {
        str += (char) Serial.read();
        delay(1); //wait for the next byte, if after this nothing has arrived it means the text was not part of the same stream entered by the user
    }
    return str;
}

You may ask, well since you're delaying how do you know if the user is just typing very fast? You can't avoid it here, since the Serial is essentially limited at a certain speed. However, the user must be typing virtually-impossibly-fast for two inputs to be confused as one.

Workhouse answered 27/7, 2012 at 0:48 Comment(0)
M
2

I don't have access to the Arduino source files here, but the following line of code won't give you a full String for obvious reasons (let me know if it's not that obvious):

int inByte = Serial.read();

Also, using

Serial.write()

you'll be sending byte per byte. That's the oposite from

Serial.println()

in which you'll be sending full sentences.

I would try working with Serial.print() or println() rather then Serial.write().

You can check out the references:

http://arduino.cc/en/Serial/Write

http://arduino.cc/en/Serial/Println

Mowbray answered 28/3, 2012 at 13:0 Comment(0)
H
1

Even though this post is old, I'll post my answer in case someone googles their way here.

For reading strings from the serial you can use the following:

String str;

while (Serial.available() > 0) {
    str = Serial.readString();
}

Works like a charm!

Hyperaemia answered 20/11, 2014 at 20:36 Comment(0)
A
0

It exists delay when transferring data via UART. Have a try with Serial.timedRead() instead. The code is as below.

void setup() {
    Serial.begin(9600);
    Serial.write("Power On");
}

void loop()
{
    while(!Serial.available());

    while (true) {
      int byte = Serial.timedRead();
      if(byte == -1)
         break;
      Serial.write(byte);
    }
    Serial.println();
}
Anglophile answered 10/6, 2012 at 9:17 Comment(0)
B
0

I wrote this simple Serial full message repeater. It does not require a String object or any kind of delaying as in previous answers.

How it works
It receives characters and stores them in buffer until terminating character \n or \0 is received. Then it prints the whole buffer back.

There is also implemented buffer overflow check, so you don't lose any data.

The main advantage of this solution is the speed and possibility to react to the message content even before the whole reading procedure is complete (for example, you can implement a message parser on top of this very easily).

#define LENGTH 20

void setup() {
  Serial.begin(9600);
  Serial.println("Ready to read");
}

void loop() {
  if (Serial.available()) {
    char buffer[LENGTH];
    int index = 0;
    bool receiving = true;
    
    while (receiving) {
      if (Serial.available()) {
        char ch = Serial.read();
        if (ch == '\n' || ch == '\0') {
          buffer[index] = '\0';
          receiving = false;
        } else {
          buffer[index++] = ch;
          if (index == LENGTH) {
            buffer[index] = '\0';
            break;
          }
        }
      }
    }

    Serial.println(buffer);
  }
}
Beltran answered 13/2, 2021 at 20:11 Comment(0)
K
-3
String str;

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

void loop ()
{
    while (Serial.available() > 0){
        char c = Serial.read();
        str.concat(c);
        if (Serial.available() == 0)
        {
            Serial.print(str);
            str = "";
            break;
        }
    }
}
Komsomolsk answered 19/2, 2015 at 7:17 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.