QT -- serial port reads data and displays real-time waveform

Posted by techbinge on Wed, 02 Feb 2022 00:34:44 +0100

1. Read data through serial port

With the lower computer, MCU communication is inseparable from using serial port for communication. Qt also provides the class of serial port communication.

When using, add this sentence import module in pro

QT += serialport

1. The first step to connect serial ports is to obtain the names of all serial ports that can be connected

After obtaining the list of serial port names, we need to select one to be connected (according to our choice)

foreach(const QSerialPortInfo &info, QSerialPortInfo::availablePorts())
    {
        QSerialPort serial;
        serial.setPort(info);
        if (serial.open(QIODevice::ReadWrite))
        {
            portList.push_back(serial.portName());
            serial.close();
        }
    }

2. Open the serial port according to the serial port name

Initialize serial port

void frmserialport::inialSerialPort()         //Initialize serial port (serial port number, baud rate, data bit, stop bit, flow control)
{
    m_flag = 0;
    QList<QString> portList;
    QStringList baudList;
    QStringList parityList;
    QStringList dataBitList;
    QStringList stopBitList;
    QStringList flowList;

    baudList<<"9600"<<"115200"<<"460800";
    dataBitList<<"8";
    parityList<<"nothing";
    stopBitList<<"1";
    flowList<<"nothing";
}
void frmserialport::on_btn_Open_clicked()   //Open serial port
{
    m_pSerialPort = new QSerialPort(this);
    m_pSerialPort->setPortName(ui->cbox_PortName->currentText());           //Serial port name
    m_pSerialPort->setBaudRate(ui->cbox_BaudRate->currentText().toInt());   //Baud rate
    switch (ui->cbox_DataBit->currentIndex()) {
    case 0:
        m_pSerialPort->setDataBits(QSerialPort::Data8);      //The data bits are 8 bits
        break;
    default:
        break;
    }

    switch (ui->cbox_Parity->currentIndex()) {
    case 0:
        m_pSerialPort->setParity(QSerialPort::NoParity);  //No check bit
        break;
    default:
        break;
    }

    switch (ui->cbox_StopBit->currentIndex()) {
    case 0:
        m_pSerialPort->setStopBits(QSerialPort::OneStop);    //One stop bit
        break;
    default:
        break;
    }

    switch (ui->cbox_Flow->currentIndex()) {
    case 0:
        m_pSerialPort->setFlowControl(QSerialPort::NoFlowControl); //No flow control
        break;
    default:
        break;
    }

    if (!m_pSerialPort->open(QIODevice::ReadWrite)){
        QMessageBox::information(this,"Tips","Serial port connection failed");
    }
    else{
        QMessageBox::information(this,"Tips",ui->cbox_PortName->currentText() + tr("Connection successful"));
        ui->btn_Open->setEnabled(false);
        ui->btn_Close->setEnabled(true);
        ui->btn_Send->setEnabled(true);
    }
     connect(m_pSerialPort,&QSerialPort::readyRead,this,&frmserialport::serialReadData); 

3. Send data and clear data

void frmserialport::on_btn_Send_clicked()    //send data
{
    QString strMessage = ui->txt_Send->toPlainText();
    sendCMD(strMessage);
}

void frmserialport::on_btn_Clear_clicked()  //eliminate
{
    if (!ui->txt_Receive->toPlainText().isEmpty()){
        ui->txt_Receive->clear();
        ui->btn_Clear->setEnabled(false);
    }
}

4. Close the serial port

void frmserialport::on_btn_Close_clicked()   //Close the serial port
{
    m_pSerialPort->clear();
    m_pSerialPort->close();
    delete m_pSerialPort;
    m_pSerialPort = nullptr;
    m_flag = 0;

    ui->btn_Open->setEnabled(true);
    ui->btn_Close->setEnabled(false);
    ui->btn_Send->setEnabled(false);
}

2. Display real-time waveform (using QCharts)

1. For the use of QCharts, please refer to Qt development technology: QCharts

Link: Qt development technology: QCharts

2. If you want to draw a graph, you need to define canvas, line and axis. My x-axis uses real-time time, so you need to add an additional timer

    //Drawing variables and coordinates
    QDateTimeAxis *axisX_aX; //x-axis in time
    QDateTimeAxis *axisX_aY;
    QDateTimeAxis *axisX_aZ;
    QValueAxis *axisY_aX;    //aX data, representing the y-axis
    QValueAxis *axisY_aY;    //aY data
    QValueAxis *axisY_aZ;    //aZ data
    QTimer *timer;     //Timer for chart
    QChart *chart;
    QSplineSeries *series_aX; //data point
    QSplineSeries *series_aY;
    QSplineSeries *series_aZ;

3. Set data and define drawing

    axisX_aX->setFormat("hh:mm:ss");
    axisY_aX->setRange(-3,3);
    chart->addSeries(series_aX);
    axisX_aX->setTickCount(10);
    axisY_aX->setTickCount(10);
    axisX_aX->setTitleText("Real time");
    axisY_aX->setTitleText("acceleration A(G):");
    series_aX->setPen(QColor(Qt::red));
    axisY_aX->setLinePen(peny);
    axisX_aX->setLinePen(peny);
    chart->addAxis(axisX_aX , Qt::AlignBottom);
    chart->addAxis(axisY_aX , Qt::AlignLeft);
    series_aX->attachAxis(axisX_aX);
    series_aX->attachAxis(axisY_aX);
    QDateTime currentTime = QDateTime::currentDateTime();           //Real time

    chart->axisX()->setMin(QDateTime::currentDateTime().addSecs(-60*1));
    chart->axisX()->setMax(QDateTime::currentDateTime().addMSecs(0));

    qsrand(QTime(0,0,0).secsTo(QTime::currentTime()));
    series_aX->append(currentTime.toMSecsSinceEpoch() , aX);   //Provide x and y-axis data

 

Finally, it came true!

 

I'm qt Xiaobai. I just started learning qt. If you have any questions, please give me more advice. Thank you for reading. If you think it's good, please give me a praise and collect it!! Finally, list some problems I encountered when writing this project!

 

1. The read serial port data will be segmented

Solution: serial port delay receiving data

Processing idea: create two SLOT functions. When the serial port has a data response, the system will give a readyRead() signal, use the SLOT function to receive a signal and process it. After entering this SLOT function, set a timing. When the timing is finished, there will be a timeout() signal. Use another SLOT function to handle the things after the timing is completed.

Thank you for your ideas.

 //connect(timer,SIGNAL(timeout()),this,SLOT(RealtimeDataSlot()));  Slot function before receiving data without delay
    
connect(timer,SIGNAL(timeout()),this,SLOT(DrawLine()));


//connect(m_pSerialPort,&QSerialPort::readyRead,this,&frmserialport::serialReadData); // Slot function before receiving data without delay

    //Delay receiving data
    connect(m_pSerialPort,SIGNAL(readyRead()),this,SLOT(on_serialReadData()));     //When there is data to display
    connect(&timer1,SIGNAL(timeout()),this,SLOT(serialReadData()));                //Enter when the timing ends

2. Separate serial port data

I use the method of string separation

Because the length of the data read by the serial port after being converted into QString is not certain, the index method is used to solve it.

    QByteArray receiveData;
    receiveData = m_pSerialPort->readAll();
    qDebug()<<"Re:"<<receiveData;

    QString str=receiveData;
    int x1=str.indexOf(":");
    int x=str.indexOf("G");
    int x2=x-x1-1;

 

After successful interception, it will be converted to Double type to provide Y-axis data to the curve.

 

If copyright infringement and other issues, private chat will be deleted immediately.

Topics: Qt