Hi again.
I've got a very weird sync problem right now.
first I couldn't push the Serial.begin() above 38400 bauds (currently working limit)
I got all sorts of bogus chars from all the terminals I used if I try to push it further.
is that possible? I thought the upper limit was 115200...
has anyone pushed it so high?
is there something I should know/do in order to push it higher ?
second I've got some very weird behaviour with the serial sync:
When I do Serial.read()
I need to do a delay after it before performing another Serial.read()
or else I will record something weird, expecially if I'm repeatedely trasmitting long strings to Arduino and at a high pace.
The delay is performed either by a delayMicroseconds(200)
and/or by printing out Serial.print("some strings"); (which I imagine is just simply chewing off routine cycles to the cpu)
I have to say that this all happens because I'm performing a Serial.read() inside a double for loop, and storing the values coming from the serial buffer in a multidimensional array.
is this whole delay thing possibly right or am I guessing wrong?
is there a way to exactly compute the necessary delay between two Serial.read()? (I went trial and error, but if I change the data in the serial buffer or the serial speed I have to go through the hand process again);
ok here it is...
a simplified version but that still has the error
you should check it with a terminal software and rapidly send strings like
M10000000100000001000000010000000100
or
M11111111111111111111111111111111111
I get sync problems, so that sometimes when I read out the recorded chars I get bogus chars or a clutter of different chars together.
int totCols = 5;
int totRows = 7;
//set the string that will be received throughSerial
/*the string should start with an 'M' so that the code knows when it is starting
rows and columns notation
M 1000000
0100000
0010000
0001000
0000100
continous string notation: M10000000100000001000000010000000100
*/
char Matrix_string [5][7]; //putting [totCols][totRows] yelds a compiler error
void Matrix_serialRead () {
for (int c=0; c < totCols; c++) {
for (int r=0; r < totRows; r++) {
//store a char in the appropriate location
Matrix_string[c][r] = Serial.read();
//need a delay before next Serial.read(); - delay can be also a Serial routine
delayMicroseconds(200);
//WARNING - if you comment the following line it won't work
//this way it syncs right all led but flicker because it has to output the result
//Serial.print(Matrix_string[c][r]);
//Serial.print(" ");
}
}
Serial.println(" done SerialRead");
//prepare the serial buffer for the next string
Serial.flush();
}
//output the string
void Matrix_display() {
for (int c=0; c < totCols; c++) {
for (int r=0; r < totRows; r++) {
Serial.print(Matrix_string[c][r]);
Serial.print(" ")
}
}
Serial.println();
}
void setup() {
Serial.begin(38400); //can push it further up!!! why??
}
void loop () {
//*check for serial data
while (Serial.available()) {
byte s = Serial.read();
if(s == 'M') {
//I needed a delay here too...I discovered it by commenting the following Serial
//if you comment or even take out one or two chars out of the string
//the whole program is more likely to fail the syncronization
Serial.println("read: ");
//start of the protocol Matrix
Matrix_serialRead ();
}
}
//continously display it all
Matrix_display();
}
is there some particular thing I need to configure in order to push it to 115200???
I'm using the default port settings
data bits: 8
parity: none
stop bits: 1
I don't have an Arduino NG, I've got one of the first USBs with the Atmega8 and a 16Khz clock crystal
OK, now I think I see what the problem is. In loop() the code calls Serial.available() to see if at least one byte is ready in the serial input. Then it reads one byte:
byte s = Serial.read();
So far, so good. But then you have a problem because you call Matrix_serialRead(), which tries to read a whole bunch of bytes inside the for loops with:
Matrix_string
[r] = Serial.read();
The problem is that Serial.read() does NOT WAIT for serial data to be available. If a byte is not ready, it will immediately return -1. If you change the above line to the following, and take out all the other things you used for artificial delay, I bet it will work fine:
while (Serial.available() == 0) {
// do nothing... just wait for a byte to arrive
}
Matrix_string[c][r] = Serial.read();
You might even add the following utility function which will always wait for a byte to be available:
[code]
char getbyte()
{
while (Serial.available() == 0) {
// do nothing
}
return Serial.read();
}
[/code]
Then you could just do:
Matrix_string[c][r] = getbyte();
any idea?
I've got unzipped also other arduinos builds...can that be an issue?
now that I actually wait for a true byte to be available in the serial buffer
I can manage to push it to 115200 without getting bogus chars...
however I've still got syncing problems:
if I pass a long string of 555555555555555555
I get this
0 0 0 5 5 0 0 0 5 0 0 0 0 5 0 0 0 5 5 0 0 0 5 0 0 0 0 5 0
as if the Serial line read or decided to put now and then some 0 in the middle...
it works at 38400 but doesn't work anymore right above it.
this means that the problem is not waiting for a true serial byte...the problem must be somewhere else...
here it goes
you have to quickly send a string like
M55555555555555555555555555555555555
or similar length
at 38400 works perfectly
if I try at 115200 I get errors
int totCols = 5;
int totRows = 7;
//set the string that will be received throughSerial
/*the string should start with an 'M' so that the code knows when it is starting
rows and columns notation
M 1000000
0100000
0010000
0001000
0000100
continous string notation: M10000000100000001000000010000000100
*/
char Matrix_string [5][7]; //putting [totCols][totRows] yelds a compiler error
//use this routine to prevent the fact that Serial.read() doesn't wait for a byte in the buffer
char Serial_getSecureByte() {
while (Serial.available() == 0) {
// do nothing
}
return Serial.read();
}
void Matrix_serialRead () {
for (int c=0; c < totCols; c++) {
for (int r=0; r < totRows; r++) {
//read a char from Serial - use function to be sure that the byte is there
//char serIn = Serial_getSecureByte();
//convert it to an int since serIn will be 49(ASCII value of num 1)
//method 2 would be subtracting 48 - TODO test the fastest
//int b = atoi(&serIn);
//store it in the appropriate slot in the string
Matrix_string[c][r] = Serial_getSecureByte();//b;
//print feedback
Serial.print(Matrix_string[c][r]);
Serial.print(" ");
}
}
Serial.println();
//prepare the serial buffer for the next string
Serial.flush();
}
//output the string
void Matrix_display() {
//Serial.println("display: ");
for (int c=0; c < totCols; c++) {
for (int r=0; r < totRows; r++) {
Serial.print(Matrix_string[c][r]);
Serial.print(" ");
}
}
Serial.println();
}
void setup() {
Serial.begin(115200); //can push it further up!!! why??
}
void loop () {
//*check for serial data
while (Serial.available()) {
byte s = Serial.read();
if(s == 'M'){;
//start of the protocol Matrix
Matrix_serialRead ();
}
}
//continously display it all
//Matrix_display();
}
I made some minor advancements but still can't solve the problem.
changed the serialavailable function as noted by CosineKitty
if I leave all default connection settings I get syncing problems...however if on the terminal I change to
stop bits=2 (instead of 1 as default and as specified in the arduino preferences)
I get it almost right...
90% of the time it gets the right data.
can it be an issue that maybe it is compiling with settings that aren't really specified in the preferencese txt?
For what it's worth, the serialAvailable() bug I found would have no effect on your code, because you are just using Serial.available() to test yes/no is there at least one byte available. Even when it returns the wrong value, it will be nonzero, so your code will react properly.