Serial Speed problem

I've been banging my head the last two days. I have a Freeduino Board with the ATmega 328, running at 16Mhz. I am using a simple serial protocoll to communicate with the Freeduino, similar to the protocoll described by Guyt.

On my host I have a program written in Qt, communicating with the Freeduino. Everything works fine as long as I stay below 28800 Baud. At 28800 and above I don't get any answer back from the serial interface. Strangely, If I use the Serial Monitor, I can go up to the 115200 Baud rate. On the Qt side I already used two different libraries for the serial communication, each resulting in no communication above 19200 Baud.... Does anyone have an Idea where to search for the Problem? Any good Idea for debug is welcome.

Does anyone have an Idea where to search for the Problem?

If the serial monitor works ok, then simple deduction indicates you need to look at your “Qt” program.

If the serial monitor works ok, then simple deduction indicates you need to look at your "Qt" program.

Which is exactly what I did the last days. That's why I tried two different libraries for the Qt serial interface as well as the "polling" vs. signalling approach for the receive buffer. I just wanted to double check that there is no known problem with any speed settings on the freeduino board that I might have overlooked...

This topic jogged a few gray matter cells. Perhaps something in this thread may be useful. http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1289383919/0 Seeing the PC code and the Arduino code would be useful, too.

Thanks for the hints so far. I managed to strip down my Problem to a simple example that does not need Qt. I have a sketch for arduino and one for processing with the exact wrong behavior.
The processing side sends an command string to the arduino and there it is returned with a _OK added.
As soon as I use a speed above 19200 (28800 even crashes) the processing side always claims to receive “null”
Slower speeds work fine.
Could someone please try those two sketches at a high Baud rate?

Here’s the arduino code:

String cmd;

int BAUDRATE=9600;
//int BAUDRATE=19200;
//int BAUDRATE=38400;
//int BAUDRATE=115200;

void setup () {
  Serial.begin(BAUDRATE);
 cmd="";
 }


void loop() {
  serialInterface();
}

void serialInterface() {
  char c;
  while(Serial.available()) {
    c=Serial.read();
    doChar(c);
  }
}

void doChar(char c)
{
  switch(c)
  {
   case '<' : 
     cmd=""; // empty commandstring
     break;
   case 
   '>' :
     if (cmd.length()>0 ) {
       evalCmd(cmd);
       cmd="";
      }
    break;
    default:
      cmd=cmd+c;
  }

}


void evalCmd(String myCmd) {
    boolean cmdOk=true;
    String answer="";
    myCmd = myCmd.toUpperCase() ;
    String myAnswer=myCmd+"_OK";
    sendAnswer(myAnswer);
    
}

void sendAnswer(String answ)
{
    String cmdString ='<' + answ + '>';
    Serial.print(cmdString);
}

And this one goes into Processing:

import processing.serial.*;

Serial myPort;  // Create object from Serial class
String inString;  // Input string from serial port: 

int BAUDRATE=9600;
//int BAUDRATE=19200;
//int BAUDRATE=38400;
//int BAUDRATE=115200;

void setup() {
  
  size(470, 200);
  String portName = Serial.list()[0];
  myPort = new Serial(this, portName, BAUDRATE); 
  
  println("Starting " + portName);
  sendCmd("TCRU00");
  sendCmd("TCRU01");
  myPort.buffer(11); 
}

void draw() {
  background(0); 
  text("received: " + inString, 10,50);
  sendCmd("TCRD00");
  sendCmd("TCRD01");
}
 
void serialEvent(Serial p) { 
  inString = p.readString(); 
}

void sendCmd(String cmd) {
  println("Sending command");
  cmd="<"+cmd+">";
  myPort.write(cmd); 
  return;
}

Thanks in advance…

I tried on two different computers. On my new work computer, running Win7 64bit with dual quad cores, the Processing program showed received NULL at 19200.

On my Acer netbook, the 19200 baud rate worked. Going higher failed.

On both computer the Arduino is flashing the RX light to beat hell. It never seems to have time to actually send anything, though, at higher baud rates.

Perhaps the issue in your Qt application is that, like the Processing app, you are not giving the Arduino time to respond.

Hmm, good hint. However, I just added a delay(1000) statement after each myPort.write statement (on the processing side) which should give my freeduino 1s to respond on each command and yet the transmission breaks at 38400Baud

