qtqmlqtserialport

Linking a QML Property to QSerial Output


I'm creating a gauge cluster using the Qt tutorial. I've gone through all those steps and have the visual side complete, so now I'm on the coding side and completely green.

The setup is an Arduino sending data to a Raspberry Pi. I'm trying to take that data and send it to my QML to update the 'rpmFrame' in the QML. As an experiment, I have the Arduino just sending '800' and I can't get the gauge to show it in any capacity (the data comes in perfect no problem and I have assigned it to the double 'rpmDouble'.) I have with several attempts gotten incoming:: valueToQML to show 800 in the debug, but it never translates to the QML. I think my I just have a fundamental poor understanding of how all the variables work across the header etc.

main.qml

import QtQuick 2.12
import QtQuick.Window 2.12
import QtQuick.Timeline 1.0
import incoming 1.0

Window {
    width: 1280
    height: 480
    visible: true
    color: "#FFFFFF"

SerialIncoming{
        id:incoming
}
    Rectangle {
        id: rectangle
        x: 0
        y: -7
        width: 1280
        height: 487
        color: "#ffffff"
    }

        Rectangle {
            id: oil
            x: 331
            y: 52
            width: 69
            height: 47
            color: "#ff0000"
        }

        Rectangle {
            id: battery
            x: 405
            y: 52
            width: 74
            height: 47
            color: "#ff0000"
        }

        Rectangle {
            id: leftturn
            x: 360
            y: 105
            width: 69
            height: 47
            color: "#15ff0d"
        }

        Rectangle {
            id: hibeam
            x: 807
            y: 65
            width: 69
            height: 47
            color: "#00caff"
        }

        Rectangle {
            id: brake
            x: 881
            y: 64
            width: 74
            height: 47
            color: "#ff0000"
        }

        Rectangle {
            id: rightturn
            x: 852
            y: 117
            width: 69
            height: 47
            color: "#15ff0d"
        }

        Rectangle {
            id: oil1
            x: 369
            y: 386
            width: 69
            height: 47
            color: "#ff0000"
        }

    Tachometer {
        id: tachometer
        x: 423
        y: 27
        rpmFrame: {incoming.valueToQML} // <-- this is where serial data goes
        displaySpeed: "500"
        scale: 0.9

    }




}

incoming.cpp

incoming::incoming(QObject *parent) : QObject(parent) {

    arduino = new QSerialPort(this);
    serialBuffer="";

    arduino->setPortName("ttyACM0");
    arduino->setBaudRate (QSerialPort::Baud9600);
    arduino->setDataBits (QSerialPort::Data8);
    arduino->setParity(QSerialPort::NoParity);
    arduino->setStopBits(QSerialPort::OneStop);
    arduino->setFlowControl (QSerialPort::NoFlowControl);
    arduino->open(QSerialPort::ReadOnly);
    QObject::connect(arduino, SIGNAL(readyRead()), this, SLOT(readSerial()));
    qDebug() << "KenDash v0.0";


}

void incoming::readSerial()
{
    //Buffer to Filter Data
    if(arduino->bytesAvailable()>0||arduino->waitForReadyRead(10))
    {
    QStringList bufferSplit = serialBuffer.split(",");

    if(bufferSplit.length() < 5)
        {
    QByteArray serialData = arduino->readAll();
    serialBuffer += QString::fromStdString(serialData.toStdString());
    serialData.clear();
        }else{
    //Clean Data Output
    serialBuffer="";
    QString serialOutput = bufferSplit[1];

    //Split the Clean Data To Sections
    QStringList dataSplit = bufferSplit[1].split("/");
    QString rpmOutput = dataSplit[0];
    QString speedOutput = dataSplit[1];

    //qDebug() << "RPM:" << rpmOutput << "Speed:" << speedOutput;

    rpmDouble = rpmOutput.toDouble();


    incoming *myinstance = new incoming;
    QObject *object = myinstance;

   object->setProperty("valueToQML", rpmDouble);
   //Read Data in Debug Panel
   qDebug() << "RPM(onheader2):" << incoming::valueToQML();
        }
    }



}

main.cpp

        #include "incoming.h"
    #include <QGuiApplication>
    #include <QQmlApplicationEngine>
    #include <QDebug>
    
    
    int main(int argc, char *argv[])
    {
        QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
        QGuiApplication app(argc, argv);
        qmlRegisterType<incoming>("incoming", 1, 0, "SerialIncoming");
        QQmlApplicationEngine engine;
    
        const QUrl url(QStringLiteral("qrc:/main.qml"));
        QObject::connect(&engine, &QQmlApplicationEngine::objectCreated,
                         &app, [url](QObject *obj, const QUrl &objUrl) {
            if (!obj && url == objUrl)
                QCoreApplication::exit(-1);
        }, Qt::QueuedConnection);
        engine.load(url);
        void incomingserial();
        return app.exec();
    
    }

incoming.h

  #ifndef INCOMING_H
#define INCOMING_H

#pragma once
#include <QString>
#include <QSerialPort>
#include <QDebug>
#include <QObject>
#include <iostream>


void incomingserial();

class incoming : public QObject
{
    Q_OBJECT
    Q_PROPERTY(double valueToQML READ valueToQML WRITE setValuetoQML NOTIFY valueToQMLChanged)

public:

    explicit incoming(QObject *parent = 0);
    //~incoming();
    double valueToQML() const
    { return rpmDouble;}
    void setValuetoQML(double valueToQML)
    {
        _valueString = valueToQML;
        emit valueToQMLChanged(valueToQML);
    }


signals:
    void valueToQMLChanged(double);

private slots:
        void readSerial();

private:
    double _valueString;
    QSerialPort *arduino;
    static const quint16 arduino_uno_vendor_id = 9025;
    static const quint16 arduino_uno_product_id = 67;
    QByteArray serialData;
    QString serialBuffer;
    QString parsed_data;
    double rpmTachOutput;
    double rpmDouble;
    QString rpmOutput;
    double rpmToDisplay();

};




#endif // INCOMING_H

Solution

  • I can't understand why you set your new incoming value to _valueString but you read the value from rpmDouble. Your QProperty read and write function should refer to the same variable so when something come from serial you should call:

    this->setValuetoQML(rpmOutput.toDouble());
    

    And inside setValuetoQML function assign new value like this:

    rpmDouble = valueToQML;
    

    Because you're returning rpmDouble when valueToQML() is called.