Pages: [1]   Go Down
Author Topic: Serial speed and syncronization problem  (Read 1515 times)
0 Members and 1 Guest are viewing this topic.
0
Offline Offline
Full Member
***
Karma: 0
Posts: 134
panta rei resist the resistors!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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);

thanks in advance
b.
Logged

Florida, USA
Offline Offline
Full Member
***
Karma: 0
Posts: 146
meow!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

I use 115200 baud all the time and it works fine.  Try posting your code here; maybe then we can see what the problem is.
Logged

0
Offline Offline
Full Member
***
Karma: 0
Posts: 134
panta rei resist the resistors!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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.

Code:
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

thanks for the help

« Last Edit: January 07, 2007, 05:57:28 pm by beltran » Logged

Florida, USA
Offline Offline
Full Member
***
Karma: 0
Posts: 146
meow!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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[c][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();
}

Then you could just do:

    Matrix_string[c][r] = getbyte();
« Last Edit: January 07, 2007, 06:11:35 pm by CosineKitty » Logged

0
Offline Offline
Full Member
***
Karma: 0
Posts: 134
panta rei resist the resistors!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

hehe you tricky little kitty smiley-wink
you are right...
thanks for the code tip

I've called the function Serial_getSecureByte()

this doesn't solve my other problem though...I can't still push the Serial line above 38400 smiley-sad
Logged

Florida, USA
Offline Offline
Full Member
***
Karma: 0
Posts: 146
meow!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
hehe you tricky little kitty Wink
you are right...
thanks for the code tip
Meow!  smiley

Quote
this doesn't solve my other problem though...I can't still push the Serial line above 38400 smiley-sad
Meow?  smiley-sad
What exactly happens when you go above 38400 baud?
Logged

Forum Administrator
Cambridge, MA
Offline Offline
Faraday Member
*****
Karma: 9
Posts: 3538
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

What version of the Arduino software are you using?  Older versions didn't support high serial speeds.
Logged

0
Offline Offline
Full Member
***
Karma: 0
Posts: 134
panta rei resist the resistors!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

arduino 0007,

and these are the preferences set by the IDE in the Application Data folder

serial.stopbits=1
serial.databits=8
serial.download_rate=19200
serial.parity=N
serial.port=COM9
serial.debug_rate=38400
serial.burn_rate=115200

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...

i'll try out a few things...
any idea?
« Last Edit: January 08, 2007, 05:35:13 am by beltran » Logged

Forum Administrator
Cambridge, MA
Offline Offline
Faraday Member
*****
Karma: 9
Posts: 3538
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Can you post your revised code?  I'll try to test it on my machine.
Logged

0
Offline Offline
Full Member
***
Karma: 0
Posts: 134
panta rei resist the resistors!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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


Code:
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();    
}

thanks in advance smiley
Logged

0
Offline Offline
Full Member
***
Karma: 0
Posts: 134
panta rei resist the resistors!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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?

Logged

Florida, USA
Offline Offline
Full Member
***
Karma: 0
Posts: 146
meow!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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.
Logged

Pages: [1]   Go Up
Jump to: