Results 1 to 7 of 7

Thread: serial.readAll() strange problem reading form FTD232

  1. #1
    Join Date
    Dec 2013
    Posts
    7
    Thanks
    1
    Qt products
    Qt4
    Platforms
    Unix/X11

    Default serial.readAll() strange problem reading form FTD232

    Hi,
    several years ago I wrote a piece of code that reads data from a serial device. Code and application worked fine until today.
    When I start up the application, it gets some data but then stops reading.
    I have a "reconnect" button that closes and opens the port again. After reconnecting, still there is no data. But now when you move the mouse, data is read. As long as the mouse is moved, data comes in. Stop mouse moving, stops data reading.
    Strange.

    My system is Ubuntu 14.04,
    QT Version is (QT-Creator says this): Based on Qt 5.5.1 (GCC 4.9.1 20140922 (Red Hat 4.9.1-10), 64 bit)

    Here is how I read the data, the function is called by a timer every 20ms:
    Qt Code:
    1. void serial_service::serial_receive(uint8_t channel)
    2. {
    3. if (channel < NUM_OF_CHANNELS)
    4. {
    5. QByteArray data = service_data[channel].serial.readAll();
    6.  
    7. // we throw away data, if data.count() > SERIAL_BUFFER_SIZE
    8. foreach (const char rec_char, data)
    9. {
    10. // use ringbuffer for code compatibility with the microcontroller-application
    11. ringBufferWrite(&service_data[channel].receive_buffer, (uint8_t) rec_char);
    12. }
    13. }
    14. }
    To copy to clipboard, switch view to plain text mode 


    Here are my serial settings:
    Qt Code:
    1. void open_serial_port(uint8_t channel, QString serial_device_name)
    2. {
    3. service_data[channel].receive_buffer.readIndex = 0; // todo: put ringbuffer into a class
    4. service_data[channel].receive_buffer.writeIndex = 0;
    5.  
    6. if (serial_device_name.isEmpty())
    7. return;
    8.  
    9. if (channel < NUM_OF_CHANNELS)
    10. {
    11. if (service_data[channel].serial.isOpen())
    12. service_data[channel].serial.close();
    13.  
    14. service_data[channel].serial.setPortName(serial_device_name);
    15. service_data[channel].serial.open(QIODevice::ReadWrite);
    16.  
    17. service_data[channel].serial.setBaudRate(QSerialPort::Baud9600);
    18.  
    19. service_data[channel].serial.setDataErrorPolicy(QSerialPort::SkipPolicy);
    20.  
    21. service_data[channel].serial.setFlowControl(QSerialPort::NoFlowControl);
    22.  
    23. service_data[channel].serial.setDataBits(QSerialPort::Data8);
    24. service_data[channel].serial.setParity(QSerialPort::NoParity);
    25.  
    26. service_data[channel].serial.setStopBits(QSerialPort::OneStop);
    27.  
    28. //qDebug() << "serial_service::open_port: " << serial_device_name;
    29. }
    30. }
    To copy to clipboard, switch view to plain text mode 

    The problem is really urgent. It's a database application that reads lap-times from a stopwatch (arduino inside). We use it for Kart-Racing and next week we have a race...
    Thank you for any help!

    by the way: Code and schematics are open source and can be found at www.typsiland.de

  2. #2
    Join Date
    Mar 2009
    Location
    Brisbane, Australia
    Posts
    7,729
    Thanks
    13
    Thanked 1,610 Times in 1,537 Posts
    Qt products
    Qt4 Qt5
    Platforms
    Unix/X11 Windows
    Wiki edits
    17

    Default Re: serial.readAll() strange problem reading form FTD232

    The timer will be dependent on the event loop running. Are you blocking it somehwere? Where is your code executing if it is not transiting serial_receive?
    Why do you use a timer to call serial_receive() rather than just reacting when a serial port tells you that it has data?

  3. #3
    Join Date
    Dec 2013
    Posts
    7
    Thanks
    1
    Qt products
    Qt4
    Platforms
    Unix/X11

    Default Re: serial.readAll() strange problem reading form FTD232

    Hi Chris,
    thanks for your answer.
    The software worked fine for the last two years. I use it almost every weekend for logging the laptimes in training.
    I think that something has changed in the Qt-Libs. My OS is Ubuntu 14.04, there must have been some update during the last four weeks.

    You are right, the thing with the timer is a little strange. The reason behind is that I use parts of the code as well in the microcontroller.

    What I didn't mention was that one CPU thread was at 100% when the serial read was active. Commenting the readAll line out resulted in normal CPU behavior.

    My solution was to read again the good old "Serial programming HOWTO" by Gerry Frerking and Peter Baumann. Then I wrote a new Class that does the serial setup and reading.

    I don't know if it is of interest for viewers, but here is the code. There's potential for optimizations, but things are running now:
    (by the way I found a short discussion at Stack Overflow, describing the same issue on a Windows machine: http://stackoverflow.com/questions/2...rking-in-5-3-1)

    Qt Code:
    1. /*
    2.  * Thanks to Gary Frerking (gary@frerking.org) and Peter Bauman
    3.  * for writing the "Serial Programming Howto"
    4.  *
    5.  */
    6.  
    7.  
    8. #include "serial_low_level.h"
    9.  
    10. bool wait_flag = true;
    11. void signal_handler_IO (int status);
    12.  
    13. void signal_handler_IO (int status)
    14. {
    15. Q_UNUSED (status);
    16. //printf("received SIGIO signal.\n");
    17. wait_flag = false;
    18. }
    19.  
    20.  
    21. serial_low_level::serial_low_level()
    22. {
    23. file_desc = -1;
    24. }
    25.  
    26.  
    27. int serial_low_level::initialize_serial_port(QString devicename)
    28. {
    29. open_serial_port(devicename);
    30. if (file_desc < 0)
    31. return -1;
    32.  
    33. install_serial_handler();
    34.  
    35. //qDebug() << "serial_low_level::initialize_serial_port: file_desc = " << file_desc;
    36.  
    37. return file_desc;
    38. }
    39.  
    40.  
    41. void serial_low_level::open_serial_port(QString devicename)
    42. {
    43. // convert string to const char*
    44. QByteArray tmp_devname = devicename.toLatin1();
    45. const char *devname_as_char = tmp_devname.data();
    46.  
    47. //open the device in non-blocking way (read will return immediately)
    48. file_desc = open(devname_as_char, O_RDWR | O_NOCTTY | O_NONBLOCK);
    49. }
    50.  
    51.  
    52. void serial_low_level::install_serial_handler(void)
    53. {
    54. //install the serial handler before making the device asynchronous
    55. saio.sa_handler = &signal_handler_IO;
    56. sigemptyset(&saio.sa_mask); //saio.sa_mask = 0;
    57. saio.sa_flags = 0;
    58. saio.sa_restorer = NULL;
    59. sigaction(SIGIO,&saio,NULL);
    60.  
    61. // allow the process to receive SIGIO
    62. fcntl(file_desc, F_SETOWN, getpid());
    63.  
    64. // make the file descriptor asynchronous
    65. fcntl(file_desc, F_SETFL, FASYNC);
    66.  
    67. // set new port settings for canonical input processing
    68. newtio.c_cflag = B9600 | CRTSCTS | CS8 | CLOCAL | CREAD;
    69. newtio.c_iflag = IGNPAR;
    70. newtio.c_oflag = 0;
    71. newtio.c_lflag = 0;
    72. newtio.c_cc[VMIN] = 1;
    73. newtio.c_cc[VTIME] = 0;
    74. tcflush(file_desc, TCIFLUSH);
    75. tcsetattr(file_desc,TCSANOW,&newtio);
    76. }
    77.  
    78.  
    79. QByteArray serial_low_level::read_channel(void)
    80. {
    81. char tmp_buffer[255];
    82. int byte_count;
    83. QByteArray result;
    84.  
    85. if (wait_flag == true) //if input is available
    86. return result;
    87.  
    88. byte_count = read(file_desc,tmp_buffer,255);
    89. if (byte_count <= 0)
    90. return result;
    91.  
    92. // headnut. For some reason get/setRawData doesn't work
    93. for (int i=0; i<byte_count; i++)
    94. result.append(tmp_buffer[i]);
    95.  
    96. wait_flag = true; /* wait for new input */
    97.  
    98. //qDebug() << "serial_low_level::read_channel: byte_count = " << result.count() << " " << byte_count;
    99.  
    100. return result;
    101. }
    102.  
    103.  
    104. void serial_low_level::write_channel(char* data, int length)
    105. {
    106. int result = write(file_desc, data, length);
    107. Q_UNUSED(result);
    108. }
    109.  
    110.  
    111. void serial_low_level::close_serial_port(void)
    112. {
    113. close(file_desc);
    114. file_desc = -1;
    115. }
    116.  
    117.  
    118. bool serial_low_level::isOpen(void)
    119. {
    120. if (file_desc == -1)
    121. return false;
    122. else
    123. return true;
    124. }
    To copy to clipboard, switch view to plain text mode 


    The Header:
    Qt Code:
    1. #ifndef SERIAL_LOW_LEVEL_H
    2. #define SERIAL_LOW_LEVEL_H
    3.  
    4. #include <QString>
    5. #include <QByteArray>
    6. #include <qdebug.h>
    7.  
    8. #include <termios.h>
    9. #include <stdio.h>
    10. #include <unistd.h>
    11. #include <fcntl.h>
    12. #include <stdlib.h>
    13. #include <sys/signal.h>
    14. #include <sys/types.h>
    15.  
    16.  
    17. QStringList get_serial_ports(void);
    18.  
    19.  
    20. class serial_low_level
    21. {
    22. public:
    23. serial_low_level();
    24. int initialize_serial_port(QString devicename);
    25. QByteArray read_channel(void);
    26. void write_channel(char* data, int length);
    27. void close_serial_port(void);
    28. bool isOpen(void);
    29.  
    30.  
    31. private:
    32. void open_serial_port(QString devicename);
    33. void install_serial_handler(void);
    34.  
    35.  
    36. int file_desc;
    37. struct termios newtio;
    38. struct sigaction saio;
    39.  
    40. };
    41.  
    42. #endif // SERIAL_LOW_LEVEL_H
    To copy to clipboard, switch view to plain text mode 

  4. #4
    Join Date
    Jan 2009
    Location
    Russia
    Posts
    309
    Thanks
    2
    Thanked 43 Times in 42 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: serial.readAll() strange problem reading form FTD232

    Probably it is Ubuntu's bug. Please look on this: https://bugreports.qt.io/browse/QTBUG-48304

  5. The following user says thank you to kuzulis for this useful post:

    linoprit (22nd October 2015)

  6. #5
    Join Date
    Dec 2013
    Posts
    7
    Thanks
    1
    Qt products
    Qt4
    Platforms
    Unix/X11

    Default Re: serial.readAll() strange problem reading form FTD232

    Thanks.
    Yes, the kernel I use is one of the affected.
    Just reboot the machine with an older kernel? I'll do testing tomorrow and report the results.

  7. #6
    Join Date
    Jan 2009
    Location
    Russia
    Posts
    309
    Thanks
    2
    Thanked 43 Times in 42 Posts
    Qt products
    Qt4
    Platforms
    Unix/X11 Windows

    Default Re: serial.readAll() strange problem reading form FTD232

    > Just reboot the machine with an older kernel?

    Yes

  8. #7
    Join Date
    Dec 2013
    Posts
    7
    Thanks
    1
    Qt products
    Qt4
    Platforms
    Unix/X11

    Default Re: serial.readAll() strange problem reading form FTD232

    Hi kuzulis,
    you are right!
    As mentioned above, I rebooted with kernel 3.13.0-62-generic and the serial-readAll works. Back to Kernel 3.13.0-65-generic the problem still exists (surprise, surprise,...).

    So all this has nothing to do with qt. It's really a kernel bug.
    (Never had such a nasty bug affecting me since the last 12 years...)

    Once again - Thank you very much!

Similar Threads

  1. Re: Reading binary files using readAll problem [SOLVED]
    By Miss Engineer in forum Qt Programming
    Replies: 0
    Last Post: 18th September 2014, 15:57
  2. Replies: 2
    Last Post: 15th March 2014, 11:54
  3. Reading/writing a serial port through USB
    By jvwlong in forum Newbie
    Replies: 2
    Last Post: 28th June 2012, 11:09
  4. Serial Port Reading problem
    By sfabel in forum Qt Programming
    Replies: 12
    Last Post: 18th February 2010, 14:59
  5. Replies: 1
    Last Post: 1st July 2009, 00:37

Tags for this Thread

Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •  
Digia, Qt and their respective logos are trademarks of Digia Plc in Finland and/or other countries worldwide.