Multiple Serial Ports
-
Hi every one.
I want to open multiple serial ports at the same App. .
I tried to open them sequentially. The result is:Started! Ports Recognition Finished! Number of Availabe Ports: 4 Port 1: "Serial Test! (Port1)\r\n" QIODevice::read (QSerialPort): device not open QIODevice::read (QSerialPort): device not open QIODevice::read (QSerialPort): device not open QIODevice::read (QSerialPort): device not open QIODevice::read (QSerialPort): device not open QIODevice::read (QSerialPort): device not open QIODevice::read (QSerialPort): device not open QIODevice::read (QSerialPort): device not open
-
Hi, not sure what you are expecting as response?
Out of personal experience I know that at least the number of available ports can be opened in parallel. In my case 2 ports are available through serial (2 ports) to usb converter. That is on windows 10 64 bit.
Therefore there are a couple of questions you need to answer at least to yourself.
Can you handle at least one serial port?
How many ports do you have available?In my case I tested with one port and when I was able to handle that part I had to simply duplicate a part and opened 2 ports.
-
@CodeFreaks You will need to show at least some code in order to get help...
-
@koahnig
@aha_1980
Thanks for your reply.
I have 4 ports available and I can communicate with each one if I remove others.
Codes:for (int i = 0 ; i < List.size() ; i++ ){ tempSerialPort = new QSerialPort(List.at(i)); portPointer = i; tempSerialPort->setPortName(availableList.at(i).portName()); tempSerialPort->setBaudRate(QSerialPort::Baud9600,QSerialPort::AllDirections); tempSerialPort->setDataBits(QSerialPort::Data8); tempSerialPort->setParity(QSerialPort::NoParity); tempSerialPort->setStopBits(QSerialPort::OneStop); tempSerialPort->setFlowControl(QSerialPort::NoFlowControl); if (tempSerialPort->open(QIODevice::ReadWrite)){ qDebug()<<"Started!"; connect(tempSerialPort, &QSerialPort::readyRead, this, &MainWindow::readData); QByteArray data("Serial Test!"); tempSerialPort->write(data,qstrlen(data)); } }
QByteArray arreyData = tempSerialPort->readAll(); tempData += QString::fromStdString(arreyData.toStdString()); if(arreyData.contains("\r\n") && tempData.contains("Port1")){ qDebug()<<"Port 1: "; tempSerialPort->close(); // delete tempSerialPort; SerialPort1 = new QSerialPort(availableList.at(portPointer)); qDebug()<<tempData; tempData = ""; } if(arreyData.contains("\r\n") && tempData.contains("Port2")){ qDebug()<<"Port 2: "; tempSerialPort->close(); // delete tempSerialPort; SerialPort2 = new QSerialPort(availableList.at(portPointer)); qDebug()<<tempData; tempData = ""; } if(arreyData.contains("\r\n") && tempData.contains("Port3")){ qDebug()<<"Port 3: "; tempSerialPort->close(); // delete tempSerialPort; SerialPort3 = new QSerialPort(availableList.at(portPointer)); qDebug()<<tempData; tempData = ""; } ...
Logic of coding is that app. sends "Serial Test!" and devices return it with port id (Port1,...,Port4).
-
@CodeFreaks said in Multiple Serial Ports:
for (int i = 0 ; i < List.size() ; i++ ){
What is the definition of List ?
Edit: and maybe you describe what you want to do with the serial ports.
QByteArray arreyData = tempSerialPort->readAll();
tempData += QString::fromStdString(arreyData.toStdString());This could easily be:
tempData += QLatin1String(tempSerialPort->readAll());
(assuming the data is pure ASCII).
-
Hi,
@CodeFreaks said in Multiple Serial Ports:
tempSerialPort = new QSerialPort(List.at(i));
You are overwriting
tempSerialPort
on each iteration. -
What about printing the error you got if the
open
call failed ? You only do something if it succeeded. -
Before commenting on the implementation, let's focus on the architecture.
So again:
and maybe you describe what you want to do with the serial ports.
-
@SGaist
Thanks for reply.
I must add some codes for different error conditions, in future.
But right now I'm sure that ports are opened.
I think the problem should be about rewriting the tempSerialPort, as you said (but I don't have any idea ...).if (tempSerialPort[portPointer]->open(QIODevice::ReadWrite)){ qDebug()<<QString ("Port %1 Started!").arg(portPointer); ...
"Port 0 Started!" "Port 1 Started!" Ports Recognition Finished! Number of Availabe Ports: 2 Port 2: "Serial Test! (Port2)\r\n" QIODevice::read (QSerialPort): device not open QIODevice::read (QSerialPort): device not open QIODevice::read (QSerialPort): device not open QIODevice::read (QSerialPort): device not open QIODevice::read (QSerialPort): device not open QIODevice::read (QSerialPort): device not open
-
It might be a stupid question, but is it possible that you are trying to open each time the port again?
At least that would be a conclusion from your tempSerialPort set up as indicated by @SGaist.
The serial ports are not closed, they are staying open. When you try to open each time, you cannot the second time, because it is still open from first initialization.
The code fragments you are delivering are not giving enough detail to get a complete overview.
However, to work properly you need
- initilization section,
- reading section (apparently working with your signal slots),
- writing section (where you require access to previously opened ports)
- eventually closing section (for wrapping up when finished)
First and last section may be used only at start and end of application for instance. The reading and writing section would be could be looped over frequently.
-
c'mon, a bit more information would be needed, e.g.
- do you need to open/close them all the time?
- do you just write to them or do you also receive data?
I think closing a port if you don't need it for some time is good practice, remember to set it up correctly when opening again (someone else might have used it in meantime).
But I would not create and destroy them all the time. Rather have a member variable:
QList<QSerialPort *> m_ports
and add the tempSerialPort's to the list:m_ports.append(tempSerialPort)
.In the slot you can access them with
sender()
, so you know where the answer is coming from.When I see this:
if(arreyData.contains("\r\n")
then I think about
QSerialPort::canReadLine()
Regards
PS:
tempData = "";
can be replaced bytempData.clear();
-
@aha_1980
@koahnig
Thanks for replies.
I've connected readyRead signal to the Mainwindow::readData.
There is only one slot to read the data, only the last port in the list will receive the data.I need all ports to be open. I want to communicate with all of them.
@aha_1980 said in Multiple Serial Ports:
In the slot you can access them with sender(), so you know where the answer is coming from.
May I ask you to explain more?
-
@CodeFreaks said in Multiple Serial Ports:
QByteArray arreyData = tempSerialPort[portPointer]->readAll();
Because you are using portPointer which value won't change after your opened all your serial ports.
@CodeFreaks said in Multiple Serial Ports:
@aha_1980 said in Multiple Serial Ports:
In the slot you can access them with sender(), so you know where the answer is coming from.
May I ask you to explain more?
Use the doc Luke: QObject::sender.
-
Hi @CodeFreaks
I would like to address your design. It is extremely confusing. It is great you are checking port existence.
Since you close them before you re-open them as-needed, I would 1) Not worry about doing new QSerialPort into a temp pointer and 2) connecting it at this point.
Just create a stack-instance (or use 'new'), do your check, close the port and if you used 'new' delete it right away. This will ensure you keep your resources clear and free. All you need to do is make your like of valid ports.
When you finally open the port for use, do your connect. This will ensure your signal and its sender are valid. Doing your connect on the temp pointer (which you delete) frees that connection. Once you are sure you have your ports opened correctly you can use sender () in your slot as follows:
QSerialPort* port = dynamic_cast <QSerialPort*> (sender ()); // You can also use qobject_cast
if (port) {
...
}I use multiple ports with auto-baud detection constantly along with CAN and UDP so you are close and you have no fear! This is all good.