However, I just added a delay(1000) statement after each myPort.write statement (on the processing side) which should give my freeduino 1s to respond on each command and yet the transmission breaks at 38400Baud

If deay() in Processing is like delay() in Arduino, it is a blocking function. Nothing else, like processing serial data, can happen during the delay.

Why don't you try a handshaking system.

Send some data from Processing, and wait for a reply from the Arduino before sending more. Does that allow you to increase the speed?

I just changed my two sketches to wait for eachother to complete a command. Still the same result. As soon as I use the 38400 Baud speed, the data seems to get lost…
Slowly I am running out of ideas here.
Here’s the new protocoll based test code for Arduino:

String cmd;

int BAUDRATE=9600;
//int BAUDRATE=19200;
//int BAUDRATE=38400;
//int BAUDRATE=115200;

void setup () {
  Serial.begin(BAUDRATE);
  delay(5000);
 cmd="";
 sendAnswer("TCRD00_OK");
 }


void loop() {
  serialInterface();
}

void serialInterface() {
  char c;
  while(Serial.available()) {
    c=Serial.read();
    doChar(c);
  }
}

void doChar(char c)
{
  switch(c)
  {
   case '<' :
     cmd=""; // empty commandstring
     break;
   case
   '>' :
     if (cmd.length()>0 ) {
       evalCmd(cmd);
       cmd="";
      }
    break;
    default:
      cmd=cmd+c;
  }

}


void evalCmd(String myCmd) {
    boolean cmdOk=true;
    String answer="";
    myCmd = myCmd.toUpperCase() ;
    String myAnswer=myCmd+"_OK";
    sendAnswer(myAnswer);
    
}

void sendAnswer(String answ)
{
    String cmdString ='<' + answ + '>';
    Serial.print(cmdString);
}

And for the processing side:

import processing.serial.*;
Serial myPort;  // Create object from Serial class
int val;      // Data received from the serial port
boolean newcmd=false;
String inString;  // Input string from serial port: 
String displayString;
//int BAUDRATE=19200;
//int BAUDRATE=38400;
int BAUDRATE=9600;

void setup() {
  inString="";
  displayString="";
  size(470, 200);
  String portName = Serial.list()[0];
  myPort = new Serial(this, portName, BAUDRATE); 
  println("Starting " + portName);
  myPort.buffer(0); 

}

void draw() {
  background(0); 
  if (newcmd==true) {
    text("received: " + displayString, 10,50);
    sendCmd("TCRD00");
    newcmd=false;
    
  }
}

void serialEvent(Serial p) { 
  char currChar;
 while(myPort.available() >0) {
   currChar=p.readChar();
  inString = inString+currChar;
  if (currChar=='>') {
    println("Received command word : "+ inString);
   displayString=inString;
   inString="";
   newcmd=true;
  }
  break;
 }
}

void sendCmd(String cmd) {
  println("Sending command");
 cmd="<"+cmd+">";
myPort.write(cmd); 
return;
}

Note that there is a 5 second delay on the arduiono side to give you a chance to launch the processing sketch before the first data is send from arduino…

Does anyone have some more ideas how to tackle this problem?

At 34800 bps you only have 260uS to handle each character. In this time the Arduino has to do

void doChar(char c)
{
  switch(c)
  {
   case '<' :
     cmd=""; // empty commandstring
     break;
   case
   '>' :
     if (cmd.length()>0 ) {
       evalCmd(cmd);
       cmd="";
      }
    break;
    default:
      cmd=cmd+c;
  }

}

Plus the while loop, serial.read and dochar call overhead and things like

cmd = cmd + c;

who knows what C++ is doing with that.

I haven’t done the maths, but my gut feeling is (and I may be well off, at 16MHz a lot can be done in 260uS) that this may be too much.

Maybe try accumulating the string command then parsing it when fully received.


Rob

I finally broke down the arduino code to just about the smallest piece I could imagine, including a handshake to prevent buffer overflow etc… I still see the communication dying at 38400 Baud.

I am starting to believe that there might be something wrong with the setup of the serial interface (bit settings for clock divider etc…)
Is there a way of debugging what’s going on in the Atmega328, in terms of setup of the serial interface?

Just for completness, here’s my stripped down arduino code

