Serial Data "reading" disorder



  • Hi everyone !

    It's my first program on Qt, so please be understanding ... (for my english too)
    

    It have an arduino uno card, and some potentiometers on it. I made a small Dialog window just to see if I can receive everything by serial buffer. I managed to receive and see all the informations (basicaly 6 numbers with 1 or 4 digits each).
    In order to separate them (they arrived like "12359542288752145"), I put a letter betwen each value with arduino, so datas arrive like "A1235AB954BC2288CD75DE2145E".
    Then i make some sections with the right letter and got the separate datas like i need.

    But the problem is I never receive data the same way, it could be either:
    "A1235AB954BC2288CD75DE2145E"
    or
    "A12"
    or even
    ""

    Do you know how to fiw that ? Here is a part of my (poor) code:

    #include "dialog.h"
    #include "ui_dialog.h"
    #include <QSerialPort>
    #include <QSerialPortInfo>
    #include <string>
    #include <QDebug>
    #include <QMessageBox>
    #include <QTime>

    Dialog::Dialog(QWidget *parent) :
    QDialog(parent),
    ui(new Ui::Dialog)
    {
    ui->setupUi(this);
    ui->InclinoD_lcdNumber->display("----");
    ui->InclinoG_lcdNumber->display("----");
    ui->Godet_lcdNumber->display("----");
    ui->Balancier_lcdNumber->display("----");
    ui->Fleche_lcdNumber->display("----");
    ui->Tourelle_lcdNumber->display("----");

    arduino = new QSerialPort(this);
    serialBuffer = "";
    
    bool arduino_is_available = false;
    QString arduino_uno_port_name;
    
    foreach(const QSerialPortInfo &serialPortInfo, QSerialPortInfo::availablePorts()){
        if(serialPortInfo.hasProductIdentifier() && serialPortInfo.hasVendorIdentifier()){
            if((serialPortInfo.productIdentifier() == arduino_uno_product_id)
                    && (serialPortInfo.vendorIdentifier() == arduino_uno_vendor_id)){
                arduino_is_available = true; 
                arduino_uno_port_name = serialPortInfo.portName();
            }
        }
    }
    
    if(arduino_is_available){
        qDebug() << "Found the arduino port...\n";
        arduino->setPortName(arduino_uno_port_name);
        arduino->open(QSerialPort::ReadOnly);
        arduino->setBaudRate(QSerialPort::Baud9600);
        arduino->setDataBits(QSerialPort::Data8);
        arduino->setFlowControl(QSerialPort::NoFlowControl);
        arduino->setParity(QSerialPort::NoParity);
        arduino->setStopBits(QSerialPort::OneStop);
        QObject::connect(arduino, SIGNAL(readyRead()), this, SLOT(readSerial()));
    }else{
        qDebug() << "Couldn't find the correct port for the arduino.\n";
        QMessageBox::information(this, "Serial Port Error", "Couldn't open serial port to arduino.");
    }
    

    }

    Dialog::~Dialog()
    {
    if(arduino->isOpen()){
    arduino->close(); // Close the serial port if it's open.
    }
    delete ui;
    }

    void Dialog::readSerial()
    {

        QStringList buffer_split;
    
        serialData = arduino->readAll();
        serialBuffer = QString::fromStdString(serialData.toStdString());
    
        parsed_data = serialBuffer.section("D", 1,1); 
        buffer_split.insert(0,parsed_data);
        parsed_data = serialBuffer.section("G", 1,1); 
        buffer_split.insert(1,parsed_data);
        parsed_data = serialBuffer.section("o", 1,1); 
        buffer_split.insert(2,parsed_data);
        parsed_data = serialBuffer.section("B", 1,1); 
        buffer_split.insert(3,parsed_data);
        parsed_data = serialBuffer.section("F", 1,1); 
        buffer_split.insert(4,parsed_data);
        parsed_data = serialBuffer.section("T", 1,1); 
        buffer_split.insert(5,parsed_data);
    
        qDebug() << buffer_split << "\n";
    
        serialData.clear();
        serialBuffer = "";
    
    
        Dialog::updateInclinoD(buffer_split[0]);
        Dialog::updateInclinoG(buffer_split[1]);
        Dialog::updateGodet(buffer_split[2]);
        Dialog::updateBalancier(buffer_split[3]);
        Dialog::updateFleche(buffer_split[4]);
        Dialog::updateTourelle(buffer_split[5]);
    

    // And after come my functions ...

    Thank you all !


  • Lifetime Qt Champion

    Hi and welcome to devnet,

    The usual way to handle incoming data is to store them in a buffer until there's enough of them to form a complete package and only then parse the packet.


  • Qt Champions 2016

    Hi
    Data most often comes in pieces so as @SGaist says, you must keep reading
    like
    m_readData.append( m_serialPort->readAll());
    until you got whole "line" of data
    you can check
    if (m_readData.size() >= EXPECTED_BYTES)
    Parse()
    or have kind of stop marker in the data.

    Other note. you could maybe use same separator between numbers, like | and then
    just say
    serialBuffer = QString::fromStdString(serialData.toStdString());
    QStringList list = serialBuffer .split ( "|" );
    then you have list of each number.
    list[0] being the first.

    Just a though. might not suit your needs.



  • @SGaist Thank you or your answer. Yes i suppose that's what I have to do, but I don't really know how. I tried with "waitForReadyRead()" but he doesn't work, my code just stop and crash on it, despite what I read I don't really know how to use it properly.



  • @mrjj Thank you.
    I used differents letters as separator because i wanted to reconize each data. Indeed I can just use one separator but it means that I have to gather all the data in the good order.
    ".append" seams like a good way but my problem is that I can't know the size of my expected bytes. Each potentiometer can send 1 to 4 digits. I assume there are already solutions for that, but I don't know what ...


  • Qt Champions 2016

    @ftsm
    Ah ok, yes if they can come out of order then same separator is not a option.

    -Each potentiometer can send 1 to 4 digits
    so maybe there comes 1 byte or maybe 4 ?



  • @mrjj Indeed. And so if I try ".append" I will have a huge disorder in datas ...
    I'm still trying to figure out a way to get everything in order but nothing work fine yet


  • Qt Champions 2016

    @ftsm
    but how does the potentiometer send its data ?
    you have no control over the format?



  • @mrjj The potentiometer send its data via Arduino. I can write how I want to send it. First I tried with "," to separate, but I could'nt reconize wich data was what. So I tried with a specific letter before and after each potentiometer value. In this case it is really hard for me to extract the potentiometer value from the line (from serial) because I only know the "split" technic


  • Lifetime Qt Champion

    Mix both techniques: an ID to know what kind of data you have and the "special" char to know where to split.



  • @SGaist Yes I think that is my best move, that's what I'm currently trying to do.
    But I have a last problem: how can I try the existence of a string from QstringList ? For example I need to know if after spliting "buffer_split[1]" exist ?


  • Lifetime Qt Champion

    You can use a while loop and take the first element at each iteration so no need for a particular check.


  • Qt Champions 2016

    @ftsm
    also QstringList has a size() that tells the number of elements. (strings)
    That also gives hints to valid index.



  • @SGaist @mrjj Thank you for that, I managed to split correctly and find the right data.
    But I am still able to do that only on debug mode, when I try to run the program it's like i'm going too fast and my "->ReadAll()" don't gather enought data. (I saw that with some qDebug()).
    So I go back to my first problem, if I use a while loop with "append" I will mix the data.
    Can't I use "waitForReadyRead()" ?



  • OH MY GOD that was the solution since the begining !! It's 1:30am and it's perfectly working !!

    THank you guys I love you so much !!

    YAAaaaaaayyy my first beautiful program on Qt and it rules !! THANK YOU


  • Qt Champions 2016

    @ftsm
    Congratulations with the baby ;)


Log in to reply
 

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