Sending files over RS-485 using QtSerialPort/QSerial



  • Hi,

    I am trying to send a file over a serial port with half-duplex RS-485 interface using the QSerialPort library to another device (imx6).
    I've managed to get the devices to read and write small amounts of data and my question is where do I go from here to be able to send HD picture files over said serial port.

    Below are my code

    #include "mainwindow.h"
    #include <QApplication>
    #include <QtSerialPort/QtSerialPort>
    #include <QString>
        QSerialPort serial;
    
    void sendData ()
    {
        qDebug() << "I sendData";
    
        QByteArray test;
    
        test[0] = 'x';
        test[1] = 'D';
        qDebug() << "announce start";
        serial.write(test);
        serial.flush();
        serial.waitForBytesWritten(1000);
        qDebug() << "announce end";
    
    }
    
    void readData ()
    {
       qDebug() << "I readData";
       QObject::connect(&serial ,&QSerialPort::readyRead, [&]
       {
    
    
        qDebug() << "New data Available: ";
        QByteArray datas = serial.readAll();
        qDebug() << datas;
    
        if (datas=="a"){
            sendData();
        }
    });
    
    }
    
    int main(int argc, char *argv[])
    {
        QApplication a(argc, argv);
        MainWindow w;
        w.show();
    
        serial.setPortName("/dev/ttymxc2");
        serial.setBaudRate(QSerialPort::Baud9600);
        serial.setDataBits(QSerialPort::Data8);
        serial.setParity(QSerialPort::NoParity);
        serial.setStopBits(QSerialPort::OneStop);
        serial.setFlowControl(QSerialPort::NoFlowControl);
    
    
        if (serial.open(QIODevice::ReadWrite))
        {
            qDebug() << "Connected";
            readData();
        }
        else {
            qDebug() << "Error";
        }
    
        return a.exec();
    }
    

    I would appreciate any help you have for me.


  • Moderators

    Hi @ivar, and welcome!

    @ivar said in Sending files over RS-485 using QtSerialPort/QSerial:

    send HD picture files over said serial port

    May I ask why you want to use RS-485 instead of a network protocol or Bluetooth? RS-485 is a very slow and error-prone protocol for transferring large files.

    But if you wish to continue, study an established protocol like XMODEM or YMODEM and add it to your RS-485 comms.



  • @JKSH said in Sending files over RS-485 using QtSerialPort/QSerial:

    XMODEM or YMODEM

    Thank you for your answer!

    I do not have the option of using bluetooth or a network protocol. I am limited to using solely RS-485 to transmit these files.
    I'm familiar with XMODEM and YMODEM but do you know if I have any other options?


  • Moderators

    @ivar said in Sending files over RS-485 using QtSerialPort/QSerial:

    I'm familiar with XMODEM and YMODEM but do you know if I have any other options?

    If you are limited to RS-485, then I can't think of any better options than XMODEM and its friends.

    I can think of a simpler option, but it probably has a high failure rate: Treat your image as a long byte array and just send the whole byte array over RS-485.



  • @JKSH I've tried XMODEM, YMODEM and ZMODEM but the problem is my ARM board I have to manually change the RX/TX of the port I am using, rendering the protocols useless to me.. At least to my knowledge.

    I'm exploring the avenue of converting the pictures into byteArrays but are having some problems converting the arrays back into pictures when I've got them into byteArrays.


  • Moderators

    @ivar said in Sending files over RS-485 using QtSerialPort/QSerial:

    having some problems converting the arrays back into pictures when I've got them into byteArrays.

    Post your code.



  • @JKSH
    Alright, so this is a test program where i try to convert a QImage > QPixmap > QByteArray and then send it over a serial port and then convert the QByteArray back into a QPixMap and finally display it on a label..

    My main problem seem to be at line 73-78 (I highlighted it with "PROBLEM, END OF PROBLEM") where I can send the data over just fine but I recieve it back all chopped up into smaller bits. I try to append the result into a new array that I can then rework into a QPixmap but I can't get it to work..

    I am very new to QT so there is alot of debugging going on to help me keep track on what is happening.

    #include "mainwindow.h"
    #include <QApplication>
    #include <QImage>
    #include <QByteArray>
    #include <QPixmap>
    #include <QBuffer>
    #include <QLabel>
    #include <QDebug>
    #include <QtSerialPort/QSerialPort>
    
    //Creates a QImage from a local fil added as a QResource
    QImage getImage () {
        QImage pic(":/smiley.png");
        return pic;
    }
    
    //Converts a QImage to QPixmap to QByteArray
    QByteArray convertToArray(QImage img) {
    
        QPixmap pixmap = QPixmap::fromImage(img);
        qDebug() << "IMG > PIX " << QPixmap::fromImage(img);
        QByteArray picArray;
        QBuffer buffer(&picArray);
        buffer.open(QIODevice::WriteOnly);
        pixmap.save(&buffer, "PNG");
    
        //Prints the array
        qDebug() << "ARRAY START";
        for (int i = 0; i < sizeof (picArray); i++) { qDebug() << picArray[i]; }
        qDebug() << "ARRAY END";
    
        //Returns true if it was successful to save it as a bytearray
        qDebug() << "SAVED AS BYTEARRAY: " <<pixmap.save(&buffer, "PNG");
        return picArray;
    }
    
    //Converts a QByteArray containing a picture to QPixmap
    QPixmap convertToPixmap(QByteArray arr) {
        QPixmap pic;
        pic.loadFromData(arr);
        return pic;
    }
    
    int main(int argc, char *argv[])
    {
        QApplication a(argc, argv);
        MainWindow w;
    
        QLabel label;
        QPixmap pic;
        QByteArray pixmapArray, datas, array;
        QSerialPort serial;
    
        serial.setPortName("/dev/ttyUSB0");
        serial.setBaudRate(QSerialPort::Baud9600);
        serial.setDataBits(QSerialPort::Data8);
        serial.setParity(QSerialPort::NoParity);
        serial.setStopBits(QSerialPort::OneStop);
        serial.setFlowControl(QSerialPort::NoFlowControl);
    
        if(serial.open(QIODevice::ReadWrite))
            qDebug() << "Device Connected";
        else
            qDebug() << "Error: Device not connected";
    
        pixmapArray = convertToArray(getImage());
    
        serial.write(pixmapArray);
        serial.flush();
        serial.waitForBytesWritten(1000);
        serial.waitForReadyRead(1000);
    //PROBLEM
        QObject::connect(&serial, &QSerialPort::readyRead, [&]{
            qDebug() << "New data available: " << serial.bytesAvailable();
            datas = serial.readAll();
            array.append(datas);
            qDebug() << array;
        });
    //END OF PROBLEM
        qDebug() << "RECIEVED ARRAY START";
        for (int i = 0; i < sizeof (array); i++) { qDebug() << array[i]; }
        qDebug() << "RECIEVED ARRAY END";
        qDebug() << sizeof(array);
    
    
        pic = convertToPixmap(array);
        label.setPixmap(pic);
        label.setGeometry(1, 1, 150, 150);
        label.show();
    
        QObject::connect(&serial, static_cast<void(QSerialPort::*)(QSerialPort::SerialPortError)>(&QSerialPort::error), [&](QSerialPort::SerialPortError error) {
            qDebug() << "An error Occured: " << error;
            a.quit();
        });
    
        return a.exec();
    }
    
    

  • Qt Champions 2018

    @ivar

    I can send the data over just fine but I recieve it back all chopped up into smaller bits. I try to append the result into a new array that I can then rework into a QPixmap but I can't get it to work..

    And that is the whole problem with serial ports, and the reason why protocols like XMODEM exists.

    You will need to invest more in your protocol, you need to know where data starts and end.

    For binary data like pictures, this is not trivial.


  • Moderators

    @ivar said in Sending files over RS-485 using QtSerialPort/QSerial:

    My main problem seem to be at line 73-78 (I highlighted it with "PROBLEM, END OF PROBLEM") where I can send the data over just fine but I recieve it back all chopped up into smaller bits.

    All communications protocols break large pieces of data into smaller chunks for transmission.

    High-level comms protocols will handle the breaking and reassembing process for you automatically. High-level comms protocols also have a mechanism to detect when a chunk gets lost or corrupted, and re-transmit the chunk when a problem is detected.

    However, RS-485 doesn't have built-in chunk management, so you need to write your own. XMODEM is an attempt to add chunk management to low-level serial protocols (like RS-232/RS-485). If you don't use XMODEM, then you must invent your own protocol to do what XMODEM does.

    Actually, I realized that I shouldn't have said this is the "simpler" way. The core idea is simple ("transmit an array of bytes"), but you need to write lots of extra code to make it work properly.

    i try to convert a QImage > QPixmap > QByteArray and then send it over a serial port and then convert the QByteArray back into a QPixMap and finally display it on a label..

    You don't need to do so many conversions. For a simple setup, just use QDataStream to serialize the QImage into a QByteArray. Do the reverse on the other size to deserialize:

    // Serializing
    QImage img = ...
    QByteArray bytes;
    QDataStream stream(&bytes, QIODevice::WriteOnly);
    stream << img;
    
    // Deserializing
    QByteArray bytes = ...
    QDataStream stream(bytes);
    QImage img;
    stream >> img;
    
    // ...
    
    label.setPixmap( QPixmap::fromImage(img) );
    

    Your main challenge is between the serializing step and the deserializing step: You need to get the bytes from one device to another in the correct order.

    Start small. Use a 2x2 image (example: 1 red pixel, 1 green pixel, 1 blue pixel, 1 black pixel)

    I try to append the result into a new array that I can then rework into a QPixmap but I can't get it to work..

    Compare the individual bytes on the sender side and the receiver side. What's different?

    I am very new to QT so there is alot of debugging going on to help me keep track on what is happening.

    Debugging is good!

    You actually have 2 separate problems to deal with:

    1. Asynchronous programming (using Qt signals and slots)
    2. Using communications protocols in general (not related to Qt)
    //PROBLEM
        QObject::connect(&serial, &QSerialPort::readyRead, [&]{
            qDebug() << "New data available: " << serial.bytesAvailable();
            datas = serial.readAll();
            array.append(datas);
            qDebug() << array;
        });
    //END OF PROBLEM
        qDebug() << "RECIEVED ARRAY START";
        for (int i = 0; i < sizeof (array); i++) { qDebug() << array[i]; }
        qDebug() << "RECIEVED ARRAY END";
        qDebug() << sizeof(array);
    
    
        pic = convertToPixmap(array);
        label.setPixmap(pic);
        label.setGeometry(1, 1, 150, 150);
        label.show();
    }
    
    

    Asynchronous programming is an important concept to understand.

    Your code calls qDebug() << "RECIEVED ARRAY START"; and shows the label right after you call QObject::connect(). It only waits for the signal-slot connection to be made -- it doesn't wait for any data to be received!

    So, you must implement a way to:

    1. Keep track of the data chunks that have been received
    2. Only update the label after the last chunk has been received.

    @ivar said in Sending files over RS-485 using QtSerialPort/QSerial:

    I have to manually change the RX/TX of the port I am using, rendering the protocols useless to me..

    I'm not sure what you mean here. What does "manually change the TX/RX of the port" mean? Why does this block XMODEM?

    To use XMODEM in your code, you just need an XMODEM library or write the code into your own program: https://gist.github.com/zonque/0ae2dc8cedbcdbd9b933



  • @JKSH Thanks alot for your answer! Really appreciate the help.

    What I mean by "manually change TX/RX of the port" is that the device im sending it to does not have a Automatic Direction Control So to change from listening to sending i have to set a GPIO high or low e.g "$: echo 1 >> /sys/class/gpio/gpio123/value
    so when I run XMODEM it always get stuck after the first ACK.

    I will follow your tips and try it out with a small 2x2 picture first and work my way from there. As well as looking into the XMODEM library.


  • Qt Champions 2018

    @ivar I'm still wondering if half-duplex serial lines are optimal for transmitting HD pictures.

    Ex: on 115 kBaud, you get approx. 10 kByte/sec.

    Transmitting 600 kByte takes a full minute! Have you considered this?



  • @aha_1980 I have, and you are right they most likely are not optimal for the purpose but my circumstances are set.
    Im just trying to make a program that works. Slow or not.



  • @JKSH Hello sir!

    So I have now got the program to send over the array of bytes and then put it together in the correct order. I now stand before the problem of closing my

        QObject::connect(&serial ,&QSerialPort::readyRead, [&] {
            qDebug() << "New data Available: ";
            QByteArray datas;
            datas = serial.readAll();
            imgBytes.append(datas);
            qDebug() << imgBytes;
        });
    

    I'm not very familiar with lambda expressions but as I've understood it this expression keeps listening to the port even when there is no more data being available.

    Any tips on how I can exit the loop? (I solved this temporarily by using a counter just so I could move forward)

    I do however have some problems with creating a image from the arrays. I've used the serializing/deserializing suggestion you posted earlier.

    this is my array before transmission

    "\x00\x00\x00\x01\x89PNG\r\n\x1A\n\x00\x00\x00\rIHDR\x00\x00\x00>\x00\x00\x00<\b\x06\x00\x00\x00>\t\tO\x00\x00\x00\tpHYs\x00\x00\x0E\xC4\x00\x00\x0E\xC4\x01\x95+\x0E\x1B\x00\x00\x00\x93IDATh\x81\xED\xD9""A\x11\x83P\x10\x04\xD1\xF9)\xB4\xA0\x06-\x89\x97hA\rf>\x07\xB8`\x80""9t?\x03S]{\xDC\x91u\xCE\x14\xCD\xE3W\xD9\xFDTVo\xAD\xE8$Yj\xCB\x0F\xFF\x97\xF7\xBE\xDD\x8B""7\x19Nc8\x8D\xE1""4\x86\xD3\x18Nc8\x8D\xE1""4\x86\xD3\x18Nc8\x8D\xE1""4\xD8\xF0\x91\xA4\xF2""B\xDA\xAA\x8F+\xF0\xC5k\xE1\xFBh-_\xBC""8\x8D\xE1""4\x86\xD3\x18Nc8\x8D\xE1""4\x86\xD3\x18Nc8\x8D\xE1""4\x86\xD3\x18Nc8\x8D\xE1""4\xB5p\xDF\xC4%'p\xA7\fw\x0F\xF4 \xAD\x00\x00\x00\x00IEND\xAE""B`\x82"
    

    and after recieval

    "\x00\x00\x00\x01\x89PNG\r\n\x1A\n\x00\x00\x00\rIHDR\x00\x00\x00>\x00\x00\x00<\b\x06\x00\x00\x00>\t\tO\x00\x00\x00\tpHYs\x00\x00\x0E\xC4\x00\x00\x0E\xC4\x01\x95+\x0E\x1B\x00\x00\x00\x93IDATh\x81\xED\xD9""A\x11\x83P\x10\x04\xD1\xF9)\xB4\xA0\x06-\x89\x97hA\rf>\x07\xB8`\x80""9t?\x03S]{\xDC\x91u\xCE\x14\xCD\xE3W\xD9\xFDTVo\xAD\xE8$Yj\xCB\x0F\xFF\x97\xF7\xBE\xDD\x8B""7\x19Nc8\x8D\xE1""4\x86\xD3\x18Nc8\x8D\xE1""4\x86\xD3\x18Nc8\x8D\xE1""4\xD8\xF0\x91\xA4\xF2""B\xDA\xAA\x8F+\xF0\xC5k\xE1\xFBh-_\xBC""8\x8D\xE1""4\x86\xD3\x18Nc8\x8D\xE1""4\x86\xD3\x18Nc8\x8D\xE1""4\x86\xD3\x18Nc8\x8D\xE1""4\xB5p\xDF\xC4%'p\xA7\fw\x0F\xF4 \xAD\x00\x00\x00\x00IEND\xAE""B`\x82"
    

    Any thoughts?



  • @JKSH I thought I would include my programs sending & recieving if you would take the time to help me out,

    SerialportSend

    #include "mainwindow.h"
    #include <QApplication>
    #include <QtSerialPort/QSerialPort>
    #include <QtDebug>
    #include <QByteArray>
    #include <QDataStream>
    
    QSerialPort serial;
    
    void sender() {
        QImage img(":/fourColors.png");
        QByteArray imgBytes;
        QDataStream stream(&imgBytes, QIODevice::WriteOnly);
        stream << img;
        qDebug() << "Transmission starting";
        qDebug() << imgBytes;
    
        serial.write(imgBytes);
        qDebug() << "..";
        serial.flush();
        serial.waitForReadyRead(1000);
        serial.waitForBytesWritten(1000);
        qDebug() << "Transmission finished";
    }
    
    int main(int argc, char *argv[])
    {
        QApplication a(argc, argv);
        MainWindow w;
        //w.show();
    
        serial.open(QSerialPort::WriteOnly);
        serial.setPortName("ttyUSB0");
        serial.setParity(QSerialPort::NoParity);
        serial.setStopBits(QSerialPort::OneStop);
        serial.setFlowControl(QSerialPort::NoFlowControl);
        serial.setBaudRate(QSerialPort::Baud9600);
        serial.setDataBits(QSerialPort::Data8);
    
        if(serial.open(QSerialPort::ReadWrite)) {
            qDebug() << "Connected to send!";
            sender();
        } else {
            qDebug() << "Error: Not connected to send!";
        }
    
        return a.exec();
    }
    

    SerialportRecieve

    #include "mainwindow.h"
    #include <QApplication>
    #include <QtSerialPort/QSerialPort>
    #include <QDebug>
    #include <QByteArray>
    #include <QDataStream>
    #include <QLabel>
    #include <QPixmap>
    
    QSerialPort serial;
    QByteArray imgBytes;
    QImage img;
    int i = 0;
    
    void imgBuilder(QByteArray imgBytes) {
        qDebug() << imgBytes;
        qDebug() << "STARTING ARRAYBUILD";
        QDataStream stream(imgBytes);
        stream >> img;
        qDebug() << "ARRAY BUILT!";
    
    }
    
    void reciever () {
        qDebug() << "I read data";
        serial.waitForBytesWritten(1000);
        QObject::connect(&serial ,&QSerialPort::readyRead, [&] {
            qDebug() << "New data Available: ";
            QByteArray datas;
            datas = serial.readAll();
            imgBytes.append(datas);
            if (!serial.bytesAvailable()) {
                i++;
                qDebug() << i;
            }
            if (i == 16) {
                qDebug() << "Closing port...";
                serial.close();
                imgBuilder(imgBytes);
            }
        });
    }
    
    int main(int argc, char *argv[])
    {
        QApplication a(argc, argv);
        MainWindow w;
        w.show();
    
        serial.open(QSerialPort::ReadOnly);
        serial.setPortName("ttyUSB1");
        serial.setParity(QSerialPort::NoParity);
        serial.setStopBits(QSerialPort::OneStop);
        serial.setFlowControl(QSerialPort::NoFlowControl);
        serial.setBaudRate(QSerialPort::Baud9600);
        serial.setDataBits(QSerialPort::Data8);
    
        if(serial.open(QSerialPort::ReadOnly)) {
            qDebug() << "Connected to recieve!";
            reciever();
        } else {
            qDebug() << "Error: Not connected to recieve!";
        }
    
        QLabel label;
        label.setPixmap( QPixmap::fromImage(img));
        label.show();
    
        QObject::connect(&serial, static_cast<void(QSerialPort::*)(QSerialPort::SerialPortError)>(&QSerialPort::error), [&](QSerialPort::SerialPortError error) {
               qDebug() << "An error Occured: " << error;
               a.quit();
           });
    
        return a.exec();
    }
    

    So from this i've compared the arrays before and after and they are identical. My program does show a label but it is empty..


  • Moderators

    @ivar said in Sending files over RS-485 using QtSerialPort/QSerial:

    So from this i've compared the arrays before and after and they are identical. My program does show a label but it is empty..

    This is related to what I said earlier about asynchronous programming.

    When you run your receiver code, this is the sequence of things that happen (Starting from main()):

    1. Create a QApplication
    2. Create and show a MainWindow
    3. Open and configure serial port
    4. Open serial port again
    5. Print debug message: "Connected to recieve!"
    6. Call the receiver() function:
      a. Print debug message: "I read data"
      b. Wait for bytes to be written
      c. Connect a lambda function to QSerialPort::readyRead()
      d. Return
    7. Create a QLabel
    8. Convert the QImage to QPixmap, and apply the pixmap to the QLabel
    9. Show the QLabel
    10. Connect a lambda function to QSerialPort::error()
    11. Start running the application's event loop (by calling QApplication::exec())
    12. (Start waiting for bytes to arrive on the serial port)
    13. (When bytes arrive) Emit the QSerialPort::readyRead() signal
    14. (When the signal is emitted) Call the lambda function that was connected in Step #6c:
      a. Print debug message: "New data Available: "
      b. Read all available data from serial port
      c. Check bytes and increment counter, i
      d. (When i == 16) Close port and deserialize bytes

    Read through your code again, and follow the list above. Make sure you understand and agree with this sequence. If something is not clear, ask for clarification.

    The most important part is this: You converted the QImage to QPixmap at Step #8, but the QImage isn't complete until Step #14d!

    You must understand: Step #6c does not run the lambda function to process the byte array. Step #6c only registers the lambda function, and then your code continues to the next line. The lambda function is only run when the signal QSerialPort::readyRead() is emitted.

    Your task now is to figure out how you should change the code so that it waits for all the bytes to be received before it creates the QPixmap. Do this first, then we'll discuss your other questions.



  • @JKSH Right. I did what you said and followed the code throughout and I understand what you mean. So I figured I was hindering myself by running everything from the main function and re-wrote my reciever program in the mainwindow.cpp instead of the main.cpp. I discarded the counter and implemented a command function instead.
    Instead of creating a label when I construct my QPixmap I tried out creating my mainwindow and a label that I can update when needed. I tried using signals and slots to make this work and I think I got it right -
    I included this (below) into my header file and can define and use the function in my mainwindow.cpp file.

    private slots:
          void serialBuilder();
    

    mainwindow.cpp

    #include "mainwindow.h"
    #include "ui_mainwindow.h"
    #include "mainwindow.h"
    #include <QApplication>
    #include <QtSerialPort/QSerialPort>
    #include <QDebug>
    #include <QByteArray>
    #include <QDataStream>
    #include <QLabel>
    #include <QPixmap>
    #include <QBuffer>
    
    QSerialPort *serial;
    QByteArray imgBytes;
    QImage img;
    int i = 0;
    
    MainWindow::MainWindow(QWidget *parent) :
        QMainWindow(parent),
        ui(new Ui::MainWindow)
    {
        ui->setupUi(this);
        serial = new QSerialPort(this);
        serial->open(QSerialPort::ReadOnly);
        serial->setPortName("/dev/ttymxc2");
        serial->setParity(QSerialPort::NoParity);
        serial->setStopBits(QSerialPort::OneStop);
        serial->setFlowControl(QSerialPort::NoFlowControl);
        serial->setBaudRate(QSerialPort::Baud9600);
        serial->setDataBits(QSerialPort::Data8);
        connect(serial,SIGNAL(readyRead()),this,SLOT(serialBuilder()));
        if(serial->open(QSerialPort::ReadOnly)) {
            qDebug() << "Connected to recieve!";
        } else {
            qDebug() << "Error: Not connected to recieve!";
        }
    
    }
    
    void MainWindow::serialBuilder(){
        serial->waitForBytesWritten(1000);
        qDebug()<< "New data available!";
        QByteArray datas;
        datas = serial->readAll();
        if (datas == "Build") {
            qDebug()<<imgBytes;
            QDataStream stream(imgBytes);
            stream >> img;
            qDebug()<< "Array built, constructing image...";
            ui->label->setContentsMargins(0,0,0,0);
            ui->label->setScaledContents(true);
            ui->label->setPixmap(QPixmap::fromImage(img));
        } else {
            imgBytes.append(datas);
        }
    }
    
    MainWindow::~MainWindow()
    {
        delete ui;
    }
    

    And success! After I had tested it out, as you suggested, with a small 2x2 pixel image and got it to work I did the same thing with a large HD picture. I got the image to be constructed and display at my other device scaled down to about 1/4th of the original size.

    However I still have some things that are unclear to me and I would like to fix.

    1. I do not fully understand the difference of connect(serial,SIGNAL(readyRead()),this,SLOT(serialBuilder())); and my earlier expression QObject::connect(&serial ,&QSerialPort::readyRead, [&] {...}); maybe this is due to me being a novice on C++...

    2. I would like to have a timer on the connect(serial,SIGNAL(readyRead()),this,SLOT(serialBuilder())); instead of it waiting for a command. Say for instance after 5 seconds, if there is no signal emitted to the port then it automatically proceeds into the construction of the array.
      This way I could maybe (?) send one image - wait for it to update it to the device - send a new picture and get it to update my device. (I would of course have to clear my array appending the byteArray intermittently)
      Perhaps I could use something like if (!serial.bytesAvailable) { ... } or ìf (serial.atEnd) { ... } I've tried it out and failed earlier but I'll give it a shot again..

    Thanks again for all your help and support, couldn't have done it without you! :)


  • Lifetime Qt Champion

    Hi,

    1. The second syntax triggers a compile time error and will fail the build.

  • Moderators

    @ivar said in Sending files over RS-485 using QtSerialPort/QSerial:

    And success! After I had tested it out, as you suggested, with a small 2x2 pixel image and got it to work I did the same thing with a large HD picture.

    Congrats! Great work.

    However I still have some things that are unclear to me and I would like to fix.

    1. I do not fully understand the difference of connect(serial,SIGNAL(readyRead()),this,SLOT(serialBuilder())); and my earlier expression QObject::connect(&serial ,&QSerialPort::readyRead, [&] {...}); maybe this is due to me being a novice on C++...

    Read this: https://doc.qt.io/qt-5/signalsandslots-syntaxes.html

    • connect(serial, SIGNAL(readyRead()), this, SLOT(serialBuilder())); is equivalent to
    • connect(serial, &QSerialPort::readyRead, this, &MainWindow::serialBuilder);

    The first version is a string-based connection; the second version is a functor-based connection

    If serialBuilder() is only called from one place, you can write it "inline" as a lambda function instead of creating a separate slot function.

    1. I would like to have a timer on the connect(serial,SIGNAL(readyRead()),this,SLOT(serialBuilder())); instead of it waiting for a command. Say for instance after 5 seconds, if there is no signal emitted to the port then it automatically proceeds into the construction of the array.
    1. Create a QTimer and store it somewhere (the same way you're storing the QSerialPort
    2. Connect the QTimer::timeout() signal to the function that converts the byte array into an image.
    3. Make the timer single-shot.
    4. Every time serialBuilder()) is called, start() the timer.

    This way, the timer starts counting down when the first chunk of data is received. If a new chunk arrives within 5 s, then the timer gets reset and it starts counting from 5 s again. 5 s after the last chunk is received, the timeout() signal gets emitted.

    Thanks again for all your help and support, couldn't have done it without you! :)

    You're most welcome. I hope you're having fun and learning lots. Here are a few more tips:

    • You are trying to open the serial port twice. Don't call open() before you configure the port.
    • Your code only reads data from the serial port -- it does not write data into the serial port. Therefore, it makes no sense to call waitForBytesWritten(): https://doc.qt.io/qt-5/qserialport.html#waitForBytesWritten
    • You have quite a few global variables. Try to avoid these. Convert them into private member variables of your MainWindow instead.
    • The nicer/proper way to include QSerialPort is: Add QT += serialport to your *.pro file, then write #include <QSerialPort> instead of #include <QtSerialPort/QSerialPort>
    • If you plan to scale down the image, then it could make sense to do it before sending it across the serial port: https://doc.qt.io/qt-5/qimage.html#scaled

    Happy coding!



  • @JKSH I'll look into the timer and make sure I understand everything we've done.
    Thanks again and have a great summer!


  • Moderators

    @ivar said in Sending files over RS-485 using QtSerialPort/QSerial:

    @JKSH I'll look into the timer and make sure I understand everything we've done.

    All the best with your project.

    Thanks again and have a great summer!

    You're welcome. Have a great summer!

    (P.S. It's winter where I live ;) )



  • @ivar if your issue is solved, please don't forget to mark your post as such! Thanks


Log in to reply