Hi all,
I try to use serialEvent() and Serial.readBytesUntil() functions to catch-up commands from the user. But i believe that avr serial port register is left dirty when i am exiting from the serialEvent(). Documentationhttp://arduino.cc/en/Reference/SerialEvent says to to use Serial.read() to capture data from the register, so is it big no no to use Serial.readBytesUntil()? I tried to use Serial.flush() but it doesn't help. What is the right way to do this?
Here is the code:
#include <string.h>
#define MAX 64 // Arduino can hold up to 64 bytes
char buf[MAX];
char pr[MAX];
void setup()
{
Serial.begin(115200);
Serial.setTimeout(10000);
Serial.println("Arduino up and running");
}
void serialEvent(){
strcpy(buf, ""); /* Clear the buffer */
/* read the serial rx buffer to global variable */
if(Serial.readBytesUntil('\n\r',buf, MAX) == 0){ */
Serial.println("No valid data found");
}}
void loop()
{
if(strlen(buf) > 0){
Serial.println(strcpy(pr,buf));
Serial.println(strlen(buf));
strcpy(buf, "");
Serial.println(strlen(buf));
}
Serial.println("in main loop");
Serial.print(buf); Serial.print(" --- "); Serial.println(pr);
delay(3000);
}
reproduce the bug:
"duck" [enter]
"s" [enter]
And I got following output:
Arduino up and running
in main loop
---
in main loop
---
duck
4
0
in main loop
--- duck
in main loop
--- duck
suck
4
0
in main loop
--- suck
in main loop
--- suck
Why ? After all, implementing serialEvent() is equivalent to write if (Serial.available() > 0) { ... }
The three dots are what would go into serialEvent().
I am sorry, I do not get the purpose of your code - even allowing for it to be a demo/test of a percieved error.
There are two ways of reading Serial data.
The first is to occasionally call Serial.available(), and call Serial.read() to handle the character if it has arrived. If the Serial managed to receive 3 characters between your calling Serial.available() then the 2nd and 3rd byte will still be there on your next check & read call. If you expected 5 bytes, and only 3 arrived .. do something else until calling available again to see if they have arrived.
The other way, is the Serial.event(), which looks to me like an interrupt routine. (Admittedly never used it - never had a need) As it gets called (interrupting what your program was doing) immediatly after a byte is received, there will only be ONE byte to read. Doing Serial.readBytesUntil is going to confuse/break everything.
Unless you are truly confident/knowledgeble with handling interrupts, then stick with the above polling technique.
I have never heard of the AVR serial "getting dirty". And no, you have not discovered a new an exquiste subtle bug.
just puts a '\0' in the first position of the buffer.
Serial.readBytesUntil('\n\r',buf, MAX);
reads the 's' and puts it in the first position of the buffer. IT DOES NOT ADD A NULL TERMINATOR. If you want the string to end after the 's' you have to put in your own terminator.
int length = Serial.readBytesUntil('\n',buf, MAX);
if (length > 0)
buff[length] = '\0';
else
Serial.println("No valid data found");
tuxduino:
Why ? After all, implementing serialEvent() is equivalent to write if (Serial.available() > 0) { ... }
The three dots are what would go into serialEvent().
I think it's just obscure. Why not make it explicit?
void loop ()
{
if (Serial.available ())
processOneByte ();
// other stuff
}
Then the OP starts making the serialEvent call wait for more than one character, which hides the fact that s/he has blocked what loop is doing.
And we get this confusion:
But i believe that avr serial port register is left dirty when i am exiting from the serialEvent().
indeed, this is the case! And also realized that is not very efficient to wait '\n' inside interrupt handler. so maybe i re-think this little further when get some sleep....
thanks all
/mikko/
johnwasser:
Your problem is that:
strcpy(buff, "");
just puts a '\0' in the first position of the buffer.