Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

Unable to send and receive images between 2 Raspberry connected to Zigbee via UART.



  • I have 2 Raspberry Pi4 connected to Zigbee via UART, I wrote the program to receive and send between the two devices. My program can send and receive character data very accurately, but when I send data from a photo, the program never receives enough data. I tried a PC connected to Zigbee and sent pictures to Pi via RealTerm, on Pi I received photos. What is the problem here? Or does anyone have another way to send photos between 2 Raspberry connected to Zigbee via UART? Thanks very much.
    Program send data:

    #include "ui_serial.h"
    #include <QDebug>
    #include <QBuffer>
    #include <QPixmap>
    #include <QFile>
    
    
    serial::serial(QWidget *parent) :
        QMainWindow(parent),
        ui(new Ui::serial)
    {
        ui->setupUi(this);
    
        serialPort = new QSerialPort(this);
        serialPort->setPortName("ttyAMA0");
        serialPort->setBaudRate(QSerialPort::Baud115200);
        serialPort->setDataBits(QSerialPort::Data8);
        serialPort->setStopBits(QSerialPort::OneStop);
        serialPort->setFlowControl(QSerialPort::NoFlowControl);
        serialPort->open(QIODevice::ReadWrite);
    
        if (serialPort->isOpen() == true){
            qDebug() <<"Port Opened....";
            connect(serialPort, SIGNAL(readyRead()), this, SLOT(on_readdata()));
        }
    }
    void serial::on_pushButton_2_clicked()
    {
        QFile* imageFile = new QFile("/home/pi/Desktop/image.jpg");
            imageFile->open(QIODevice::ReadOnly);
            QByteArray ba = imageFile->readAll();
            imageFile->close();
            delete imageFile;
            if(serialPort->isOpen()==true){
                serialPort->write(ba);
                qDebug()<<ba.size()<<"size_send:";
            }
    }
    

    Data receiving program:

    #include "ui_serial.h"
    #include <QDebug>
    #include <QBuffer>
    #include <QPixmap>
    #include <QFile>
    #include <QMessageBox>
    
    serial::serial(QWidget *parent) :
        QMainWindow(parent),
        ui(new Ui::serial)
    {
        ui->setupUi(this);
    
        serialPort = new QSerialPort(this);
        serialPort->setPortName("ttyAMA0");
        serialPort->setBaudRate(QSerialPort::Baud115200);
        serialPort->setDataBits(QSerialPort::Data8);
        serialPort->setStopBits(QSerialPort::OneStop);
        serialPort->setFlowControl(QSerialPort::NoFlowControl);
        serialPort->open(QIODevice::ReadWrite);
    
        if (serialPort->isOpen() == true){
            qDebug() <<"Port Opened....";
            connect(serialPort, SIGNAL(readyRead()), this, SLOT(on_readdata()));
        }
    }
    
    void serial::on_readdata()
    {
        QByteArray ba;
        while (serialPort->waitForReadyRead(1000)){
            ba.append(serialPort->readAll());
        }
        qDebug()<<ba.size()<<"sizeeeee:";
        QFile newDoc("/home/pi/Desktop/imagexx.jpg");
                if(newDoc.open(QIODevice::WriteOnly)){
                    newDoc.write(ba);
                }
                newDoc.close();
    }
    

  • Qt Champions 2019

    @Rika said in Unable to send and receive images between 2 Raspberry connected to Zigbee via UART.:

    while (serialPort->waitForReadyRead(1000)){
    ba.append(serialPort->readAll());
    }

    How do you actually know when the whole picture was received?
    You need a protocol. For example you could first send an int containing the image size and then send the actual image. This way the receiver would know how many bytes to receive.



  • @jsulm Thank you for replying. I tried sending images from a PC (using Realterm to send pictures), on my Pi 4, I ran the receiving program and got the images. Could the error be in the sending program?


  • Lifetime Qt Champion

    @Rika
    Hi
    There is no real error as such. it's just that data will come as multiple read and
    the current code will then save only the last seen data piece as imagexx.jpg
    and the image will always appear broken.

    Overlooked waitForReadyRead in slot

    That is why @jsulm want you to include the size of the image so we can know we got all data.


  • Qt Champions 2019

    @mrjj said in Unable to send and receive images between 2 Raspberry connected to Zigbee via UART.:

    There is no real error as such. it's just that data will come as multiple read and
    the current code will then save only the last seen data piece as imagexx.jpg

    Are you sure?

    QByteArray ba;
    while (serialPort->waitForReadyRead(1000)){
        ba.append(serialPort->readAll());
    }
    

  • Lifetime Qt Champion

    @jsulm
    Hi
    Àhh on first ready signal, it will call the slot and the
    waitForReadyRead + loop will then read all remaining data.
    Ok that should actually do it.
    ( if really never breaks the while loop)


  • Qt Champions 2019

    @mrjj Yes, possible that the timeout kicks in and terminates the loop before everything was received.


  • Lifetime Qt Champion

    @jsulm
    Hi
    I also wonder if that would happen if image was say 1 MB.

    But it should be clear to poster if its called more than once with the
    qDebug()<<ba.size()<<"sizeeeee:";


  • Qt Champions 2019

    @Rika I suggest you implement the receiving part in a proper way: without mixing asynchronous and synchronous ways to read data. Remove the loop from serial::on_readdata(). Put QByteArray ba as member variable in the class. Accumulate data in ba untill you got all data.



  • @jsulm @mrjj I used qDebug to find out how much data was sent and received. I sent a 30kB image, the data I got from "qDebug()<<ba.size()<<"sizeeeee:";" was 132, I tried many times and all received 132. I used different photos, they gave different results but always the same.


  • Qt Champions 2019

    @Rika Please read https://doc.qt.io/qt-5/qserialport.html#waitForReadyRead "This function blocks until new data is available for reading and the readyRead() signal has been emitted" and my previous post (no need for waitForReadyRead and the loop).



  • @jsulm You mean this?

    void serial::on_readdata()
    {
        QByteArray ba(serialPort->readAll());
        qDebug()<<ba.size()<<"sizeeeee:";
        QFile newDoc("/home/pi/Desktop/imagexx.jpg");
                if(newDoc.open(QIODevice::WriteOnly)){
                    newDoc.write(ba);
                }
                newDoc.close();
    }
    

  • Qt Champions 2019

    @Rika No, not like this. Please read my post above "Put QByteArray ba as member variable in the class. Accumulate data in ba untill you got all data."



  • @jsulm Sorry, I don't really understand what you mean. Can you give an example with code?


  • Qt Champions 2019

    @Rika

    void serial::on_readdata()
    {
        ba.apend(serialPort->readAll());
        qDebug()<<ba.size()<<"sizeeeee:";
        if (ba.size() == imageSize) {
            QFile newDoc("/home/pi/Desktop/imagexx.jpg");
            if(newDoc.open(QIODevice::WriteOnly)){
                newDoc.write(ba);
            }
            newDoc.close();
        }
    }
    


  • @jsulm I tried it and it failed, I sent 31021 bytes and always received 241 bytes.


  • Lifetime Qt Champion

    @Rika
    So it only shows
    qDebug()<<ba.size()<<"sizeeeee:";
    1 time with size 241 ?



  • @mrjj No, the last time was 241. My old way it also received only 241 bytes, so I was thinking of the possibility of an error sent by the program.


  • Lifetime Qt Champion

    @Rika said in Unable to send and receive images between 2 Raspberry connected to Zigbee via UART.:

    No, the last time was 241.

    So you do get mutiple
    qDebug()<<ba.size()<<"sizeeeee:";
    messages ?



  • @mrjj
    144 sizeeeee:
    160 sizeeeee:
    176 sizeeeee:
    192 sizeeeee:
    208 sizeeeee:
    224 sizeeeee:
    240 sizeeeee:
    241 sizeeeee:


  • Qt Champions 2019

    @Rika As I already said: you have to accumulate all these data in ba and when you got everything then you store it in the file.
    Again the code:

    void serial::on_readdata()
    {
        ba.apend(serialPort->readAll());
        qDebug()<<ba.size()<<"sizeeeee:";
        if (ba.size() == imageSize) {
            QFile newDoc("/home/pi/Desktop/imagexx.jpg");
            if(newDoc.open(QIODevice::WriteOnly)){
                newDoc.write(ba);
            }
            newDoc.close();
        }
    }
    

  • Lifetime Qt Champion

    @Rika
    But it stops at 241 every time?

    Maybe its due to data.
    Could you try in your sent function

    void serial::on_pushButton_2_clicked()
    {
    
    
            QByteArray ba;
            ba.fill('A', 1000);
            if(serialPort->isOpen()==true){
                serialPort->write(ba);
                qDebug()<<ba.size()<<"size_send:";
            }
    }
    

    and see if that changes how you the reading goes.
    This just sends 1000 A.

    Also i wonder if write will copy the data and then send / if write sent it all there as else we have the issue of the sent buffer running out of scope.



  • @jsulm I have made your way, the above is the result from qDebug (). It only received 241 bytes so file imagexxx.jpg was not created. (my imageSize= 31021).


  • Moderators

    @Rika said in Unable to send and receive images between 2 Raspberry connected to Zigbee via UART.:

    @jsulm I have made your way, the above is the result from qDebug (). It only received 241 bytes so file imagexxx.jpg was not created. (my imageSize= 31021).

    at this point, you're not getting away with a simple I've tried that, it does not work.

    @jsulm is absolutely correct. Show us your actual code



  • @mrjj I tried with 1000 A, received only 190


  • Lifetime Qt Champion

    @J-Hilk
    Do you know if write blocks ?
    QByteArray ba; // local
    ba.fill('A', 1000);
    if(serialPort->isOpen()==true){
    serialPort->write(ba); // blocks here ? as ba is by reference



  • @J-Hilk

    Send:

    #include "ui_serial.h"
    #include <QDebug>
    #include <QBuffer>
    #include <QPixmap>
    #include <QFile>
    
    
    serial::serial(QWidget *parent) :
        QMainWindow(parent),
        ui(new Ui::serial)
    {
        ui->setupUi(this);
    
        serialPort = new QSerialPort(this);
        serialPort->setPortName("ttyAMA0");
        serialPort->setBaudRate(QSerialPort::Baud115200);
        serialPort->setDataBits(QSerialPort::Data8);
        serialPort->setStopBits(QSerialPort::OneStop);
        serialPort->setFlowControl(QSerialPort::NoFlowControl);
        serialPort->open(QIODevice::ReadWrite);
    
        if (serialPort->isOpen() == true){
            qDebug() <<"Port Opened....";
            connect(serialPort, SIGNAL(readyRead()), this, SLOT(on_readdata()));
        }
    }
    void serial::on_pushButton_2_clicked()
    {
        QFile* imageFile = new QFile("/home/pi/Desktop/image.jpg");
            imageFile->open(QIODevice::ReadOnly);
            QByteArray ba = imageFile->readAll();
            imageFile->close();
            delete imageFile;
            if(serialPort->isOpen()==true){
                serialPort->write(ba);
                qDebug()<<ba.size()<<"size_send:";
            }
    }
    

    Rec:

    #include "serial.h"
    #include "ui_serial.h"
    #include <QtSerialPort/QSerialPort>
    #include <QDebug>
    #include <QBuffer>
    #include <QPixmap>
    #include <QFile>
    #include <QMessageBox>
    
    serial::serial(QWidget *parent) :
       QMainWindow(parent),
       ui(new Ui::serial)
    {
       ui->setupUi(this);
    
       serialPort = new QSerialPort(this);
       serialPort->setPortName("ttyAMA0");
       serialPort->setBaudRate(QSerialPort::Baud115200);
       serialPort->setDataBits(QSerialPort::Data8);
       serialPort->setStopBits(QSerialPort::OneStop);
       serialPort->setFlowControl(QSerialPort::NoFlowControl);
       serialPort->open(QIODevice::ReadWrite);
    
       if (serialPort->isOpen() == true){
           qDebug() <<"Port Opened....";
           connect(serialPort, SIGNAL(readyRead()), this, SLOT(on_readdata()));
       }
    
    }
    
    serial::~serial()
    {
       delete ui;
       serialPort->close();
    }
    
    
    void serial::on_readdata()
    {
       ba.append( serialPort->readAll());
       qDebug()<<ba.size()<<"sizeeeee:";
       if (ba.size() == 31021) {
           QFile newDoc("/home/pi/Desktop/imagexx.jpg");
               if(newDoc.open(QIODevice::WriteOnly)){
                   newDoc.write(ba);
               }
               newDoc.close();
       }
    //    ui->label->setText(ba);
    
    //      QPixmap b;
    //      if(b.loadFromData(ba,"JPG")){
    //          ui->label->setPixmap(b);
    //      }
    
    }
    
    

  • Moderators

    @mrjj IIRC, it's passed on to the OS during the write call and that copies the data. But I'm not entirely sure 😬


  • Lifetime Qt Champion

    @J-Hilk
    Yeah i was wondering since its a board if that still happens as it would
    make sense we get cut if not.

    @Rika
    Can you try this

    void serial::on_pushButton_2_clicked()
    {
            static QByteArray ba;
            ba.fill('A', 1000);
            if(serialPort->isOpen()==true){
                serialPort->write(ba);
                qDebug()<<ba.size()<<"size_send:";
            }
    }
    

    and tell me if we still only get up to 190 bytes with the sizeeeee message.



  • @mrjj I tried, still only get 190.
    16 sizeeeee:
    32 sizeeeee:
    64 sizeeeee:
    64 sizeeeee:
    14 sizeeeee:


  • Lifetime Qt Champion

    @Rika
    Good testing.
    So even it says
    qDebug()<<ba.size()<<"size_send:";
    1000 size_send
    you only get
    5 lines of
    16 sizeeeee:
    32 sizeeeee:
    64 sizeeeee:
    64 sizeeeee:
    14 sizeeeee:
    ?



  • @mrjj Sometimes 4 lines, sometimes 7 lines, but the total is 190 bytes. With 500-A, received only 230


  • Lifetime Qt Champion

    @Rika
    Ok
    if we do
    ba.fill('A', 10);
    do you then get all ?



  • @mrjj yes.


  • Lifetime Qt Champion

    @Rika
    So it seems data get cut over some size.

    What Os is running on the boards ?

    Also maybe Zigbee has some sort of max transfer size ?



  • @mrjj I use raspbian. I tried using a PC connected to zigbee and sent photos to my Pi4 + Zigbee with Realterm, my Pi4 received the photos. I think the error is in the program sends the data.


  • Moderators

    well, lets narrow it down,
    write returns a quint64 with the actual number of bytes written to the serialport, what does that return ?

    void serial::on_pushButton_2_clicked()
    {
            static QByteArray ba;
            ba.fill('A', 1000);
            if(serialPort->isOpen()==true){
                quint64 send = serialPort->write(ba);
                qDebug()<<send << " of" << ba.size()<<"size_send:";
            }
    }
    


  • @J-Hilk 1000 of 1000 size.


  • Moderators

    @Rika well,
    to make sure your 2nd application is not simply very late in its creation/startup process, try clicking the button a 2nd time, see if something changes :D

    After that, time for a serial port listing device, to check what is actually transferred


  • Lifetime Qt Champion

    @J-Hilk
    When i goggle Zigbee , i do see max payload mentioned.
    Do you think that could be the cause here ?
    I never used Zigbee so not sure if its even an issue.


Log in to reply