Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. QML and Qt Quick
  4. textfield updates intermittent 'garbage'
Qt 6.11 is out! See what's new in the release blog

textfield updates intermittent 'garbage'

Scheduled Pinned Locked Moved Solved QML and Qt Quick
4 Posts 2 Posters 648 Views 1 Watching
  • Oldest to Newest
  • Newest to Oldest
  • Most Votes
Reply
  • Reply as topic
Log in to reply
This topic has been deleted. Only users with topic management privileges can see it.
  • D Offline
    D Offline
    Dave_022
    wrote on last edited by
    #1

    I have an Arduino connected via serial running the a simple sketch to return dummy data. this returns fine as shown by debug.

    My LCD displays update fine until I use the zero button in TableSaw qml then it intermittently returns garbage output whilst ending up on the correct figure. I have no idea why?

    Also I can't get the display to update again once I push the reset zero button...

    Page2 doesn't have anything on it yet..

    arduino sketch

    #include <Cmd.h>
    float currentDistanceX = 0;
    float currentDistanceY = 0;
    
    void setup() {
      
      Serial.begin(9600);
      cmdInit(&Serial);
      cmdAdd("startX", start_x);
      cmdAdd("startY", start_y);
      cmdAdd("home", homing);
      cmdAdd("jog x", jog_x);
      Serial.println("Enter start and number");
    }
    
    void loop() {
      cmdPoll();
    }
    
    void start_x(int arg_cnt, char **args)
    {
      float distance = (cmdStr2Num(args[1], 10));
      
      if ((distance > 0) && (distance < 1200)) {
      if(distance >= currentDistanceX) {
      for (int i = currentDistanceX; i < (distance+1); i++) {
      Serial.println(i);  
      Serial.flush();
      delay(200);
       }
      }
       else {
        for (int i = currentDistanceX; i > (distance-1); i--) {
      Serial.println(i);  
      Serial.flush();
      delay(200);
       }
       }
      currentDistanceX = distance;
       }
      
      else {
        Serial.println("Out of Range");
      }  
    }
    
    void start_y(int arg_cnt, char **args)
    {
      float distance = (cmdStr2Num(args[1], 10));
      
      if ((distance > 0) && (distance < 1200)) {
      if(distance >= currentDistanceY) {
      for (int i = currentDistanceY; i < (distance+1); i++) {
      Serial.println(i);  
      Serial.flush();
      delay(200);
       }
      }
       else {
        for (int i = currentDistanceY; i > (distance-1); i--) {
      Serial.println(i);  
      Serial.flush();
      delay(200);
       }
       }
      currentDistanceY = distance;
       }
      
      else {
        Serial.println("Out of Range");
      }  
    }
    
    void homing(int arg_cnt, char **args)
    {
      Serial.println("homing x");
      delay (2000);
      currentDistanceX = 0;
      Serial.println("homing y");
      delay (2000);
      currentDistanceY = 0;
      Serial.println("homing complete");
    }
    
    void jog_x (int arg_cnt, char **args)
    {
      Serial.print("Jogging");
      delay (2000);
      Serial.print("Jog Off");
    }
    
    

    arduinoserial.h

    
    #ifndef ARDUINOSERIAL_H
    #define ARDUINOSERIAL_H
    
    #include <QObject>
    #include <QSerialPort>
    
    class ArduinoSerial : public QObject
    {
        Q_OBJECT
        Q_PROPERTY(QString bladeHeightValue READ bladeHeightValue WRITE setBladeHeightValue NOTIFY bladeHeightValueChanged)
        Q_PROPERTY(QString bladeAngleValue READ bladeAngleValue WRITE setBladeAngleValue NOTIFY bladeAngleValueChanged)
    
    public:
        ArduinoSerial();
        QString bladeHeightValue() const;
        QString bladeAngleValue() const;
    
    public slots:    
        void startSerialPort(); // Starts the Open Serial Port Function
        void readSerial();
        void setBladeHeightValue(const QString& value);
        void setBladeAngleValue(const QString& value);
        void closeSerialPort();
        void writeSerial(QString dro, const QByteArray &data);
    
    signals:
        void serialPortOpen(); // Signal for sucessfully opening Serial Port
        void serialPortEror(); // Signal on not finding arduino in openSerialPort
        void bladeHeightValueChanged(); // Signal on data received from arduino
        void bladeAngleValueChanged(); // Signal on data received from arduino
        void homingComplete(); // Signal sent when arduino has finished homing
    
    private:
        QSerialPort *arduino;
        static const quint16 arduino_uno_vendor_id = 9025;
        static const quint16 arduino_uno_product_id = 67;
        QString arduino_port_name;
        bool arduino_is_available;
        QString m_bladeHeightValue;
        QString m_bladeAngleValue;
        QString droToSet;
    
        void openSerialPort();
    };
    
    #endif // ARDUINOSERIAL_H
    

    arduinoserial.cpp

    #include "arduinoserial.h"
    #include <QDebug>
    #include <QSerialPort>
    #include <QSerialPortInfo>
    
    ArduinoSerial::ArduinoSerial()
    {   
        startSerialPort();
    }
    
    QString ArduinoSerial::bladeHeightValue() const
    {
        return m_bladeHeightValue;
    }
    
    QString ArduinoSerial::bladeAngleValue() const
    {
        return m_bladeAngleValue;
    }
    
    void ArduinoSerial::startSerialPort()
    {
        this->openSerialPort();
    }
    
    void ArduinoSerial::readSerial()
    {   
        // Read data
        static QByteArray byteArray;
        byteArray += arduino->readAll();
    
        //we want to read all message not only chunks
        if(!QString(byteArray).contains("\n"))
            return;
    
        //sanitize data
        QString data = QString( byteArray ).remove("\r").remove("\n");
        byteArray.clear();
    
        if(data == "homing complete")
            homingComplete();
    
        // Print data
        qDebug() << "RECV: " << data;
        //remove command prompt from Arduno Cmd and only return Integers to LCD
        if(data.toInt()){
            if(droToSet == "bladeHeight") {
                setBladeHeightValue(data);
                bladeHeightValueChanged();
            }
            if(droToSet == "bladeAngle") {
                setBladeAngleValue(data);
                bladeAngleValueChanged();
            }
    
        } else {
            return;
        }
    }
    
    
    void ArduinoSerial::setBladeHeightValue(const QString &value)
    {
        if (m_bladeHeightValue != value) {
            m_bladeHeightValue = value;
            bladeHeightValueChanged();
        }
    }
    
    void ArduinoSerial::setBladeAngleValue(const QString &value)
    {
        if (m_bladeAngleValue != value) {
            m_bladeAngleValue = value;
            bladeAngleValueChanged();
        }
    }
    
    void ArduinoSerial::closeSerialPort()
    {
        if(arduino->isOpen()){
            arduino->close();
        }
        qDebug() << "Seriol Port is closed";
    }
    
    void ArduinoSerial::writeSerial(QString dro, const QByteArray &data)
    {
        if (dro == "bladeHeight") droToSet = "bladeHeight";
        if (dro == "bladeAngle") droToSet = "bladeAngle";
        if (dro == "fence") droToSet = "fence";
        if (dro == "router") droToSet = "router";
        arduino->write(data);
        qDebug() << (data) + " written to serial";
    }
    
    void ArduinoSerial::openSerialPort()
    {
        /*
         *   Identify the port the arduino uno is on.
         */
        arduino = new QSerialPort;
        arduino_is_available = false;
        arduino_port_name = "";
    
        //
        //  For each available serial port
        foreach(const QSerialPortInfo &serialPortInfo, QSerialPortInfo::availablePorts()){
            //  check if the serialport has both a product identifier and a vendor identifier
            if(serialPortInfo.hasProductIdentifier() && serialPortInfo.hasVendorIdentifier()){
                //  check if the product ID and the vendor ID match those of the arduino uno
                if((serialPortInfo.productIdentifier() == arduino_uno_product_id)
                        && (serialPortInfo.vendorIdentifier() == arduino_uno_vendor_id)){
                    arduino_is_available = true; //    arduino uno is available on this port
                    arduino_port_name = serialPortInfo.portName();
                    qDebug() << QString("Arduino Port Name: %1").arg(arduino_port_name);
                }
            }
        }
        /*
         *  Open and configure the arduino port if available
         */
        if(arduino_is_available){
            qDebug() << "Found the arduino port...\n";
            arduino->setPortName(arduino_port_name);
            arduino->setBaudRate(QSerialPort::Baud9600);
            arduino->setDataBits(QSerialPort::Data8);
            arduino->setFlowControl(QSerialPort::NoFlowControl);
            arduino->setParity(QSerialPort::NoParity);
            arduino->setStopBits(QSerialPort::OneStop);
            arduino->open(QSerialPort::ReadWrite);
            qDebug() << arduino->isOpen();
            QObject::connect(arduino, SIGNAL(readyRead()), this, SLOT(readSerial()));
            serialPortOpen();
        }else{
            serialPortEror();
        }
    
    }
    
    

    main.cpp

    #include <QGuiApplication>
    #include <QQmlApplicationEngine>
    #include <QQmlContext>
    #include "arduinoserial.h"
    
    int main(int argc, char *argv[])
    {
        qputenv("QT_IM_MODULE", QByteArray("qtvirtualkeyboard"));
    
        QCoreApplication::setAttribute(Qt::AA_EnableHighDpiScaling);
    
        QGuiApplication app(argc, argv);
    
        QQmlApplicationEngine engine;
    
        qmlRegisterType<ArduinoSerial>("arduino.serial", 1, 0, "ArduinoSerial");
    
        engine.load(QUrl(QStringLiteral("qrc:/main.qml")));
        if (engine.rootObjects().isEmpty())
            return -1;
    
        return app.exec();
    }
    
    

    main.qml

    import QtQuick 2.11
    import QtQuick.Window 2.11
    import QtQuick.VirtualKeyboard 2.3
    import QtQuick.Controls 2.2
    import arduino.serial 1.0
    import QtQuick.Dialogs 1.2
    import QtGraphicalEffects 1.0
    import QtQuick.Controls.Styles 1.4
    
    ApplicationWindow {
        id: root
        visible: true
        width: 800
        height: 400
        title: qsTr("Stack")
    
        FontLoader {
            id: lcdFont
            source: "lcd.ttf"
        }
        property real bladeHeight: 0
        property real bladeAngle: 0
        property real zeroBladeHeight: 0
        property real zeroBladeAngle: 0
    
        ArduinoSerial {
            id: typeFromArduinoSerial
    
            onSerialPortOpen: console.log("Serial Port Open")
            onSerialPortEror: serialErrorDialog.visible = true
    
            onBladeHeightValueChanged: bladeHeight = (bladeHeightValue/10) - zeroBladeHeight
            onBladeAngleValueChanged: bladeAngle = (bladeAngleValue/10) - zeroBladeAngle
    
    
            onHomingComplete: {
    
            }
    
        }
    
        MessageDialog {
            id: serialErrorDialog
            title: "Serial Port Error"
            icon: "Critical"
            informativeText: "Can't find arduino!"
            standardButtons: StandardButton.Ok
            modality: Qt.ApplicationModal
            onAccepted: Qt.quit();
        }
    
    
        header: ToolBar {
            contentHeight: toolButton.implicitHeight
    
            ToolButton {
                id: toolButton
                text: stackView.depth > 1 ? "\u25C0" : "\u2630"
                font.pixelSize: Qt.application.font.pixelSize * 1.6
                onClicked: {
                    if (stackView.depth > 1) {
                        stackView.pop()
                    } else {
                        drawer.open()
                    }
                }
            }
    
            Label {
                text: stackView.currentItem.title
                anchors.centerIn: parent
            }
        }
    
        Drawer {
            id: drawer
            width: root.width * 0.66
            height: root.height
    
            Column {
                anchors.fill: parent
    
                ItemDelegate {
                    text: qsTr("Table Saw")
                    width: parent.width
                    onClicked: {
                        stackView.push("TableSaw.qml")
                        drawer.close()
                    }
                }
                ItemDelegate {
                    text: qsTr("Page 2")
                    width: parent.width
                    onClicked: {
                        stackView.push("Page2.qml")
                        drawer.close()
                    }
                }
            }
        }
    
        StackView {
            id: stackView
            initialItem: "Home.qml"
            anchors.fill: parent
        }
    
        InputPanel {
            id: inputPanel
            z: 99
            x: 0
            y: root.height
            width: root.width
    
            states: State {
                name: "visible"
                when: inputPanel.active
                PropertyChanges {
                    target: inputPanel
                    y: root.height - inputPanel.height
                }
            }
            transitions: Transition {
                from: ""
                to: "visible"
                reversible: true
                ParallelAnimation {
                    NumberAnimation {
                        properties: "y"
                        duration: 250
                        easing.type: Easing.InOutQuad
                    }
                }
            }
        }
    }
    
    
    

    home.qml

    import QtQuick 2.11
    import QtQuick.Window 2.11
    import QtQuick.VirtualKeyboard 2.3
    import QtQuick.Controls 2.2
    import arduino.serial 1.0
    import QtQuick.Dialogs 1.2
    import QtGraphicalEffects 1.0
    import QtQuick.Controls.Styles 1.4
    
    Page {
        width: 800
        height: 400
    
        title: qsTr("Home")
    
        Image {
            id: woodBackground
            source: "Images/wood_background.jpg"
            width: root.width
            height: root.height
        }
    
        FontLoader {
            id: lcdFont
            source: "lcd.ttf"
        }
    
        Label {
            id: welcomeLabel
            color: "#3115ae"
            text: "Woodworking Tool"
            font.family: "Courier"
    
            font.pixelSize: 60
            font.bold: true
            anchors.horizontalCenter: parent.horizontalCenter
            anchors.verticalCenter: parent.verticalCenter
            anchors.verticalCenterOffset: -120
        }
        RoundButton {
            id: homeButton
            icon.source: "Images/home.png"
            icon.height: 100
            icon.width: 100
            anchors.centerIn: parent
            anchors.verticalCenterOffset: 40
            onClicked: {
                typeFromArduinoSerial.writeSerial("home" + "\r")
            }
        }
    
        }
    
    
    
    

    tablesaw.qml

    import QtQuick 2.11
    import QtQuick.Window 2.11
    import QtQuick.VirtualKeyboard 2.3
    import QtQuick.Controls 2.2
    import arduino.serial 1.0
    import QtQuick.Dialogs 1.2
    import QtGraphicalEffects 1.0
    import QtQuick.Controls.Styles 1.4
    
    Page {
        width: root.width
        height: root.height
    
        title: qsTr("Table Saw")
    
        Binding {
            target: bladeHeightLCD
            property: 'text'
            value: root.bladeHeight
        }
    
        Binding {
            target: bladeAngleLCD
            property: 'text'
            value: root.bladeAngle
        }
    
        Image {
            id: woodBackground
            source: "Images/wood_background.jpg"
            width: root.width
            height: root.height
        }
    
        Column{
            spacing: 50
    
            Row {
    
                TextField {
                    id: writeBladeHeight
                    placeholderText: "Set Blade Height.."
                    inputMethodHints: Qt.ImhDigitsOnly
                    onAccepted: {
                        typeFromArduinoSerial.writeSerial("bladeHeight", ("startX " + (parseFloat(text) + root.zeroBladeHeight)*10) + "\r")
                    }
                    onActiveFocusChanged: {
                        writeBladeHeight.text = ""
                    }
                }
    
                TextField {
                    id: bladeHeightLCD
                    readOnly: true
                    width: 150
                    height: 40
                    background: Rectangle {
                        width: bladeHeightLCD.width
                        height: bladeHeightLCD.height
                        radius: 20
                        color: "black"
                        border.width: 1
                        border.color: "red"
                    }
                    color: "springgreen"
                    font.family: lcdFont.name
                    font.pixelSize: 50
                    font.letterSpacing: 5
                }
    
                RoundButton {
                    id: zeroBladeHeightButton
                    text: "Zero"
                    onClicked: {
                        root.zeroBladeHeight = root.bladeHeight
                        console.log(root.zeroBladeHeight);
                        bladeHeightLCD.text = "0"
                    }
                }
                RoundButton {
                    id: unZeroBladeHeightButton
                    text: "Reset Zero"
                    onClicked: {
                        root.zeroBladeHeight = 0
                        root.bladeHeight = root.bladeHeight - root.zeroBladeHeight
    
                    }
                }
            }
    
    
            Row {
    
                TextField {
                    id: writeBladeAngle
                    placeholderText: "Set Blade Angle.."
                    inputMethodHints: Qt.ImhDigitsOnly
                    onAccepted: {
                        typeFromArduinoSerial.writeSerial("bladeAngle", "startY " + ((parseFloat(text) + root.zeroBladeAngle)*10) + "\r")
                    }
                    onActiveFocusChanged: {
                        writeBladeAngle.text = ""
                    }
                }
    
                TextField {
                    id: bladeAngleLCD
                    readOnly: true
                    width: 150
                    height: 40
                    background: Rectangle {
                        width: bladeAngleLCD.width
                        height: bladeAngleLCD.height
                        radius: 20
                        color: "black"
                        border.width: 1
                        border.color: "red"
                    }
                    color: "springgreen"
                    text: ""
                    font.family: lcdFont.name
                    font.pixelSize: 50
                    font.letterSpacing: 5
                }
    
                RoundButton {
                    id: zeroTwo
                    text: "Zero"
                    onClicked: {
                        root.zeroBladeAngle = root.bladeAngle
                        bladeAngleLCD.text = root.bladeAngle
                        console.log(zeroBladeAngle);
                        bladeAngleLCD.text = "0"
                    }
                }
                RoundButton {
                    id: unZeroTwo
                    text: "Reset Zero"
                    onClicked: {
                        root.zeroBladeAngle = 0
                        bladeAngleLCD.text = root.bladeAngle
                    }
                }
            }
    
    
        }
    }
    
    
    
    
    
    1 Reply Last reply
    0
    • SGaistS Offline
      SGaistS Offline
      SGaist
      Lifetime Qt Champion
      wrote on last edited by
      #2

      Hi,

      You are likely breaking the binding when you push that button.

      Interested in AI ? www.idiap.ch
      Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

      1 Reply Last reply
      0
      • D Offline
        D Offline
        Dave_022
        wrote on last edited by
        #3

        I have tried the following as well to force an update but nothing changes...

              RoundButton {
                        id: unZeroTwo
                        text: "Reset Zero"
                        onClicked: {
                            root.zeroBladeAngle = 0
                            root.bladeAngle = root.bladeAngle - root.zeroBladeAngle
                        }
                    }
        
        1 Reply Last reply
        0
        • D Offline
          D Offline
          Dave_022
          wrote on last edited by
          #4

          I managed to sort it.

                 onBladeHeightValueChanged: bladeHeight = ((bladeHeightValue/10) - zeroBladeHeight).toFixed(1)
          
          

          The maths was messy when taking a number from serial such as 11 then dividing it by 10 to 1.1 and misusing a non-zero zeroBladeHeight number such as 1 it was giving 0.00001. Sorted by fixing result to 1 decimal place.

             signal bladeHeightZeroed
              onBladeHeightZeroed: bladeHeightLCD.text = root.bladeHeight - root.newZeroBladeHeight
              signal bladeHeightUnZeroed
              onBladeHeightUnZeroed: bladeHeightLCD.text = root.bladeHeight
          

          I added signals in main Page area of qml

             RoundButton {
                          id: zeroBladeHeightButton
                          text: "Zero"
                          onClicked: {
                              root.newZeroBladeHeight = root.bladeHeight
                              root.zeroBladeHeight += newZeroBladeHeight
                              bladeHeightZeroed()
                          }
          
                      }
                      RoundButton {
                          id: unZeroBladeHeightButton
                          text: "Reset Zero"
                          onClicked: {
                              root.bladeHeight = root.zeroBladeHeight
                              root.zeroBladeHeight = 0
                              bladeHeightUnZeroed()
                          }
          

          Then called them in buttons to update display. Additional variable allowed me to stack zeroing and the reset

          1 Reply Last reply
          1

          • Login

          • Login or register to search.
          • First post
            Last post
          0
          • Categories
          • Recent
          • Tags
          • Popular
          • Users
          • Groups
          • Search
          • Get Qt Extensions
          • Unsolved