PDA

View Full Version : QSerialport in multithread



snow_starzz
2nd December 2013, 09:03
Hi guys..

Previously i'm using external library for accessing RS232 serial port. Now i want to try to use Qserialport in Qt5.1.
however, i have some problems as i'm using multithreading program (Qthread).

Main thread

void MainWindow::on_plotButton_clicked()
{
//Initialize thread for acc
Thread_Acc = new QThread;
Sensors* Acc = new Sensors();
Acc->moveToThread(Thread_Acc);
connect(Thread_Acc, SIGNAL(started()), Acc, SLOT(FetchData_AW()));
connect(Acc, SIGNAL(finished()), Thread_Acc, SLOT(quit()));
connect(Acc, SIGNAL(finished()), Acc, SLOT(deleteLater()));
connect(Thread_Acc, SIGNAL(finished()), Thread_Acc, SLOT(deleteLater()));}

Worker thread

void Sensors::FetchData_AW()
{
foreach (const QSerialPortInfo &info, QSerialPortInfo::availablePorts()) {
qDebug() << "Name : " << info.portName();
qDebug() << "Description : " << info.description();
qDebug() << "Manufacturer: " << info.manufacturer();

if(info.portName() == "COM24")
{
cport_nr_Acc.setPort(info);
cport_nr_Acc.close();
if (cport_nr_Acc.open(QIODevice::ReadWrite))
{
cport_nr_Acc.setBaudRate(57600);
cport_nr_Acc.setDataBits(QSerialPort::Data8);
cport_nr_Acc.setParity(QSerialPort::NoParity);
cport_nr_Acc.setStopBits(QSerialPort::OneStop);
cport_nr_Acc.setFlowControl(QSerialPort::NoFlowCon trol);
}else
return;
break;
}
}
Fetch_ACC = new QTimer (this);
connect(Fetch_ACC,SIGNAL(timeout()),this,SLOT(Loop _DataAW()));
Fetch_ACC->start(55);
}

the program can run but it display warning as below and the input from the device is also not as expected (value not stabilize) comparing if i use external rs232 library.

QObject: Cannot create children for a parent that is in a different thread.
(Parent is QSerialPort(0x127bac98), parent's thread is QThread(0x10b40ed0), current thread is QThread(0x128967f0)
QObject: Cannot create children for a parent that is in a different thread.
(Parent is QSerialPort(0x127bac98), parent's thread is QThread(0x10b40ed0), current thread is QThread(0x128967f0)
QObject: Cannot create children for a parent that is in a different thread.
(Parent is QSerialPort(0x127bac98), parent's thread is QThread(0x10b40ed0), current thread is QThread(0x128967f0)

is there any interruption of the port if I'm using it from other than main thread?
i already make the Qserialport as the variable in worker-thread class instead of global variable.
what can i do to solve this issues because i really want to use readyRead signal.

Thanks in advance... =)

anda_skoa
2nd December 2013, 12:42
Where to you create your QSerialPort instances?
Maybe accidentally as non-pointer members of Sensors or in Sensors' constructor?

Cheers,
_

snow_starzz
3rd December 2013, 02:26
class Sensors : public QObject
{
Q_OBJECT

public:
Sensors();
QSerialPort cport_nr_Acc;

..... }

should i used pointer instead??

Added after 1 45 minutes:

SOLVE!!

Thanks anda_skoa.. =)

I'm using pointer for the qserialport and for the value, i'm not using the proper method to assigned the value from the QBytearray.

Code below for others reference.. =)

Sensors::Sensors()
{
cport_nr_Acc = new QSerialPort (this);
}
void Sensors::FetchData_AW()
{
cport_nr_Acc->setPortName("COM24");
cport_nr_Acc->close();
if (cport_nr_Acc->open(QIODevice::ReadWrite))
{
cport_nr_Acc->setBaudRate(57600);
cport_nr_Acc->setDataBits(QSerialPort::Data8);
cport_nr_Acc->setParity(QSerialPort::NoParity);
cport_nr_Acc->setStopBits(QSerialPort::OneStop);
cport_nr_Acc->setFlowControl(QSerialPort::NoFlowControl);
}else
return;

Fetch_ACC = new QTimer (this);
connect(Fetch_ACC,SIGNAL(timeout()),this,SLOT(Loop _DataAW()));
Fetch_ACC->start(25);
}
void Sensors::Loop_DataAW()
{
if(!EN_A)
{
Fetch_ACC->stop();
cport_nr_Acc->close();
emit finished();
return;
}

// expected to get 14 byte of input from device
for(int y = 0;y<14;y++)
{
cport_nr_Acc->waitForReadyRead(50);
nA = cport_nr_Acc->bytesAvailable();
if(nA>=14)
break;
Sleep(1);
}

if(nA == 14)
{
inacc = cport_nr_Acc->readAll();
inacc[nA] = 0; // put a "null" at the end of a string!

char *p = inacc.data();
// input buffer .xxyyzzxxyyzz. --> direct value
dataAx = (static_cast<unsigned char>(p[1])<<8)|static_cast<unsigned char>(p[2]);
dataAy = (static_cast<unsigned char>(p[3])<<8)|static_cast<unsigned char>(p[4]);
dataAz = (static_cast<unsigned char>(p[5])<<8)|static_cast<unsigned char>(p[6]);
dataWx = (static_cast<unsigned char>(p[7])<<8)|static_cast<unsigned char>(p[8]);
dataWy = (static_cast<unsigned char>(p[9])<<8)|static_cast<unsigned char>(p[10]);
dataWz = (static_cast<unsigned char>(p[11])<<8)|static_cast<unsigned char>(p[12]);

}else
{
qDebug() << "Polling fail " << nA;
return;
}

but why pointer should be use?? doesn't it still in the same thread if the variable is class variable??

anda_skoa
3rd December 2013, 10:18
but why pointer should be use?? doesn't it still in the same thread if the variable is class variable??

The difference is that you now have a parent.

Basically in your original situation the QSerialPort object was created by the main thread, as part of creating the Sensors object. At this point both "belonged" to the main thread.
You then correctly moved the Sensors object to the new thread, however the QSerialPort instance was not.

Now you have QSerialPort as a child of Sensors, it is being moved alongside its parent.
Another option would have been to create it in the new thread's context, like you do with the QTimer.

Cheers,
_