Important: Please read the Qt Code of Conduct - https://forum.qt.io/topic/113070/qt-code-of-conduct

textfield updates intermittent 'garbage'



  • 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
                    }
                }
            }
    
    
        }
    }
    
    
    
    
    

  • Lifetime Qt Champion

    Hi,

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



  • 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
                    }
                }
    


  • 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


Log in to reply