String cmd;
String fullCmd;
//int BAUDRATE=9600;
//int BAUDRATE=19200;
//int BAUDRATE=38400;
//int BAUDRATE=115200;
boolean cmdComplete=false;
void setup () {
  Serial.begin(BAUDRATE);
  delay(5000);
 cmd="";
 Serial.print("<TCRD00>");
 }


void loop() {
  char c;
  while(Serial.available()) {
    c=Serial.read();
    if (c=='<') {
      cmd="";
    } else if (c=='>') {
      fullCmd=cmd;
      cmd="";
      cmdComplete=true;
      break;
    } else {
       cmd+=c;
    }
  }
  if (cmdComplete==true) {
    Serial.print('<' + fullCmd + '>');
    cmdComplete=false;
  }
}

 [smiley=embarassed.gif] [smiley=embarassed.gif]

I ran this code (same as yours but a couple of minor changes that would make no difference)

String cmd;
String fullCmd;
//int BAUDRATE=9600;
//int BAUDRATE=19200;
//int BAUDRATE=38400;
//int BAUDRATE=115200;
boolean cmdComplete=false;
void setup () {
  Serial.begin(115200);
 cmd="";
 Serial.print("start");
 }


void loop() {
  char c;
  while(Serial.available()) {
    c=Serial.read();
    if (c=='<') {
      cmd="";
    } else if (c=='>') {
      fullCmd=cmd;
      cmd="";
      cmdComplete=true;
      break;
    } else {
       cmd+=c;
    }
  }
  if (cmdComplete==true) {
    Serial.println('<' + fullCmd + "_OK>");
    cmdComplete=false;
  }
}

then fed it

from the serial monitor and got

<TCRD00_OK>
<TCRD00_OK>
<TCRD00_OK>
<TCRD00_OK>
<TCRD00_OK>
<TCRD00_OK>
<TCRD00_OK>
<TCRD00_OK>

in return, and that’s at 115200bps with no delays.

So there’s nothing wrong with the Arduino code I think, I’d be looking at the processing side.

I am starting to believe that there might be something wrong with the setup of the serial interface (bit settings for clock divider etc…)

That would imply a bug in the serial library, pretty unlikely by now I would think.


Rob

Well, as I stated before, the serial monitor seems to be the only thing that can communicate with my arduino at 115200 Baud. Everything else (QtSerial or Processing) simply does not work at any speed above 19200Baud. Something seems different in the way that the serial monitor communicates with the arduino compared to my applications.

Does anyone have a high speed example showing data exchange from a processing sketch to the arduino at 115200 Baud, that I could use as starting point for my application?

as I stated before, the serial monitor seems to be the only thing that can communicate with my arduino at 115200 Baud.

Sorry, I missed that.

I don’t know processing or Qt but do have VB.Net so I wrote a small program to spit out 50 x “” and I got 50 x “<TCRD00_OK>” with no errors.

So there’s nothing fundamentally wrong with the Arduino code. It has to be the processing. Looking at this function

void serialEvent(Serial p) {
      char currChar;
       while(myPort.available() >0) {
               currChar=p.readChar();
              inString = inString+currChar;
              
              if (currChar=='>') {
                      println("Received command word : "+ inString);
                     displayString=inString;
                     inString="";
                     newcmd=true;
              }
        break;
       }
}

What’s the purpose of the break?

How does serialEvent get fired? I assume it’s a callback function for the serial port event but I see no connection between it and myPort.

Still none of this explains the “works at < 38400” problem.

Also I see no definition of portName, is this working code?


Rob

Both of your serial streams passing over the same pin, aren't they? Do you really need to save the two pins that moving "your" stream (as opposed the the one used by the development system) to dedicated pins, by using NewSoftSerial? If not, it removes all possibility of your stream and the serial monitor's stream clashing... and it is easy to do.

More at...

http://sheepdogguides.com/dt4t.htm

