Arduino-C ++ Communication Does Not Read Arduino

I have the following code:

QSerialPort arduPort("COM5"); arduPort.setBaudRate(QSerialPort::Baud9600); arduPort.setDataBits(QSerialPort::Data8); arduPort.setParity(QSerialPort::NoParity); arduPort.setStopBits(QSerialPort::OneStop); arduPort.setFlowControl(QSerialPort::NoFlowControl); arduPort.open(QSerialPort::ReadWrite); cout<<arduPort.isReadable()<<endl; cout<<arduPort.isWritable()<<endl; arduPort.write("a"); QByteArray s=arduPort.readAll(); cout<<QString(s).toStdString()<<endl; 

And the following code in Arduino:

 int inByte = 0; void setup() { Serial.begin(9600); while(!Serial){;} int i=0; } void loop() { if(Serial.read()=='a') Serial.write('b'); } 

First I send 'a' to Arduino, and ARduino should reply with 'b'. But when I read the port of Arduino, I get "only".

Does anyone know why I get '' instead of 'b'? Thank you for your time.

+4
source share
3 answers

Update: see the bottom of this answer for an answer. TL DR: you set the baud rate (and, presumably, all other settings) after opening the port.

I believe this is a bug in implementing QSerialPort on Windows. I have not been able to narrow down the cause, but I have the following symptoms:

  • Download Arduino (Uno in my case, Leonardo can behave very differently) with an ASCII demo. Disconnect and replace the Arduino. Please note that the TX indicator does not light.

  • Connect to it using a Putty or Arduino monitor. This resets the Arduino and then prints the ASCII table. The TX indicator is lit continuously as expected.

  • Disconnect / replace Arduino and this time connect to it using the QSerialPort program. This time, despite opening the port, the TX indicator never lights up, and readyRead() never fires. Also note that Arduino does not reset, because by default QSerialPort does not change the DTR. If you do QSerialPort::setDataTerminalReady(false); , then pause for 10 ms, then set it to true , it will reset Arduino as expected, but it still doesn't transmit.

  • Note that if you have an Arduino program that continuously transfers data (the ASCII example stops), if you open the port with putty to start the transfer, and then open it with QSerialPort without disconnecting the cable, it will work! However, once you disconnect the cable / cable, it will stop working again.

This makes me suspect that putty sets the serial port parameter, which is required for arduino and reset when reconnecting the cable. QSerialPort obviously does not change this value.

Here are the Putty settings, as far as I can tell:

 dcb.fBinary = TRUE; dcb.fDtrControl = DTR_CONTROL_ENABLE; dcb.fDsrSensitivity = FALSE; dcb.fTXContinueOnXoff = FALSE; dcb.fOutX = FALSE; dcb.fInX = FALSE; dcb.fErrorChar = FALSE; dcb.fNull = FALSE; dcb.fRtsControl = RTS_CONTROL_ENABLE; dcb.fAbortOnError = FALSE; dcb.fOutxCtsFlow = FALSE; dcb.fOutxDsrFlow = FALSE; dcb.Parity = NOPARITY; dcb.StopBits = ONESTOPBIT; dcb.BaudRate = ...; dcb.ByteSize = ...; 

And QSerialPort :

 dcb.fBinary = TRUE; dcb.fDtrControl = unchanged! dcb.fDsrSensitivity = unchanged! dcb.fTXContinueOnXoff = unchanged! dcb.fOutX = FALSE; dcb.fInX = FALSE; dcb.fErrorChar = FALSE; dcb.fNull = FALSE; dcb.fRtsControl = RTS_CONTROL_DISABLE; dcb.fAbortOnError = FALSE; dcb.fOutxCtsFlow = FALSE; dcb.fOutxDsrFlow = unchanged! dcb.Parity = NOPARITY; dcb.StopBits = ONESTOPBIT; dcb.BaudRate = ...; dcb.ByteSize = ...; 

Therefore, I think that this should be one of the immutable values, which makes Arduino think that it is not connected. From the DCB documentation I suspect fTxContinueOnXoff .

Well, I will write a small program to read these settings and see what changes.

