Arduino analog input to QT Gauge.
-
Thank you for your help, it turns out all I had to do was restart QT Creator.
I'm not stuck on another problem and could I ask for your help?
Ive removed the C++ gauge example and replaced it with a simple QML gauge, I would like to take my serial signal and place it in the needleAngle slot.
Could you tell me the best way to do this as my code seems to emit a lot of errors.
*.proQT += core gui serialport qml QT += quick greaterThan(QT_MAJOR_VERSION, 4): QT += widgets TARGET = 300zx TEMPLATE = app DEFINES += QT_DEPRECATED_WARNINGS SOURCES += main.cpp\ dialog.cpp HEADERS += dialog.h FORMS += dialog.ui DISTFILES += \ main.qml \ QtQuickViewManager/View.pri \ QtQuickViewManager/README.md \ oiltemp.qml include(./QtQuickViewManager/View.pri) RESOURCES += \ resource.qrc QML_IMPORT_PATH =
*.h
#ifndef DIALOG_H #define DIALOG_H #include <QDialog> #include <QSerialPort> #include <QByteArray> namespace Ui { class Dialog; } class Dialog : public QDialog { Q_OBJECT public: explicit Dialog(QWidget *parent = 0); ~Dialog(); signals: void oil_pressure_bar(QVariant num); public slots: void analogRead2(); void analogRead3(); void updateOilPressure(QString); void updateOilTemperature(QString); void needleAngle(QVariant num); private: Ui::Dialog *ui; QSerialPort *arduino; static const quint16 arduino_uno_vendor_id = 0x2341; static const quint16 arduino_uno_product_id = 0x0001; QByteArray serialData; QString serialBuffer; QString parsed_data; double oil_pressure_volt; }; #endif // DIALOG_H
*.cpp
#include "dialog.h" #include "ui_dialog.h" #include <QSerialPort> #include <QSerialPortInfo> #include <string> #include <QDebug> #include <QMessageBox> #include <QQuickView> #include <QQmlApplicationEngine> #include <QtQuickWidgets/QQuickWidget> Dialog::Dialog(QWidget *parent) : QDialog(parent), ui(new Ui::Dialog) { ui->setupUi(this); setWindowFlags(Qt::Dialog | Qt::FramelessWindowHint); ui->oilpress_LCD1->display("-------"); ui->oilpressraw_LCD2->display("-------"); ui->oiltemp_LCD1->display("-------"); ui->oiltempraw_LCD2->display("-------"); QQuickView *view = new QQuickView(); QWidget *container = QWidget::createWindowContainer(view, this); container->setMinimumSize(250, 250); container->setMaximumSize(250, 250); container->setFocusPolicy(Qt::TabFocus); view->setSource(QUrl("qrc:/new/prefix1/main.qml")); ui->verticalLayout->addWidget(container); *italicised text* auto Dialog = new QDialog(this); auto quickWidget = new QQuickWidget(QUrl("main.qml"), this); auto Rectangle = quickWidget->rootObject(); // Connect C++ signal to QML slot QObject::connect(Dialog, SIGNAL(oil_pressure_bar(QVariant num)),Rectangle, SLOT(needleAngle(QVariant num))); arduino = new QSerialPort(this); serialBuffer = ""; parsed_data = ""; oil_pressure_volt = 0.0; //oil_pressure_bar = 0.0; bool arduino_is_available = false; QString arduino_uno_port_name; 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_uno_port_name = serialPortInfo.portName(); } } } /* * Open and configure the arduino port if available */ if(arduino_is_available){ qDebug() << "Found the arduino port...\n"; arduino->setPortName(arduino_uno_port_name); arduino->open(QSerialPort::ReadOnly); arduino->setBaudRate(QSerialPort::Baud57600); arduino->setDataBits(QSerialPort::Data8); arduino->setFlowControl(QSerialPort::NoFlowControl); arduino->setParity(QSerialPort::NoParity); arduino->setStopBits(QSerialPort::OneStop); QObject::connect(arduino, SIGNAL(readyRead()), this, SLOT(analogRead2())); QObject::connect(arduino, SIGNAL(readyRead()), this, SLOT(analogRead3())); }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::analogRead2() { QStringList buffer_split = serialBuffer.split(","); if(buffer_split.length() < 3) { serialData = arduino->readAll(); serialBuffer = serialBuffer + QString::fromStdString(serialData.toStdString()); serialData.clear(); }else{ serialBuffer = ""; qDebug() << buffer_split << "\n"; parsed_data = buffer_split[1]; //oil_pressure_bar = (0.008) * (parsed_data.toDouble()); oil_pressure_volt = (0.0048) * (parsed_data.toDouble()); qDebug() << "Pressure: " << oil_pressure_volt << "\n"; Dialog::updateOilPressure(parsed_data); } } void Dialog::updateOilPressure(QString sensor_reading) { //ui->oilpress_LCD1->display(oil_pressure_bar); ui->oilpressraw_LCD2->display(oil_pressure_volt); }
main.cpp
#include "dialog.h" #include <QApplication> #include <QWidget> #include <QCoreApplication> #include <QFile> #include <QString> #include <QDebug> #include <QTextStream> #include <ViewManagement.h> #include <QGuiApplication> #include <QScopedPointer> #include <QQmlApplicationEngine> #include <QSerialPort> #include <QSerialPortInfo> #include <QObject> void read(QString filename) { QFile file(filename); if(!file.open(QFile::ReadOnly | QFile::Text)) { qDebug() << " Could not open the file for reading"; return; } QTextStream in(&file); QString myText = in.readAll(); // put QString into qDebug stream qDebug() << myText; file.close(); } int main(int argc, char *argv[]) { QApplication a(argc, argv); QWidget widget(0); Dialog w; w.setWindowTitle("Temperature Sensor Reading"); w.setFixedSize(800,480); w.show(); return a.exec(); }
*.qml
import QtQuick 2.1 import QtQuick.Controls 2.0 import QtQuick.Extras 1.4 import QtSensors 5.7 Rectangle { id: gauge width: 500 height: 250 property alias btnMinus: btnMinus property alias needle: needle property alias btnPlus: btnPlus property double needleAngle: 0; Image { id: background x: 0 y: 0 width: 250 height: 250 source: "Img/background.png" Image { id: needle x: 92 y: 121 width: 150 height: 8 source: "Img/needle.png" transform: Rotation {origin.x: 35; origin.y: 5; angle: needleAngle} smooth: true } Button { id: btnPlus x: 8 y: 192 width: 50 height: 50 text: qsTr("+") onClicked: needleAngle +=10 } Button { id: btnMinus x: 192 y: 192 width: 50 height: 50 text: qsTr("-") onClicked: needleAngle -=10 } } }
And again any help and advice would be much appreciated.
-
What errors is it emitting ?
-
C:\Users\Stephn\Documents\300zx\dialog.cpp:37: error: no matching function for call to 'Dialog::connect(QDialog*&, const char*, QQuickItem*&, const char*)'
QObject::connect(Dialog, SIGNAL(oil_pressure_bar(QVariant)),Rectangle, SLOT(needleAngle(QVariant)));
^This is the error I'm getting. much appreciated.
-
You are trying to connect classes. You have to connect instances of these classes.
-
And by classes you mean "dialog" when I should be connecting " updatedoilpress"?
And instead of "Rectangle" I should be connecting Rotation"?Also would this QObject::Connect be the easiest and simplest way of connecting a C++ signal (analogread2, oil_press_bar) to a QML Slot (Neeedle, needleAngle)?
-
You'd have to search for the objects you are interest in in your engine and then connect them.
By the way, why not make this dialog also with QtQuick ?
-
Ok so id search for the instances, I can google how to do that.
What are the benefits of using QtQuick, over my method?
-
That was just curiosity. Nothing wrong in mixing both. If you go with a QtQuick only GUI you should be able to drop the dependency on the QtWidgets module which makes your application lighter weight.
-
Hi,
I took your advice and used the cpp for serial data collection and the qml for the GUI, but I'm having a problem with this error.
C:\Users\Stephn\Documents\nissan300zx\serialport.h:50: error: 'double SerialPort::oil_pressure_volt' conflicts with a previous declaration
double oil_pressure_volt;
^I know that the code is duplicating names, but id like to read that name in Q_Property and then send it to QML.
#ifndef SERIALPORT_H #define SERIALPORT_H #include <QObject> #include <QQuickItem> #include <QSerialPort> #include <QSerialPortInfo> #include <QByteArray> class SerialPort : public QObject { Q_OBJECT Q_PROPERTY(QString oil_pressure_volt READ oil_pressure_volt WRITE set_oil_pressure_volt NOTIFY oil_pressure_volt_Changed) public: SerialPort(QObject *parent = 0); SerialPort(QString); QString oil_pressure_volt() const { return m_oil_pressure_volt; } public slots: void analogRead2(); void updateOilPressure(QString); void set_oil_pressure_volt(QString oil_pressure_volt) { if (m_oil_pressure_volt == oil_pressure_volt) return; m_oil_pressure_volt = oil_pressure_volt; emit oil_pressure_volt_Changed(oil_pressure_volt); } signals: void oil_pressure_volt_Changed(QString oil_pressure_volt); private: QSerialPort *arduino; static const quint16 arduino_uno_vendor_id = 0x2341; static const quint16 arduino_uno_product_id = 0x0001; QByteArray serialData; QString serialBuffer; QString parsed_data; double oil_pressure_volt; QString m_oil_pressure_volt; }; #endif // SERIALPORT_H
Could I rename the oil_pressure_volt in the CPP
void SerialPort::updateOilPressure(QString sensor_reading) { //oil_pressure_volt(double) = data; }
-
Why are you declaring a oil_pressure_volt property QString then the matching variable as double and still use QString everywhere ?
-
Sorry, that was me trying different ideas out.
#ifndef SERIALPORT_H #define SERIALPORT_H #include <QObject> #include <QQuickItem> #include <QSerialPort> #include <QSerialPortInfo> #include <QByteArray> class SerialPort : public QObject { Q_OBJECT Q_PROPERTY(double oil_pressure_volt READ oil_pressure_volt WRITE set_oil_pressure_volt NOTIFY oil_pressure_volt_Changed) public: SerialPort(QObject *parent = 0); SerialPort(QString); double oil_pressure_volt() const { return m_oil_pressure_volt; } public slots: void analogRead2(); void updateOilPressure(QString); void set_oil_pressure_volt(double oil_pressure_volt) { if (m_oil_pressure_volt == oil_pressure_volt) return; m_oil_pressure_volt = oil_pressure_volt; emit oil_pressure_volt_Changed(oil_pressure_volt); } signals: void oil_pressure_volt_Changed(double oil_pressure_volt); private: QSerialPort *arduino; static const quint16 arduino_uno_vendor_id = 0x2341; static const quint16 arduino_uno_product_id = 0x0001; QByteArray serialData; QString serialBuffer; QString parsed_data; double oil_pressure_volt; double m_oil_pressure_volt; }; #endif // SERIALPORT_H This is the error, C:\Users\Stephn\Documents\nissan300zx\serialport.h:48: error: 'double SerialPort::oil_pressure_volt' conflicts with a previous declaration double oil_pressure_volt; ^
-
Hi, So after making a few suggested changes I cant now display a "0" on my qml text field, I think this zero is the first reading of the analogRead 2.
I changed to this in the main.
engine.rootContext()->setContextProperty("serialport", &serialport);
and this in the header.
Q_PROPERTY( double oilPressureVoltage MEMBER m_oil_pressure_volt WRITE set_oil_pressure_volt NOTIFY oil_pressure_volt_Changed )
I think I need to add some code into a string,
#ifndef SERIALPORT_H #define SERIALPORT_H #include <QObject> #include <QQuickItem> #include <QSerialPort> #include <QSerialPortInfo> #include <QByteArray> class SerialPort : public QObject { Q_OBJECT Q_PROPERTY( double oilPressureVoltage MEMBER m_oil_pressure_volt WRITE set_oil_pressure_volt NOTIFY oil_pressure_volt_Changed ) public: SerialPort(QObject *parent = 0); SerialPort(QString); public slots: void analogRead2(); void updateOilPressure(QString); void set_oil_pressure_volt(double oilPressureVoltage) { if (m_oilPressureVoltage == oilPressureVoltage) return; m_oilPressureVoltage = oilPressureVoltage; emit oil_pressure_volt_Changed(oilPressureVoltage); } signals: void oil_pressure_volt_Changed(double oilPressureVoltage); private: QSerialPort *arduino; static const quint16 arduino_uno_vendor_id = 0x2341; static const quint16 arduino_uno_product_id = 0x0001; QByteArray serialData; QString serialBuffer; QString parsed_data; double oil_pressure_volt; double m_oilPressureVoltage; }; #endif // SERIALPORT_H
-
Can you how how you are using that class in QML ?
-
yes its...
import QtQuick 2.5 import QtQuick.Window 2.2 import QtQuick.Extras 1.4 import QtQuick.Controls 2.0 import SerialPortlib 1.0 Window { id: gauge visible: true width: 640 height: 480 TextEdit { id: textEdit text: SerialPort.newValue verticalAlignment: Text.AlignVCenter horizontalAlignment: Text.AlignCenter } } and...
int main(int argc, char *argv[])
{
QGuiApplication app(argc, argv);
SerialPort serialport;
qmlRegisterType<SerialPort>("SerialPortlib", 1, 0, "SerialPort");
QQmlApplicationEngine engine;
engine.load(QUrl(QStringLiteral("qrc:/main.qml")));return app.exec();
-
What's that
newValue
?You seem to be trying to use a
SerialPort
object but you are currently accessing it's class (or Type in QML).You either need to create a SerialPort object in QML or give an instance from it to the engine.
Did you already read the QML CPP integration chapter of Qt's documentation ?
-
I tried to create an object by doing;
import QtQuick 2.5 import QtQuick.Window 2.2 import QtQuick.Extras 1.4 import QtQuick.Controls 2.0 import SerialPortlib 1.0 Window { visible: true width: 640 height: 480 id: gauge SerialPort{ OnOil_pressure_volt_Changed:(console.log(newValue)); } }
with no joy, is this what your referring too?
-
Your QML slot name is wrong.
AFAIK it should be
onOil_pressure_volt_changed
Note that Qt's naming style is camelCase, that might help you match your code with the documentation.You should maybe take a look at http://qmlbook.org
-
Ahh thank you, that was an interesting read, ive achieved what I wanted.
-
Great !
In that case, please mark the thread as solved using the "Topic Tools" button so that other forum users may know a solution has been found :)