(That's couched in "Delphi running the other partner in the exchange" terms, but there is lots of generally useful material along the way.)

Yes, I am currently using one connection only namely the serial over USB. My laptop has no native serial interface anymore so I took advantage of the USB. Your information looks promising although forces me unto my old laptop. I will try over the X-mas vacation. Thanks anyway.

I would like to ask for your help once more (hope I am not going onto your nerves yet…). I stripped down my code to the most simplistic case that I can imagine. Please take a minute to test the arduino code with the processing counterpart. Increase the baud rate in both sketches until communication fails (if so). The communication is started from Processing by pressing any key. From there on, the same data keeps bouncing back and forth between processing and arduino and can be seen in the processing console. I wonder whether I have a Linux specific problem and who else might be limited to the 19200 Baud. Please post your results together with your OS

Arduino code:

char c;
int BAUDRATE=9600;
//int BAUDRATE=19200;
//int BAUDRATE=38400;
//int BAUDRATE=115200;
boolean cmdComplete=false;
void setup () {
  Serial.begin(BAUDRATE);

}

void loop() {
  while(Serial.available() >0) {
    c=Serial.read();
    Serial.write(c);
  }
}

Processing sketch:

import processing.serial.*;
Serial myPort;  // Create object from Serial class

int BAUDRATE=9600;
//int BAUDRATE=19200;
//int BAUDRATE=38400;
//int BAUDRATE=19200;
//int BAUDRATE=115200;
void setup() {
  size(470, 200);
  String portName = Serial.list()[0];
  myPort = new Serial(this, portName, BAUDRATE); 
  println("Starting " + portName);
  myPort.buffer(0); 
}

void draw() {
}
void serialEvent(Serial p) { 
  char currChar;
 while(myPort.available() >0) {
   currChar=p.readChar();
   println(" Receive char: "+currChar);
 myPort.write(currChar);
 }
}

void keyPressed() {
  println("Sending initial command");
  myPort.write("<TCRD00>");
      
}

I appreciate your help very much.

OK I've downloaded the processing environment (Windows Vista), might as well see what it's like eh?. I get the same error that you do, ie, no work at 38400, so I've had a play, I'm using the following (partial code snippets)

void loop() {
  while(Serial.available() >0) {
    c=Serial.read();
    Serial.write([glow]0xAA[/glow]);
  }
}

and

void serialEvent(Serial p) {
 char currChar;
 while(myPort.available() >0) {
   currChar=p.readChar();
   println("-" + hex(currChar,2) + "-" );
 }
}

Note the 0xAA in the Arduino code and the fact that I'm printing the hex value of the char recieved at the PC end.

If I make this 0xFF I get the following when I press a key

Sending initial command
-00-

then I change to 0xAA and get this

Sending initial command
-00-
-00-
-00-
-00-
-00-

Note that on a serial line 0xFF looks like

-_----------

and 0xAA looks like

-----_-----

so I deduce from that that the baud rates are incompatable and that the Arduino is transmitting too fast or the PC receiving too slow. I reason that because a falling edge on the serial line is seen as the beginning of a start bit, if the receiver is expecting a data rate much faster than the transmitter is sending the receiver will parse the start bit as an entire character.

That I believe is why I see a single -00- when the Arduno sends 0xFF and 5 of them when it sends 0xAA, ie one for each LOW bit in the byte.

Admitedly it's not the same every time and other combinations of transmit data don't quite align with that theory.

Anyway I'll continue playing for a while.


Rob

After doing some more google searching I come to believe that I might be hit by issue 102 as described here http://code.google.com/p/arduino/issues/detail?id=102

Unfortunately I have no way of trying my lastest minimum code on an old 0016 version or on the latest code snapshot. If someone could try for me, this would be great. If not I will wait until 0022 comes out and check my code again.

OK I think I’ve found the main problem, as is often the case it was blindingly obvious once seen. You had

int BAUDRATE=115200;

that’s trying to fit a large number into an int. And 38400 is > an unsigned int as well so I suspect that caused problems. 19200 etc are small enough to fit. At the end of the day I think it was a baud rate problem caused by dud values being used in the serial.begin() call.

The best way to define these things is with a #define

#define BAUDRATE 115200

That way it’s just a pre processor text substitution and there are no data types involved.

You had the same on the processing side as well, for some reason that worked but should still be fixed. Here’s a logic analyser trace of it working, it’s displayed in HEX but the characters are “”.

I also modified the Arduino code a little,

char c;
//#define BAUDRATE 9600
//#define BAUDRATE 19200
//#define BAUDRATE 38400
#define BAUDRATE 115200


boolean cmdComplete=false;
void setup () {
  Serial.begin(BAUDRATE);

}

void loop()
{

  while(Serial.peek() == -1) {}; // wait for a character

  char c = Serial.read(); 
  Serial.write(c);

}

Hope that allows you to continue with the project.


Rob