4

I am writing a Qt application to communicate with another computer over a serial port. I have 2 real issues.

1. I can send and receive data fine, but sometimes the serial port "eats" part of my input. For example if I send:

cd /application/bin

sometimes (not always) it will only receive:

cd /applica

(Since it's a terminal it echoes the input back. Also my prompt tells me I'm clearly in the wrong spot.)

2. Also, sometimes the Qt slot which fires when there is data available doesn't fire even though I know that there's data I can receive. If I send another \r\n down the port the slot will fire. For example sometimes I'll ls something, and the command name will be read back from the port, but the contents of the folder sit there in limbo until I hit return again. Then I get the listing of the directory and two prompts.

Here's my code:

void Logic::onReadyRead(){        
        QByteArray incomingData;  
        incomingData = port->readAll();
        QString s(incomingData);
        emit dataAvailable(s);// this is a Qt slot if you don't know what it is.
        qDebug() << "in:"<< s.toLatin1();     
}

void Logic::writeToTerminal(QString string )
{
    string.append( "\r\n");
    port->write((char*)string.data(), string.length());
    if ( port->bytesToWrite() > 0){
        port->flush();
    }
    qDebug() << "out:" << string.toLatin1();
}
László Papp
  • 51,870
  • 39
  • 111
  • 135
Muricula
  • 1,174
  • 3
  • 9
  • 16
  • I just realized it may not be clear, these are unrelated issues. Shell will tell me that it can't go to `/applica` because no such directory exists – Muricula Aug 02 '13 at 23:13
  • You'll need to buffer the data that is read from the port until you encounter the , which might require multiple reads from the port. – Pete Aug 03 '13 at 00:02

2 Answers2

2

I found the solution, and I suspect it was an encoding error, but I'm not sure. Instead of sending a QString down the serial port, sending a QByteArray fixed both problems. I changed the writeToTerminal() method:

void Logic::writeToTerminal(QString string )
{
    string.append( "\r");
    QByteArray ba = string.toAscii();
    port->write(ba);
}
Muricula
  • 1,174
  • 3
  • 9
  • 16
0

From this forum, it appears that sometimes not all the data gets sent, and whatever does gets sent has a '\0' appended to it. So if

cd /applica'\0' got sent, then the port->readAll() would stop there, because it thinks it has read everything.

One suggested answer on that forum was to read line by line, which your code almost does. So I think in your case, you can change your code to:

void Logic::onReadyRead(){        
    QByteArray incomingData;  
    if(port->canReadLine()) {
      incomingData = port->readLine();
      QString s(incomingData);
      emit dataAvailable(s);// this is a Qt slot if you don't know what it is.
      qDebug() << "in:"<< s.toLatin1();
    }     
}

void Logic::writeToTerminal(QString string )
{
    string.append( "\r\n");
    port->write((char*)string.data(), string.length());
    if ( port->bytesToWrite() > 0){
        port->flush();
    }
    qDebug() << "out:" << string.toLatin1();
}
maditya
  • 8,626
  • 2
  • 28
  • 28
  • 1
    I'd suggest to not blindly convert from QByteArray to QString and vice versa without specifying the encoding. E.g. when writing: `QByteArray data = s.toUtf8(); //explicitly convert to UTF-8`; And check return values:`const qint64 written = port->write(data.constData(), data.length());` – Frank Osterfeld Aug 03 '13 at 07:44
  • @maditya, I had tried reading line by line but it did not fix my problem. It worked slightly worse than `port->readAll()` Thanks nonetheless – Muricula Aug 05 '13 at 18:00