Problem with QtSerialPort on Windows
-
Hello all!
I'm trying to develop a simple command line program to write to a device connected through USB-Serial adapter. Using the example application from "here":http://qt-project.org/wiki/QtSerialPort (scroll down to "Simple Example" that lists connected serial devices), it shows the device. But whenever I normally open a connection to the device, it gives error "void __thiscall QSerialPortPrivate::detectDefaultSettings(void): Unexpected flow
control settings" on open, and nothing goes through to the device even if I alter the flow control, parity and other settings afterwards. It doesn't give any other error or warning while the port is open, nor is there any errors set for the port.The code I'm trying to execute is as follows:
@
// QByteArr bytearr is introduced and filled with data before this snippet in the program code
QSerialPort serial;
serial.setPortName("COM11");
if (serial.open(QIODevice::ReadWrite)) {
bool success = serial.setBaudRate(QSerialPort::Baud9600) &
serial.setStopBits(QSerialPort::OneStop) &
serial.setDataBits(QSerialPort::Data8) &
serial.setParity(QSerialPort::NoParity) &
serial.setFlowControl(QSerialPort::NoFlowControl);
qDebug() << "Connected to usb device " << serial.portName() << " " << (success ? "OK" : "FAIL");serial.write(bytearr); serial.waitForBytesWritten(-1); serial.close(); }
@
The serial port name in use has been confirmed with the example application. The device I'm trying to write to accepts commands as bytes, and it does not send any response back at all.The weird thing is, I can get the program shown above to work by running another application, that opens the same port, and continuously (in while(true) loop) reads all data from the port and writes it to command line, and then manually closing the program. Although this test program for reading gives the same error about flow control settings, after running the test program the other program for writing works for as long as the usb cable is connected. Running the test program also removes the flow control setting error message from appearing in either of the programs.
This is the test program, that should read everything from the port (it doesn't work like it should, but it resolves the issue):
@#include <QtCore/QCoreApplication>
#include <QtCore/QDebug>#include <QtSerialPort/QSerialPort>
#include <QtSerialPort/QSerialPortInfo>QT_USE_NAMESPACE
int main(int argc, char *argv[])
{QSerialPort serial; serial.setPortName("COM11"); if (serial.open(QIODevice::ReadWrite)) { bool success = serial.setBaudRate(QSerialPort::Baud9600) & serial.setStopBits(QSerialPort::OneStop) & serial.setDataBits(QSerialPort::Data8) & serial.setParity(QSerialPort::NoParity) & serial.setFlowControl(QSerialPort::NoFlowControl); qDebug() << "Connected to usb device: " << (success ? "OK" : "FAIL"); while(true) { if(serial.waitForReadyRead(-1)) { QByteArray out = serial.readAll(); for(int i=0; i< out.length(); i++) { qDebug() << (int) out[i]; } } } serial.close(); qDebug() << "Connection closed."; } qDebug() << "Program exiting."; return 0;
}@
Although my question/problem should be obvious by now, this way for this to work isn't very optimal. Is there something I'm doing wrong in the writing application / something that I'm not taking into account, or is this a bug in Windows 8 environment? The program code has been proven to work as it is in Ubuntu Linux environment, and it kinda works in windows environment as well, but only after running the reader program. Calling the readAll function for 1M times in a for-loop doesn't work to simulate the effect of running the reader program, nor does opening the serial port without closing it first before trying to write.
I am running Qt 5.2 32-bit, my compiler is MSVC2012 and my os is Windows 8 64-bit, although this has been confirmed to happen on 64-bit Windows 7. 32-bit Windows has not been tested.
Any help is greatly appreciated!
-
[quote]
“void __thiscall QSerialPortPrivate::detectDefaultSettings(void): Unexpected flow control settings”
[/quote]It is normal, don't pay attention.
It is wrong in your case (though it will work):
[code]
...
serial.write(bytearr);
serial.flush();
serial.close();
...
[/code]should be:
[code]
...
serial.write(bytearr);
serial.waitForBytesWritten();
serial.close();
...
[/code]Next, it is wrong in your case:
[code]
...
while(true) {
QByteArray out = serial.readAll();
for(int i=0; i< out.length(); i++) {
qDebug() << (int) out[i];
}
}
serial.close();
...
[/code]Should be:
[code]
...
while(true) {
if (serial.waitForReadyRead()) {
QByteArray out = serial.readAll();
for(int i=0; i< out.length(); i++) {
qDebug() << (int) out[i];
}
}
}
serial.close();
...
[/code]So, please look an examples of QtSerialPort and read Qt documentation.
-
yes. it is. but in your case it is synch approach.
-
Ahh.. Sorry.. :)
-
Thank you for your replies. Although I'm sure these are things to be taken into account, they are not the thing in this case. The latter program is provided only because running it makes the first program for writing work. Whether it actually reads anything or not is not the issue, and making the change you suggested would probably break the reader program even further, as the device will not send anything to the program at all, thus it will never actually reach the readAll part.
As for the change in writer program, waitForBytesWritten has already been tried and it did not change anything in how the program worked (or didn't). Your suggested fix also contains a problem, as waitForBytesWritten expects integer parameter for wait timeout in msecs.
Although you mention that the error/warning message can be ignored, results show otherwise as it will not appear when the program works as it should (after running reader program once). But I also understand it is not the cause of my problems, only an effect of something else not working. And that "something else" is what I need help with most likely.
-
I already say to you that it is necessary to change in your code when using the synchronous approach (because your code demonstrated sync approach).
But I recommend to use asynchronous approach with use of signals/slots.
-
@kuzulls
And I already said, what you suggested didn't fix the problem. :) I also tried the fix you gave for the reader program, and it actually did start working, and it also still works so that it makes the writer program work afterwards until usb cable is removed. But it doesn't solve the problem I need help with. The writer program (first piece of code) has to work without the reader program (second piece of code).
Inspired from the fixes, I also attempted having one waitForReadRead call with long timeout before trying to write there, but this didn't solve the problem which is, the device does not receive (or does not receive correctly) what I'm trying to send there unless I run the second piece of code first.
As for it being sync'd or async'd, it doesn't matter at this point. Purpose of this program / project at this stage is to get the connection to device to work for writing, it's okay if the program has to wait for the connection. Also it's worthwhile to mention (like I mentioned in OP) that this works in other environments than windows flawlessly, even with the "flawed" code I have now fixed (without seeing any changes in results really).