Solved Problems writing data in the Serial Port
-
Hello, I'm having a problem with the serial port. I'm writing data to the serial port from a text-box and doing an echo.
This is the code for writing data.
A have a signal to the button that sends the command to write in the port.
QObject::connect(ui->pB_Write, SIGNAL(pressed()), SLOT(Totem_Serial_Send()));
This is the code that gets executed once the button is pressed.
void MainWindow::Totem_Serial_Send() { QString S_tex_val=ui->SP_Write->toPlainText(); Q_tex_val.append(S_tex_val.toUtf8()); if(Totem_Serial.isWritable()) { Totem_Serial.write(Q_tex_val,Q_tex_val.length()); Totem_Serial.flush(); } qDebug()<<(QString)S_tex_val; Q_tex_val.clear(); S_tex_val.clear(); }
For a better undestanding I'm going to show what's happening.
When I press the Write button, I echo the data, but is not always the data that I have written. What could be causing this problem? I know the reading code is working fine. I have tested the reading with separably with sensor measurements, but writing is not echoing the data right. I also tried to add a delay, but the problem persist.
Any help will be appreciate it.
-
Problem solved. I had to to the following.
//Unfold the array and send byte by byte with a delay QString S_tex_val=ui->SP_Write->toPlainText(); int n=S_tex_val.size(); QString val=S_tex_val.data()[n-1]; for(int i=0;i<n;i++) { QString val=S_tex_val.data()[i]; Q_tex_val=val.toUtf8(); Totem_Serial.write(Q_tex_val); Totem_Serial.flush(); QThread::msleep(10); Totem_Serial.waitForBytesWritten(200); } qDebug()<<(QString)S_tex_val;
it only worked with the delay and the waitforbytes.
-
@anfedres Are you using Qt's serial library to do the read/write? I ask because that has been tremendously buggy for me in the past.
If you are you may want to try a simple command line native application that takes Qt out of the picture and see if you still have the same read/write issue.
That said, it looks like noise or data corruption on the line to me. Although that may not hold true since the corrupted parts are the same with TEW_5. So now that I think about it, it probably isn't noise/data corruption.
What if you add a qDebug right before the write with the Q_tex_val so you can see if it is writing exactly what you think each time.
Beyond that I don't see enough code or have a good enough understanding of what tech you're using to help more than that.
-
There likely is some data corruption going on as @ambershark mentioned. If I set bit2 of the third letter of the test phrase 'TEST_5_' the 'S' becomes a 'W'. It also happens to be one of the bits that is toggled from 'S' to 'T' (which is missing in the received message).
Aside from COM13 being an unlucky number (a joke) it is likely a USB-Serial adapter. Some of these work really well while others are very poor and unreliable. I have seen one that would add extra characters under certain conditions. When I contacted the manufacturer with my findings they actually were pretty quick to send me a different model that didn't have this problem.
I assume you have some sort of loopback connector with Rx and Tx tied together. You can blob a bit of solder between pins 2 and 3 of a DB9 connector if you want to eliminate hardware beyond the USB-Serial adapter. If you have something more than a simple loopback connector you have a better chance of picking up noise.
The problems I found with USB-Serial adapters were sensitive to the configuration. If you are using something like 4800:E,8,1 (even parity) try a more common set such as 9600:N,8,1 or even down to 1200 baud. For your test program the settings shouldn't matter. You didn't show what serial port settings you are using.
This is not a Qt problem at all (or at least I can't image how this could possibly be something from Qt).
-
Hi @Rondog and @ambershark. I'm making sure that the value I'm sending to the UART is the same value I'm displaying, that's why in the code I have ```
qDebug()<<(QString)S_tex_val;
I have tried using TERRA TERM to see the data that I'm getting and it looks just fine. Any thoughts?
-
I just noticed something. If I write down only 2 or 3 letters in the port. I can have repetitiveness, but more than 3, the data gets corrupted some times.
-
I suspect the problem is in the read code, how do you read the data from the serial port?
-
Problem solved. I had to to the following.
//Unfold the array and send byte by byte with a delay QString S_tex_val=ui->SP_Write->toPlainText(); int n=S_tex_val.size(); QString val=S_tex_val.data()[n-1]; for(int i=0;i<n;i++) { QString val=S_tex_val.data()[i]; Q_tex_val=val.toUtf8(); Totem_Serial.write(Q_tex_val); Totem_Serial.flush(); QThread::msleep(10); Totem_Serial.waitForBytesWritten(200); } qDebug()<<(QString)S_tex_val;
it only worked with the delay and the waitforbytes.
-
@anfedres said in Problems writing data in the Serial Port:
it only worked with the delay and the waitforbyes.
This confirms my doubts, could you show how you read the bytes on the other side?
-
You don't need to delay (msleep) for each byte you write. I have used QSerialPort quite a bit and I never had a problem writing data including some fairly large blobs. I never seen it corrupted due to timing.
The QSerialPort::waitForBytesWritten(-1) is a good idea if you need to block until you know the data has actually been written out the serial port. QSerialPort does buffer the data you write so sending it doesn't guarantee it was actually written out the serial port. This is particularly important if you are writing large chunks of data and there is back and forth communications. For example, if you send a large blob of data then wait for a response to what was written you might 'time-out' because the data is likely still be written when you are already expecting a response to it.
The last comment could be part of the problem you have. I assume you do not open/close QSerialPort each time you want to write some data to the port. If you do this then some of what is written may be lost if it hasn't been written. Anything on the buffers will be discarded if the port is closed before it has been written.
-
More than likely you have a read issue like @vronin says. You definitely don't need to delay between sends.