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 !
-
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.
-
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 ... -
@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
-
Mix both techniques: an ID to know what kind of data you have and the "special" char to know where to split.
-
-
You can use a while loop and take the first element at each iteration so no need for a particular check.
-
@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()" ?