Update 1

Well, I wrote my program and made the following discovery. The differences after the putty was launched and my Qt program were as follows:

  • BaudRate: THIS WASN'T INSTALLED BY QT !!!!!!! It turns out that you can set the baud rate only after opening the port. . Otherwise, it will remain at the previous value, which will be 0 when you first connect the cable.
  • fDtrControl: Set the value 1 to Putty, remaining 0 to Qt.
  • fOutX and fInX: both are also set to 1 by Putty and remain at 0 by Qt.

After moving all my calls to the set...() function after opening it worked fine. I didn't have to bother with DtrControl or Out / InX. (Although I also set the DTR high manually.)

Update 2

When configuring all the parameters that, as I thought, it would be nice to set the skip for the error policy. DON'T DO IT! LEAVE IT ON IGNOR! Otherwise, he fucks everything and adds weird delays to all of your communications.

+4
source

Configuring ports before opening is not possible until Qt 5.2. The reason is that the original design was too low-level for the class, but rather object oriented. For a long time I was considered whether it should be changed, and in the end I decided to do it.

I just introduced a change, which is now under code verification, which will also make your original concept.

Here you can find information:

Allows you to set port values โ€‹โ€‹before opening

The summary can be read here for a change:

Let me set the port values โ€‹โ€‹before opening

This patch also changes the behavior of the open method. We do not use port discovery forever. It was a broken concept, and it is very unlikely that anyone would ever rely on it. If someone did this, they would be in trouble anyway, getting noisy warnings is useless and all that.

Another option was also considered that this behavior is not necessarily the default, but this will complicate the API too much without making a big gain.

The default port settings are now also normal 9600.8, N, 1 and without flow control. Also note that the serial port is automatically closed in an open way if any of the settings does not work.

Upgrade your version of Qt (at least to Qt 5.2) or you can back up this change yourself. Then you can write this code, and in fact it is even recommended:

 QSerialPort arduPort("COM5"); arduPort.setBaudRate(QSerialPort::Baud9600); arduPort.setDataBits(QSerialPort::Data8); arduPort.setParity(QSerialPort::NoParity); arduPort.setStopBits(QSerialPort::OneStop); arduPort.setFlowControl(QSerialPort::NoFlowControl); arduPort.open(QSerialPort::ReadWrite); 
+4
source

BaudRate: THIS IS NOT INSTALLED BY QT !!!!!!! It turns out you can set the baud rate after opening the port. Otherwise, it remains at the previous value equal to 0 when you first connect the cable.

Yes it's true. But it has been fixed and will be available in Qt 5.3

fDtrControl: Set the value 1 to Putty, remaining 0 to Qt.

Not. Qt do not touch the DTR signal when opened. This signal will only be cleared when DTR_CONTROL_HANDSHAKE has been set. Because QtSerialPort does not support DTR / DSR flow control. Thus, in any case, you can control the DTR with QSerialPort :: setDataTerminalReady (bool).

PS: I mean the current release of Qt 5.3

fOutX and fInX: both are also set to 1 by Putty and remain at 0 by Qt.

This flag is used only when using QSerialPort :: Software flow control (Xon / Xoff). But you are using QSerialPort :: NoFlowControl (as I can see from your code snippet), so everything is fine. Therefore, please check that you are using Putty with "None" flow control.

When configuring all the parameters that I thought it would be nice to set the skip for the error policy.

Use only the QSerialPort :: Ignore policy (default). Because other policies are outdated (all policies) and will be deleted in the future.

UPD:

dcb.fRtsControl = RTS_CONTROL_ENABLE;

Ahh, it seems that your Arduino is expecting the RTS signal to be turned on by default. In this case, you should use QSerialPort :: setRequestToSend (bool). But this is only possible in QSerialPort :: NoFlowControl mode.

those. RTS will always be in RTS_CONTROL_DISABLE or RTS_CONTROL_HANDSHAKE after opening the port (depends on your FlowControl settings, QSerialPort :: setFlowControl ()).

0
source

Source: https://habr.com/ru/post/1502444/


All Articles