Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Communication Arduino-C++ do 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 next 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 an 'a' to the Arduino, and the ARduino must respond with 'b'. But when I read the port of the Arduino, I recieve '' only.

Anyone knows why I recieve '' instead of 'b'? Thanks for your time.

like image 392
Elseine Avatar asked Jan 13 '23 09:01

Elseine


1 Answers

Update: See bottom of this answer for the answer. TL;DR: You have so set the baud rate (and presumably all the other settings) after you open the port.

I believe this is a bug in the Windows implementation of QSerialPort. I haven't been able to narrow down the cause yet but I have the following symptoms:

  1. Load the Arduino (Uno in my case; Leonardo may behave very differently) with the ASCII demo. Unplug and replug the Arduino. Note that the TX light doesn't come on.

  2. Connect to it with Putty or the Arduino serial port monitor. This resets the Arduino and then prints the ASCII table. The TX light is on continuously as expected.

  3. Unplug/replug the Arduino and this time connect to it with a QSerialPort program. This time despite the port being opened ok the TX light never comes on and readyRead() is never triggered. Also note that the Arduino is not reset because by default QSerialPort does not change DTR. If you do QSerialPort::setDataTerminalReady(false); then pause for 10ms then set it true it will reset the Arduino as expected but it still doesn't transmit.

  4. Note that if you have an Arduino program that transmits data continuously (ASCII example stops), if you open the port with putty so that it starts transmitting and then open it with QSerialPort without unplugging the cable it will work! However as soon as you unplug/plug the cable it stops working again.

This makes me suspect that putty is setting some serial port option that is required by the arduino and reset when you replug the cable. QSerialPort obviously doesn't change this value.

Here are the settings used by Putty 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 by 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 = ...;

So I think it must be one of those unchanged values which makes the Arduino think that it isn't connected. From the DCB documentation I suspect fTxContinueOnXoff.

Ok I am going to write a little program to read these settings and see what changes.

Update 1

Ok I wrote my program and made the following discovery. The differences after running putty and just my Qt program were:

  • BaudRate: THIS WASN'T SET BY QT!!!!!!! It turns out you can only set the baud rate after you open the port.. Otherwise it is left at the previous value which is 0 when you first plug in the cable.
  • fDtrControl: Set to 1 by Putty, left at 0 by Qt.
  • fOutX and fInX: Both also set to 1 by Putty and left at 0 by Qt.

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

Update 2

While setting all the parameters I thought it would be a good idea to set the error policy to 'skip'. DON'T DO THIS! LEAVE IT ON IGNORE! Otherwise it fucks everything up and adds weird delays to all your communications.

like image 107
Timmmm Avatar answered Jan 21 '23 20:01

Timmmm