Arduino & QextSerialPort

hi everybody,

i own a Arduino Duemilanove and want to use it with a custom gui, written in Qt. So i use QextSerialPort [1] (for a nicer doc see [2]) to open the virtual com-port /dev/ttyUSB0. During the development, i found some issues, so i started to snoop around here in the forum. I saw many threads with open questions (like [3]) about interfacing Arduino with QextSerialPort, so i decided to share my configuration.

For testing purposes, i wrote a simple sketch, that echoes any char receives back to sender:

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

void loop() {
      if (Serial.available() > 0) {
              Serial.println(Serial.read());
      }
}

To test the setup, i use putty [4]. Open /dev/ttyUSB0 at 57600 baud with the default settings:

Databits 8
Stopbits 1
Parity None
Flow Control XON/XOFF

I putting in some chars (here: xva) gives me back and saw on the console:

(you see only the reply, local echo is off)
After consulting a ascii-table like [5], everythink SEEMS to be ok, cause x = 120, c = 99, etc.

So i started to code the QextSerialPort code. I rip off the example code for the event-driven mode (polling sux :wink: from [6] and putted in my configuration values:

[...]
    const QString serport_filename = "/dev/ttyUSB0";

    this->serport = new QextSerialPort(serport_filename, QextSerialPort::EventDriven);
    this->serport->setBaudRate(BAUD57600);
    this->serport->setFlowControl(FLOW_XONXOFF);
    this->serport->setParity(PAR_NONE);
    this->serport->setDataBits(DATA_8);
    this->serport->setStopBits(STOP_1);
    this->serport->setTimeout(500);

    if (this->serport->open(QIODevice::ReadWrite) == true) {
        connect(this->serport, SIGNAL(readyRead()), this, SLOT(handleSerialData()));

        qDebug() << "listening for data on" << this->serport->portName();
        //emit portOpened();
    }
    else {
        qDebug() << "device failed to open:" << this->serport->errorString();
        //return false;
    }
   
[...]

As you see, i handle the incoming data in handleSerialData():

void SerialPort::handleSerialData()
{
    /* check if we can read from port */
    if (!serport->isOpen())
        return;

    /* get the data from port */

    QByteArray result;
    int bytesAvailable = this->serport->bytesAvailable();
    result.resize(bytesAvailable);
    this->serport->read(result.data(), result.size());
[...]

You see, hacked some quick and dirty code to read the data in a QByteArray. In the next step, i inspected the incoming data with Qt Creator’s Debugger.

I expected the QByteArray “result” contains ‘x’, ‘v’, ‘a’ (or the ascii-code equivalent ‘120’,‘118’,‘97’) BUT no, i got single digits: ‘1’,‘2’,‘0’,… (see picture above)

Maybe, the Serial.println(Serial.read()); function converts char to int to digits? Why it seems to work with Putty? i asked my self. But instead of patching the Serial lib of Arduino, i decided to write some quick & dirty code again, to convert it back (until i patch the Arduino Serial lib (if necessary )).

   QStringList sl = QString(result).split (QRegExp("\\r\\n") );
   QString strResult;
   QChar chrTmp;
   for( int i=0; i < sl.size(); i++)
   {
       chrTmp = QChar(sl.at(i).toInt());
       strResult += QString(chrTmp);
   }

   QByteArray   asciiResults  = strResult.toAscii();

Now, asciiResults contains the desired string “xva”. Puhh.

BUT: After getting more repeatedly data from the serial port, (done via a QTimer, 1000ms), it often gets corrupt data. Sometimes (~20%) there are some special chars in the received data.
Okay, maybe during a cosmic shower the data on the wire transforms sometimes (10x^-12), but every 5th-15th byte?

There must be a othere reason! So decided to ask the Arduino forum (you ;):

  • Is there any fundamental error in my approach?
  • Is the serial config, e.g. the Flow Control ?
  • Do you have a minimal example of working code?

Thanks,

rf_

Links:
[1] - http://code.google.com/p/qextserialport/
[2] - http://api.kde.org/4.x-api/kdeedu-apidocs/marble/html/classQextSerialPort.html
[3] - http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1277827861
[4] - sudo apt-get install putty or http://www.chiark.greenend.org.uk/~sgtatham/putty/download.html
[5] - http://en.wikipedia.org/wiki/ASCII#ASCII_printable_characters
[6] - http://code.google.com/p/qextserialport/source/browse/examples/event/PortListener.cpp

On the Arduino side, you read in a byte, using Serial.read(). Then, you use Serial.println() to send that byte back out.

But, because you didn't explicitly define HOW to do that, Serial.println converted the byte to a string, and sent the string and a carriage return and line feed to the serial port.

One byte in, 5 bytes out.

You could have used Serial.write() to write the byte AS A BYTE, or you could have used Serial.print() with the optional argument of BYTE to do the same thing.

Adding a carriage return and line feed after each byte seems to be explicitly shooting yourself in the foot.

Perhaps if you fix the Arduino code, the Qt stuff will work as advertised.

Dear PaulS,

thanks for your reply.

I will try to send is as "BYTE", and post the results ASAP.

rf_

Dear PaulS,

you are right ;)

i changed the Arduino sketch to use Serial.write() instead of Serial.prinln():

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

void loop() {
      if (Serial.available() > 0) {
              Serial.write(Serial.read());
      }
}

Now it works like expected, even at 115k ;D The corrupt data is gone too.

Many thanks, i only looked on the Host-side, suspected the error somewhere in the QExtSerialPort-Code...

Problem SOLVED!

rf_