Shop OBEX P1 Docs P2 Docs Learn Events
Good QT Serial Port Library — Parallax Forums

Good QT Serial Port Library

KyeKye Posts: 2,200
edited 2014-02-27 11:14 in Propeller 1
Does anyone know of a good QT serial port library that does not toggle the DTR or the RTS lines whenever the serial port settings are changed? What serial library is used for the command line prop-load tool?

I've been working on a GUI in QT for my CMUcam4 and it's surprisingly difficult to implement basic serial connectivity that I was able to do with an Arduino/Prop.

I need to be able to change the baud rate while the serial port is open. Right now I'm using the QtSerialPort library. However, the library toggles the DTR and RTS liens whenever settings are changed...

Thank for any help,

Comments

  • Heater.Heater. Posts: 21,230
    edited 2012-11-03 06:16
    Kye,

    I have been hacking on the propgcc loader recently for use on the Raspberry Pi. You can browse through the code here:http://code.google.com/p/propgcc/source/browse/#hg%2Floader%2Fsrc or just check out the entire propgcc project and have at it.

    The loader does not use a cross platform serial library but rather has different serial handling code for each OS. osint_linux.c osint_cygwin.c etc etc.

    It does not support changing baud of an open port but you might be able to hack it around to do that.

    Why do that anyway? It's nothing to close the port and reopen at a different baud.
  • David BetzDavid Betz Posts: 14,516
    edited 2012-11-03 06:26
    Kye wrote: »
    Does anyone know of a good QT serial port library that does not toggle the DTR or the RTS lines whenever the serial port settings are changed? What serial library is used for the command line prop-load tool?

    I've been working on a GUI in QT for my CMUcam4 and it's surprisingly difficult to implement basic serial connectivity that I was able to do with an Arduino/Prop.

    I need to be able to change the baud rate while the serial port is open. Right now I'm using the QtSerialPort library. However, the library toggles the DTR and RTS liens whenever settings are changed...

    Thank for any help,
    The propeller-load program is not written using Qt. It is just a plain vanilla C program that uses posix functions to handle the serial I/O.
  • KyeKye Posts: 2,200
    edited 2012-11-03 08:26
    I see, the problem I am getting is that the serial port toggles the RTS and DTR lines on me constantly whenever any setting is changed. This is an issue as the CMUcam4 gets reset by this. Additionally, I need to be able to change the baud rate while communicating with the CMUcam4 to reach a higher BPS from 19200 to 250000 without reseting the CMUcam4.

    Do the libraries you were using David allow me to do this effectively?

    Thanks,
  • David BetzDavid Betz Posts: 14,516
    edited 2012-11-03 09:05
    Kye wrote: »
    I see, the problem I am getting is that the serial port toggles the RTS and DTR lines on me constantly whenever any setting is changed. This is an issue as the CMUcam4 gets reset by this. Additionally, I need to be able to change the baud rate while communicating with the CMUcam4 to reach a higher BPS from 19200 to 250000 without reseting the CMUcam4.

    Do the libraries you were using David allow me to do this effectively?

    Thanks,
    I'm not using any libraries. I'm just using the posix termio ioctls. You can find the code in osint_linux.c which, contrary to what it's name suggests, is also used for the Mac.
  • jazzedjazzed Posts: 11,803
    edited 2012-11-03 09:16
    Hi Kye,

    In windows there are some settings to disable RTS/DTR flipping (links below). Linux and Mac are much more difficult.
    The QExtSerialPort library has been reasonable except for needing the receive to be polled.

    Windows communications reference: http://msdn.microsoft.com/en-us/library/windows/desktop/aa363195(v=vs.85).aspx
    DTR/RTS control from the DCB struct: http://msdn.microsoft.com/en-us/library/windows/desktop/aa363214(v=vs.85).aspx

    Cross-platform serial port operations is a bear. In Linux/Mac, you may be able to set the NOHUP attribute while making the change (not persistent in Mac). Another trick to try if that doesn't work is having a second process open a port in shared mode while you do your change in the main program.

    --Steve
  • KyeKye Posts: 2,200
    edited 2012-11-03 12:26
    Hi Jazzed,

    Do you know if QTExtSerialPort will work for what I need to do? I need to be able to change the baud rate on the port without the DTR or RTS lines changing.

    Thanks,
  • jazzedjazzed Posts: 11,803
    edited 2012-11-03 19:00
    Kye wrote: »
    Do you know if QTExtSerialPort will work for what I need to do? I need to be able to change the baud rate on the port without the DTR or RTS lines changing.

    It works in the SimpleIDE 0-8-5 terminal. There is a baud-rate box in the terminal that can be changed at any time.

    I tested changing baud-rates just now with Windows7 and Linux. My Mac box is turned off to save energy - maybe someone else can check that. I don't remember ever having such trouble with the Mac, but I could be wrong.
  • KyeKye Posts: 2,200
    edited 2012-11-03 19:46
    Okay, I'm going to try that library.

    Thanks,
  • KyeKye Posts: 2,200
    edited 2012-11-04 07:49
    So, I'm having some weird problems with the qextserialport library/ It seems when I call the read function with a child thread even after verifying that there are bytes in a buffer that the child thread never returns from read. Here's the code...

    I spawn the child thread in this section...
    CMUCOM[COLOR=#000000].[/COLOR]setPortName[COLOR=#000000]([/COLOR][COLOR=#000000]item[/COLOR][COLOR=#000000]);[/COLOR]
    
    CMUCOM[COLOR=#000000].[/COLOR]setQueryMode[COLOR=#000000]([/COLOR][COLOR=#800080]QextSerialPort[/COLOR][COLOR=#000000]::[/COLOR][COLOR=#800080]Polling[/COLOR][COLOR=#000000]);[/COLOR]
    
    
    
    [COLOR=#808000]if[/COLOR][COLOR=#000000](![/COLOR]CMUCOM[COLOR=#000000].[/COLOR][COLOR=#000000][I]open[/I][/COLOR][COLOR=#000000]([/COLOR][COLOR=#800080]QIODevice[/COLOR][COLOR=#000000]::[/COLOR][COLOR=#800080]ReadWrite[/COLOR][COLOR=#000000]))[/COLOR]
    
    [COLOR=#000000]{[/COLOR]
    
    [COLOR=#800080]QMessageBox[/COLOR][COLOR=#000000]::[/COLOR]critical[COLOR=#000000]([/COLOR][COLOR=#808000]this[/COLOR][COLOR=#000000],[/COLOR]tr[COLOR=#000000]([/COLOR][COLOR=#008000]"Error"[/COLOR][COLOR=#000000]),[/COLOR]CMUCOM[COLOR=#000000].[/COLOR]errorString[COLOR=#000000]());[/COLOR]
    
    [COLOR=#808000]return[/COLOR][COLOR=#000000];[/COLOR]
    
    [COLOR=#000000]}[/COLOR]
    
    
    
    CMUCOM[COLOR=#000000].[/COLOR]setBaudRate[COLOR=#000000]([/COLOR][COLOR=#800080]BAUD19200[/COLOR][COLOR=#000000]);[/COLOR]
    
    CMUCOM[COLOR=#000000].[/COLOR]setDataBits[COLOR=#000000]([/COLOR][COLOR=#800080]DATA_8[/COLOR][COLOR=#000000]);[/COLOR]
    
    CMUCOM[COLOR=#000000].[/COLOR]setFlowControl[COLOR=#000000]([/COLOR][COLOR=#800080]FLOW_OFF[/COLOR][COLOR=#000000]);[/COLOR]
    
    CMUCOM[COLOR=#000000].[/COLOR]setParity[COLOR=#000000]([/COLOR][COLOR=#800080]PAR_NONE[/COLOR][COLOR=#000000]);[/COLOR]
    
    CMUCOM[COLOR=#000000].[/COLOR]setStopBits[COLOR=#000000]([/COLOR][COLOR=#800080]STOP_1[/COLOR][COLOR=#000000]);[/COLOR]
    
    CMUCOM[COLOR=#000000].[/COLOR]setTimeout[COLOR=#000000]([/COLOR][COLOR=#000080]500[/COLOR][COLOR=#000000]);[/COLOR]
    
    
    
    [COLOR=#008000]//Sleep[/COLOR][COLOR=#008000]sleep;[/COLOR]
    
    [COLOR=#008000]//[/COLOR][COLOR=#008000]sleep.msleep(100);[/COLOR]
    
    CMUCOM[COLOR=#000000].[/COLOR]setDtr[COLOR=#000000]([/COLOR][COLOR=#808000]true[/COLOR][COLOR=#000000]);[/COLOR]
    
    CMUCOM[COLOR=#000000].[/COLOR]setRts[COLOR=#000000]([/COLOR][COLOR=#808000]true[/COLOR][COLOR=#000000]);[/COLOR]
    
    [COLOR=#008000]//sleep.msleep(100);[/COLOR]
    
    CMUCOM[COLOR=#000000].[/COLOR]setDtr[COLOR=#000000]([/COLOR][COLOR=#808000]false[/COLOR][COLOR=#000000]);[/COLOR]
    
    CMUCOM[COLOR=#000000].[/COLOR]setRts[COLOR=#000000]([/COLOR][COLOR=#808000]false[/COLOR][COLOR=#000000]);[/COLOR]
    
    
    
    [COLOR=#800000]ui[/COLOR][COLOR=#000000]->[/COLOR][COLOR=#800000]statusBar[/COLOR][COLOR=#000000]->[/COLOR]showMessage[COLOR=#000000]([/COLOR]tr[COLOR=#000000]([/COLOR][COLOR=#008000]"Busy"[/COLOR][COLOR=#000000]));[/COLOR]
    
    [COLOR=#808000]this[/COLOR][COLOR=#000000]->[/COLOR]setEnabled[COLOR=#000000]([/COLOR][COLOR=#808000]false[/COLOR][COLOR=#000000]);[/COLOR]
    
    
    
    [COLOR=#008000]//[/COLOR]
    
    
    
    [COLOR=#800080]QEventLoop[/COLOR][COLOR=#000000]q[/COLOR][COLOR=#000000];[/COLOR]
    
    [COLOR=#800080]QFutureWatcher[/COLOR][COLOR=#000000]<[/COLOR][COLOR=#808000]int[/COLOR][COLOR=#000000]>[/COLOR][COLOR=#000000]watcher[/COLOR][COLOR=#000000];[/COLOR]
    
    connect[COLOR=#000000](&[/COLOR][COLOR=#000000]watcher[/COLOR][COLOR=#000000],[/COLOR][COLOR=#808000]SIGNAL[/COLOR][COLOR=#000000]([/COLOR]finished[COLOR=#000000]()),[/COLOR][COLOR=#000000]&[/COLOR][COLOR=#000000]q[/COLOR][COLOR=#000000],[/COLOR][COLOR=#808000]SLOT[/COLOR][COLOR=#000000]([/COLOR]quit[COLOR=#000000]()));[/COLOR]
    
    [COLOR=#800080]QFuture[/COLOR][COLOR=#000000]<[/COLOR][COLOR=#808000]int[/COLOR][COLOR=#000000]>[/COLOR][COLOR=#000000]future[/COLOR][COLOR=#000000]=[/COLOR][COLOR=#800080]QtConcurrent[/COLOR][COLOR=#000000]::[/COLOR]run[COLOR=#000000](&[/COLOR]CMUCAM[COLOR=#000000],[/COLOR][COLOR=#000000]&[/COLOR][COLOR=#800080]CMUcam4[/COLOR][COLOR=#000000]::[/COLOR]begin[COLOR=#000000]);[/COLOR]
    
    [COLOR=#000000]watcher[/COLOR][COLOR=#000000].[/COLOR]setFuture[COLOR=#000000]([/COLOR][COLOR=#000000]future[/COLOR][COLOR=#000000]);[/COLOR]
    
    
    
    [COLOR=#808000]if[/COLOR][COLOR=#000000]([/COLOR][COLOR=#000000]future[/COLOR][COLOR=#000000].[/COLOR]isRunning[COLOR=#000000]())[/COLOR]
    
    [COLOR=#000000]{[/COLOR]
    
    [COLOR=#000000]q[/COLOR][COLOR=#000000].[/COLOR]exec[COLOR=#000000]();[/COLOR]
    
    [COLOR=#000000]}[/COLOR]
    

    And then the child preforms I/O with this code.
    [COLOR=#808000]int[/COLOR][COLOR=#800080]CMUcom4[/COLOR][COLOR=#000000]::[/COLOR]read[COLOR=#000000]()[/COLOR]
    
    [COLOR=#000000]{[/COLOR]
    
    [COLOR=#808000]char[/COLOR][COLOR=#000000]c[/COLOR][COLOR=#000000];[/COLOR]
    
    
    
    [COLOR=#808000]switch[/COLOR][COLOR=#000000]([/COLOR]CMUCOM[COLOR=#000000].[/COLOR]read[COLOR=#000000](&[/COLOR][COLOR=#000000]c[/COLOR][COLOR=#000000],[/COLOR][COLOR=#000080]1[/COLOR][COLOR=#000000]))[/COLOR]
    
    [COLOR=#000000]{[/COLOR]
    
    [COLOR=#808000]case[/COLOR][COLOR=#000000]-[/COLOR][COLOR=#000080]1[/COLOR][COLOR=#000000]:[/COLOR][COLOR=#808000]throw[/COLOR]CMUCOM[COLOR=#000000].[/COLOR]errorString[COLOR=#000000]();[/COLOR]
    
    [COLOR=#808000]case[/COLOR][COLOR=#000080]0[/COLOR][COLOR=#000000]:[/COLOR][COLOR=#808000]return[/COLOR][COLOR=#000000]-[/COLOR][COLOR=#000080]1[/COLOR][COLOR=#000000];[/COLOR]
    
    [COLOR=#808000]default[/COLOR][COLOR=#000000]:[/COLOR][COLOR=#808000]break[/COLOR][COLOR=#000000];[/COLOR]
    
    [COLOR=#000000]}[/COLOR]
    
    
    
    [COLOR=#808000]return[/COLOR][COLOR=#000000]c[/COLOR][COLOR=#000000];[/COLOR]
    
    [COLOR=#000000]}[/COLOR]
    
    
    
    [COLOR=#800080]size_t[/COLOR][COLOR=#800080]CMUcom4[/COLOR][COLOR=#000000]::[/COLOR]write[COLOR=#000000]([/COLOR][COLOR=#800080]uint8_t[/COLOR][COLOR=#000000]c[/COLOR][COLOR=#000000])[/COLOR]
    
    [COLOR=#000000]{[/COLOR]
    
    [COLOR=#808000]return[/COLOR]CMUCOM[COLOR=#000000].[/COLOR]putChar[COLOR=#000000](([/COLOR][COLOR=#808000]char[/COLOR][COLOR=#000000])[/COLOR][COLOR=#000000]c[/COLOR][COLOR=#000000])[/COLOR][COLOR=#000000]?[/COLOR][COLOR=#000080]1[/COLOR][COLOR=#000000]:[/COLOR][COLOR=#808000]throw[/COLOR]CMUCOM[COLOR=#000000].[/COLOR]errorString[COLOR=#000000]();[/COLOR]
    
    [COLOR=#000000]}[/COLOR]
    
    
    
    [COLOR=#800080]size_t[/COLOR][COLOR=#800080]CMUcom4[/COLOR][COLOR=#000000]::[/COLOR]write[COLOR=#000000]([/COLOR][COLOR=#808000]const[/COLOR][COLOR=#808000]char[/COLOR][COLOR=#000000]*[/COLOR][COLOR=#000000]str[/COLOR][COLOR=#000000])[/COLOR]
    
    [COLOR=#000000]{[/COLOR]
    
    [COLOR=#800080]qint64[/COLOR][COLOR=#000000]len[/COLOR][COLOR=#000000]=[/COLOR]CMUCOM[COLOR=#000000].[/COLOR]write[COLOR=#000000]([/COLOR][COLOR=#000000]str[/COLOR][COLOR=#000000]);[/COLOR]
    
    
    
    [COLOR=#808000]if[/COLOR][COLOR=#000000]([/COLOR][COLOR=#000000]len[/COLOR][COLOR=#000000]==[/COLOR][COLOR=#000000]-[/COLOR][COLOR=#000080]1[/COLOR][COLOR=#000000])[/COLOR]
    
    [COLOR=#000000]{[/COLOR]
    
    [COLOR=#808000]throw[/COLOR]CMUCOM[COLOR=#000000].[/COLOR]errorString[COLOR=#000000]();[/COLOR]
    
    [COLOR=#000000]}[/COLOR]
    
    
    
    [COLOR=#808000]return[/COLOR][COLOR=#000000]([/COLOR][COLOR=#800080]size_t[/COLOR][COLOR=#000000])[/COLOR][COLOR=#000000]len[/COLOR][COLOR=#000000];[/COLOR]
    
    [COLOR=#000000]}[/COLOR]
    
    
    
    [COLOR=#800080]size_t[/COLOR][COLOR=#800080]CMUcom4[/COLOR][COLOR=#000000]::[/COLOR]write[COLOR=#000000]([/COLOR][COLOR=#808000]const[/COLOR][COLOR=#800080]uint8_t[/COLOR][COLOR=#000000]*[/COLOR][COLOR=#000000]buffer[/COLOR][COLOR=#000000],[/COLOR][COLOR=#800080]size_t[/COLOR][COLOR=#000000]size[/COLOR][COLOR=#000000])[/COLOR]
    
    [COLOR=#000000]{[/COLOR]
    
    [COLOR=#800080]qint64[/COLOR][COLOR=#000000]len[/COLOR][COLOR=#000000]=[/COLOR]CMUCOM[COLOR=#000000].[/COLOR]write[COLOR=#000000](([/COLOR][COLOR=#808000]const[/COLOR][COLOR=#808000]char[/COLOR][COLOR=#000000]*)[/COLOR][COLOR=#000000]buffer[/COLOR][COLOR=#000000],[/COLOR][COLOR=#000000]([/COLOR][COLOR=#800080]qint64[/COLOR][COLOR=#000000])[/COLOR][COLOR=#000000]size[/COLOR][COLOR=#000000]);[/COLOR]
    
    
    
    [COLOR=#808000]if[/COLOR][COLOR=#000000]([/COLOR][COLOR=#000000]len[/COLOR][COLOR=#000000]==[/COLOR][COLOR=#000000]-[/COLOR][COLOR=#000080]1[/COLOR][COLOR=#000000])[/COLOR]
    
    [COLOR=#000000]{[/COLOR]
    
    [COLOR=#808000]throw[/COLOR]CMUCOM[COLOR=#000000].[/COLOR]errorString[COLOR=#000000]();[/COLOR]
    
    [COLOR=#000000]}[/COLOR]
    
    
    
    [COLOR=#808000]return[/COLOR][COLOR=#000000]([/COLOR][COLOR=#800080]size_t[/COLOR][COLOR=#000000])[/COLOR][COLOR=#000000]len[/COLOR][COLOR=#000000];[/COLOR]
    
    [COLOR=#000000]}[/COLOR]
    
    
    
    [COLOR=#808000]int[/COLOR][COLOR=#800080]CMUcom4[/COLOR][COLOR=#000000]::[/COLOR]available[COLOR=#000000]()[/COLOR]
    
    [COLOR=#000000]{[/COLOR]
    
    [COLOR=#808000]int[/COLOR][COLOR=#000000]bytes[/COLOR][COLOR=#000000]=[/COLOR][COLOR=#000000]([/COLOR][COLOR=#808000]int[/COLOR][COLOR=#000000])[/COLOR]CMUCOM[COLOR=#000000].[/COLOR][COLOR=#000000][I]bytesAvailable[/I][/COLOR][COLOR=#000000]();[/COLOR]
    
    
    
    [COLOR=#808000]if[/COLOR][COLOR=#000000]([/COLOR][COLOR=#000000]bytes[/COLOR][COLOR=#000000]==[/COLOR][COLOR=#000000]-[/COLOR][COLOR=#000080]1[/COLOR][COLOR=#000000])[/COLOR]
    
    [COLOR=#000000]{[/COLOR]
    
    [COLOR=#808000]throw[/COLOR]CMUCOM[COLOR=#000000].[/COLOR]errorString[COLOR=#000000]();[/COLOR]
    
    [COLOR=#000000]}[/COLOR]
    
    
    
    [COLOR=#808000]return[/COLOR][COLOR=#000000]bytes[/COLOR][COLOR=#000000];[/COLOR]
    
    [COLOR=#000000]}[/COLOR]
    
    
    
    [COLOR=#808000]void[/COLOR][COLOR=#800080]CMUcom4[/COLOR][COLOR=#000000]::[/COLOR]flush[COLOR=#000000]()[/COLOR]
    
    [COLOR=#000000]{[/COLOR]
    
    CMUCOM[COLOR=#000000].[/COLOR]flush[COLOR=#000000]();[/COLOR]
    
    [COLOR=#000000]}[/COLOR]
    
    
    
    [COLOR=#808000]int[/COLOR][COLOR=#800080]CMUcom4[/COLOR][COLOR=#000000]::[/COLOR]peek[COLOR=#000000]()[/COLOR]
    
    [COLOR=#000000]{[/COLOR]
    
    [COLOR=#808000]char[/COLOR][COLOR=#000000]data[/COLOR][COLOR=#000000];[/COLOR]
    
    
    
    [COLOR=#808000]switch[/COLOR][COLOR=#000000]([/COLOR]CMUCOM[COLOR=#000000].[/COLOR]peek[COLOR=#000000](&[/COLOR][COLOR=#000000]data[/COLOR][COLOR=#000000],[/COLOR][COLOR=#000080]1[/COLOR][COLOR=#000000]))[/COLOR]
    
    [COLOR=#000000]{[/COLOR]
    
    [COLOR=#808000]case[/COLOR][COLOR=#000000]-[/COLOR][COLOR=#000080]1[/COLOR][COLOR=#000000]:[/COLOR][COLOR=#808000]throw[/COLOR]CMUCOM[COLOR=#000000].[/COLOR]errorString[COLOR=#000000]();[/COLOR]
    
    [COLOR=#808000]case[/COLOR][COLOR=#000080]0[/COLOR][COLOR=#000000]:[/COLOR][COLOR=#808000]return[/COLOR][COLOR=#000000]-[/COLOR][COLOR=#000080]1[/COLOR][COLOR=#000000];[/COLOR]
    
    [COLOR=#808000]default[/COLOR][COLOR=#000000]:[/COLOR][COLOR=#808000]break[/COLOR][COLOR=#000000];[/COLOR]
    
    [COLOR=#000000]}[/COLOR]
    
    
    
    [COLOR=#808000]return[/COLOR][COLOR=#000000]data[/COLOR][COLOR=#000000];[/COLOR]
    
    [COLOR=#000000]}[/COLOR]
    

    Anything come to mind that is wrong? (Please ignore the forum software removing and adding spaces randomly).

    Specifically, the child thread calls read and never returns from the function... The problem is, the child thread never calls read until it knows that bytes are available by first calling bytes available. The writing code appears to have no problems.

    What's weird is if I make the serial port event driven the code immediately crashes hard and has to close. I'm not sure why that happens...

    Thanks,

    ---

    Why is working with serial ports so hard on a PC... I've spent 3 days trying to do what was trivial on an Arduino or Propeller.
  • jazzedjazzed Posts: 11,803
    edited 2012-11-04 10:09
    Hi Kye. Encountering and learning to overcome these issues are par for the course.

    To draw on a widget, you need to set up a signal/slot function and emit the signal.

    Yes, like I said polling is the only reliable way with QExtSerialPort. I've never seen serial port event handling work on windows with QExtSerialPort.

    Look at the PortListener files below. You'll note that PortListener has a run() function that polls for data in the receiver and "emits" a signal that is setup to be handled by the console.cpp code below.

    It is common in a multi-tasking OS application to have these "producer/consumer" relationships when there is lots of overhead that just can't happen at "interrupt" time. In this case the producer (PortListener::run() ... emit ...) is a tiny thread that lives outside the main context of Qt and emits the signal updateEvent which becomes the consumer slot PortListener::updateReady(). The consumer calls Console::updateReady().

    http://code.google.com/p/propside/source/browse/propside/PortListener.cpp?name=spinside
    http://code.google.com/p/propside/source/browse/propside/PortListener.h?name=spinside

    All the drawing work is done here:
    http://code.google.com/p/propside/source/browse/propside/console.cpp?name=spinside


    In this case serial port handling is easier on Propeller and other devices because there is no GUI.

    An alternative to Qt is to stick with .net or delphi on Windows ... that's essentially what Parallax has done until now. I know that Chip has wrestled with this stuff too, and limiting to one platform reduces the complexity. Chip's desire for self-contained computing environment for example would simplify this greatly. I've called this idea the ApocalyChips, but it sounds practical in light of these serial-port struggles.
  • KyeKye Posts: 2,200
    edited 2012-11-04 11:10
    I know its par course jazzed :)

    Getting buttons and message prompts for the GUI was so much easier however. It just worked.

    Thank you,
  • jazzedjazzed Posts: 11,803
    edited 2012-11-04 11:49
    Just an observation. :)

    Not trying to be condescending or anything. Empathy was my goal - guess that didn't come through.

    It was hard to tell if the approach you were using was correct, so I generalized. Hope the example helps.
  • KyeKye Posts: 2,200
    edited 2012-11-04 13:44
    I think the problem is that the serial library object is owned by the main thread and it's child thread probably doesn't have the same rights to use it.

    I can do two things to solve this problem...

    I can create a program you like have where the child thread is always alive and working or I just make the master thread do everything and sprinkle processEvents calls in the lowest level code for the CMUcam4 interface.

    My goal with the GUI I am doing right now is for it to be simple... so, I'm going to try option 2 first.

    Thanks,
  • Dr_AculaDr_Acula Posts: 5,484
    edited 2012-11-04 16:08
    Not that this helps solve the problem, but I came across the same issue with C# and VB.net. Opening and closing serial port objects will reset those lines, and it is coded deep inside the object and the vibe out there on the internet forums was that it could not be changed. The prop is close to the metal, but I don't think we have had access to serial port uarts since ? about the mid 1990s.

    Fundamentally, I guess we are not using these signal lines for their intended purpose. Not that the propeller is the only one to do this (picaxe have similar issues).

    When writing code I've come to the reluctant conclusion that it is best to use just Tx and Rx and not use the handshaking lines at all. Poll for data regularly (either on the prop or on the PC), and have wakeup bytes at the beginning of packets. On the picaxe forum there were many discussions around radio and using 10101010 wakeup bytes (lots of ascii U's) to bias the volts prior to sending data. And of course with radio you need another channel to send handshaking signals so it is easiest not to. Things like a "reset" can still be sent as a packet of data rather than by toggling a line.

    My PC serial drivers tend to be a little unorthodox as a result - instead of waiting for a serial "event" I set up a clock and check for bytes on a regular basis, and if there are bytes, find out how many and retrieve that number of bytes. Wiring cables are simpler too if there are only 3 wires.

    But I guess you already have written code based on handshaking lines?
  • KyeKye Posts: 2,200
    edited 2012-11-07 12:27
    Oh, BTW. I got it working with QExtSerial. I have to fix the DTR and RTS issue still. But, otherwise it's operational.

    The GUI is coming out really nicely. QT is amazing. I wish, however, that they didn't move their website and kill all of their links.
  • jazzedjazzed Posts: 11,803
    edited 2012-11-07 12:56
    Kye wrote: »
    Oh, BTW. I got it working with QExtSerial. I have to fix the DTR and RTS issue still. But, otherwise it's operational.

    The GUI is coming out really nicely. QT is amazing. I wish, however, that they didn't move their website and kill all of their links.

    That's good news. Did you try http://qt-project.org/ ?
  • Heater.Heater. Posts: 21,230
    edited 2012-11-07 14:30
    Kye,
    I wish, however, that they didn't move their website and kill all of their links.

    Yeah. Not their fault really. Qt was started by TrollTech which was bought by Nokia. Nokia is now gutted by Microsoft. Who of course do not like cross-platform tools. So Qt is now farmed out to Digia.

    I do hope Qt can survive all this turmoil.
  • refaQtorrefaQtor Posts: 4
    edited 2012-12-13 09:57
    I keep coming back to qextserialport, as I've consistently had good luck with it "just working" across Linux and Windows. Here are the salient bits of code that I use, in case it is of help to you, or other webfarers.

    Regarding the "need to poll"... I manage happily with this code for many things. I connect the readRead() signal to my handling function, and away I go. BUT, this fails when I need better response time than about 1.3 seconds. (embedded Linux on 600MHz BeagleBone)
    MicroSerialPort::MicroSerialPort(QObject *parent) :
         QObject(parent),
         SerPort(new QextSerialPort()),
     ...
     {     
        SerPort->setBaudRate(BAUD9600);
         SerPort->setDataBits(DATA_8);
         SerPort->setStopBits(STOP_1);
         SerPort->setParity(PAR_NONE);
         SerPort->setPortName("ttyO5");
     
        connect(SerPort, SIGNAL(readyRead()), this, SLOT(readData()));
     
        SerPort->open(QIODevice::ReadOnly);
     }  
    
    void PanelSerialPort::readData()
     {     
        QByteArray bit(SerPort->read(1));
     ...
     }
    

    Waiting for the signal, as tidy as it is, was inadequate for a particular situation when connecting to my microcontroller. For faster response time (I needed < 85ms) I had to resort to polling as shown here. Best do this in another QThread, too.
    void MicroSerialPort::readConstantly()
     {     
        while(1)
         {
             QByteArray bit(SerPort->read(1));
             if (bit.count()>0)
             { 
            ... emit signalConnectedToHandlingProcess;
            }
         }
     }
    

    So, that is how it works for me. Hope it helps you, or others.
  • KyeKye Posts: 2,200
    edited 2012-12-13 13:53
    Thank you refaQtor, I managed to fix the DTR/RTS issue by editing the lowest level code to not use the DTR/RTS signals.

    I still haven't fix the threading issue yet. I think it has to do with the way I created the serial port.

    Thanks,
  • ErNaErNa Posts: 1,752
    edited 2014-02-24 15:53
    I just started to work with Qt and had the very same problem: build a simple terminal and communicate with the QuickStart board. I found this website: http://qt-project.org/doc/qt-5.1/qtserialport/qserialport.html#details and I can imagine, this info will be useful
    ErNa
  • KyeKye Posts: 2,200
    edited 2014-02-27 11:14
    Yeah, that class didn't exist 2 years ago.

    2 years ago... wow, time flies...
Sign In or Register to comment.