0

I'm making a Qt data acquisition GUI to replace LabVIEW for an application in my lab.

I want a pushbutton on my GUI to write some data to the serial port (to a microcontroller), then wait for data acquisition to finish (which the microcontroller does) and then get the data back over the serial port for saving, plotting, etc.

The following void checks for incoming serial data. It prints the number of bytes in the serial buffer.

Now, when I run the program I click the button and get "0" on the first click. A second click gives me the correct number of bytes available.

It appears that I am not getting the incoming serial data available until the next time I click the pushbutton. Why is this?

void MainWindow::on_run_PushButton_clicked(){

sendserialData("go");

quint64 availablebytes = 0; 
int i=0;
while(availablebytes < 4 ){ // less than 4 bytes on the incoming serial buffer
    availablebytes = microcontroller->bytesAvailable();
    qDebug() << availablebytes;
    i++;
    if(i==4){break;}
}

FYI if it is important, here are the properties of the serial port:

if(microcontroller_is_available){
   // open and configure serialport
    microcontroller->setPortName(microcontroller_port_name);
    microcontroller->open(QSerialPort::ReadWrite);
    microcontroller->setBaudRate(QSerialPort::Baud115200);
    microcontroller->setDataBits(QSerialPort::Data8);
    microcontroller->setParity(QSerialPort::NoParity);
    microcontroller->setStopBits(QSerialPort::OneStop);
    microcontroller->setFlowControl(QSerialPort::NoFlowControl);

}
else{
    QMessageBox::warning(this, "Port error", "Cannot connect to the microcontroller.");
}

UPDATE 14 Nov 2016

Following the suggestions of others, the following code works properly, reading in the data immediately once I have pushed the pushbutton. I connected the readyRead signal to readData:

connect(microcontroller, &QSerialPort::readyRead, this, &MainWindow::readData);

void MainWindow::on_run_PushButton_clicked()
{
ui->run_PushButton->blockSignals(true);
serialData="";
sendserialData("go");
}

void MainWindow::sendserialData(QString command)
{
if(microcontroller->isWritable()){
    microcontroller->write(command.toStdString().c_str());
}else{
    qDebug() << "Cannot write to the microcontroller";
}
}

void MainWindow::readData()
{
serialData += microcontroller->readAll();
qDebug() << serialData;
ui->run_PushButton->blockSignals(false);
}

Note the use of blockSignals, so the DAQ cannot be started while it is already running.

Michael T
  • 21
  • 3
  • 1
    How long is the timeout before leaving the `bytesAvailable()` function ? If no timeout, add at least a delay in the `while { ... }`. – J. Piquard Nov 11 '16 at 22:27
  • Good suggestion, thanks. A 1 second delay works, but this seems excessively long considering the length of the data acquisition routine on the microcontroller. – Michael T Nov 11 '16 at 22:52
  • If your microcontroller is only waiting your order, a 100 ms timeout will be enough. – J. Piquard Nov 11 '16 at 22:59

1 Answers1

1

Looking at the Qt Serial Port documentation, it looks like you want to connect to a session using the QIODevice::readyRead signal, which will be raised when new bytes arrive at the port.

There is also an SO question/answer about how to use this event.

Community
  • 1
  • 1
Joe Friedrichsen
  • 1,976
  • 14
  • 14