Need explanation QSerialPort vs Pyserial



  • I'm trying to reset an Arduino Leonardo into boot loader mode by opening and closing the usb serial with a baudrate of 1200. This does not seem to work with Qt. When I tried this with PySerial, just opening and closing the port it works. I also tested with stty and that also works.

    Does anybody have any ideas why QSerialPort does not work ?

    void Programmer::resetAvr()
    {
        m_port.setBaudRate(QSerialPort::Baud1200);
        m_port.setDataBits(QSerialPort::Data8);
        m_port.setParity(QSerialPort::NoParity);
        m_port.setStopBits(QSerialPort::OneStop);
        m_port.setFlowControl(QSerialPort::NoFlowControl);
        m_port.setPortName(m_portName);
    
        if(m_port.open(QIODevice::ReadWrite) == true)
        {
            m_port.close();
        }
    }
    
    #!/usr/bin/env python
    
    import serial, sys
    
    serialPort = sys.argv[1]
    print serialPort
    
    ser = serial.Serial(
        port=serialPort,
        baudrate=1200,
        parity=serial.PARITY_NONE,
        stopbits=serial.STOPBITS_ONE,
        bytesize=serial.EIGHTBITS
    )
    ser.isOpen()
    ser.close()             # close port
    
    stty -F /dev/ttyACM0 1200 cs8 -cstopb -parenb
    

  • Qt Champions 2017

    Hi @moscowbob,

    just opening and closing a serial port without sending data will not change anything for the other side (independent of the baud rate).

    So there is most likely a control line (RTS, CTS, RTR) involved that actually does the reset? Do you have a description how the reset is supposed to work?

    And if it is working like this, there can be indeed a difference between pyserial and QSerialPort.



  • @aha_1980 , thanks for response.
    The connection is a USB CDC connection, the AT32U4 chip has an embedded usb that is configured as a virtual comport. So there are no control lines connected. As I understand, when the host opens the port, it will configure the device endpoint and it is there where the 1200 baud is used to reset the device into bootloader mode.

    I have captured the usb conversation between the host pc and device for all 3 methods and the QSerialPort conversation looks completely different - unfortunately my knowledge is very limited when it comes to this, so if you want, I can post the three Wireshark capure files for viewing.


  • Qt Champions 2017

    Hi @moscowbob,

    yeah, you can post them, but I have to admit that my knowledge is also limited here :)

    But maybe someone else can help you here...



  • What is the accepted method for the forum when posting files - I do not have privilege to upload here ?

    Thanks


  • Qt Champions 2017

    @moscowbob
    Hi
    It only wants
    alt text
    What type are you trying ?



  • Thanks @mrjj ,
    The capture files I have are wireshark .pcapng or a zip file containing all 3 captures.


  • Qt Champions 2017

    Not sure it will accept those.



  • No there is something else wrong, I just tried to upload a simple text file with .c extension and I just get the same message

    " ERROR
    You do not have enough privileges for this action."



  • Well after spending many hours digging through usb protocol documentation I have finally got to a point where I can say the problem is with QSerialPort. Since I cannot upload files I will try and explain.

    PySerial and linux stty both exhibit the same behavior when viewed in wireshark usb capture:

    1. Host send command 0x22 with value 0x03 to enable RTS and DTR
    2. Host send comand 0x20 with 7 bytes data to configure BAUD, DATABITS, PARITY and STOPBITS
      1200, 8, n, 1
    3. Host send command 0x22 with value 0x00 to disable RTS/DTR

    Now the device resets and goes into boot mode.

    QSerialPort behaves as follows - Open/Close :

    1. Host send command 0x22 with value 0x03 to enable RTS and DTR
    2. Host send command 0x20 with 7 bytes data to configure BAUD, DATABITS, PARITY and STOPBITS
      (all these configurations are sent)
      400000, 8, n, 1
      9600, 8, n, 1
      1200, 8, n, 1
      115200, 8, n, 1
    3. Host send command 0x22 with value 0x00 to disable RTS and DTR
    #include <QCoreApplication>
    #include <QDebug>
    #include <QSerialPort>
    
    int main(int argc, char *argv[])
    {
        QCoreApplication a(argc, argv);
        QSerialPort mPort;
    
        mPort.setBaudRate(QSerialPort::Baud1200);
        mPort.setDataBits(QSerialPort::Data8);
        mPort.setStopBits(QSerialPort::OneStop);
        mPort.setParity(QSerialPort::NoParity);
        mPort.setPortName("/dev/ttyACM0");
    
        qDebug() << "Open Port";
        mPort.open(QIODevice::ReadWrite);
        if(mPort.isOpen())
        {
            qDebug() << "Close Port";
            mPort.close();
        }
    
        exit(0);
    //    return a.exec();
    }
    

    Anybody ??



  • Well, finally a breakthrough !

    It turn out that the deprecated function

    mPort.setSettingsRestoredOnClose(false);
    

    Does the trick.

    Although the Arduino now does reset, since QSerialPort does not send the restored values before closing the port, it still sends a garbage packet before setting the 1200 baud. I have not figured that one out yet, and I am now getting tired.

    So I will mark this as solved but will raise another post to query the strange behavior when QSerialPort opens.


  • Qt Champions 2017

    @moscowbob

    Please report this at bugreports.qt.io (and provide a link to the bug here).

    You will have better possibilities to discuss the behavior with the developers there and you should also be able to attach the Wireshark logs.

    Thanks.


Log in to reply
 

Looks like your connection to Qt Forum was lost, please wait while we try to reconnect.