Arduino & Qt



  • Hey,

    i have a Qt Projekt witch communicate with a Arduino.

    I can control GPIO´s with Buttons (LOW / HIGH), but now I want to read for example the status of an GPIO or read a variable from Arduino ...

    Arduino Code:

    #define PIN_LED8 D8
    #define PIN_LED7 D7
    #define PIN_LED6 D6
    
    
    float INT_TEST = 23.3;
    
    void setup()
    {
      pinMode(PIN_LED8, OUTPUT);
      analogWrite(PIN_LED8, 0);
    
      pinMode(PIN_LED7, OUTPUT);
      analogWrite(PIN_LED8, 0);
    
      pinMode(PIN_LED6, OUTPUT);
      analogWrite(PIN_LED8, 0);
      
      Serial.begin(115200);
    }
    
    void loop()
    {
      if (Serial.available()){
        int led_pin = Serial.parseInt();
        int led_brightness = Serial.parseInt();
        write_leds(led_pin, led_brightness);
        Serial.write((byte*)&INT_TEST, 4);
        delay(1000);
        }
    }
    
    void write_leds(int ledpin, int brightness)
    {
      if(ledpin == 8){
        analogWrite(PIN_LED8, brightness);
        return;
      }
        if(ledpin == 7){
        analogWrite(PIN_LED7, brightness);
        return;
      }
        if(ledpin == 6){
        analogWrite(PIN_LED6, brightness);
        return;
      }
      return;
    }
    

    For example I want to read the Status of PIN_LED7 (D7) and the variable INT_TEST.

    My Qt-Code:

    #include "Widget.h"
    #include "ui_Widget.h"
    #include <QSerialPort>
    #include <QSerialPortInfo>
    #include <QMessageBox>
    #include <QDebug>
    
    Widget::Widget(QWidget *parent)
        : QWidget(parent)
        , ui(new Ui::Widget)
    {
        ui->setupUi(this);
    
        arduino_is_available = false;
        arduino_port_name = "";
        arduino = new QSerialPort;
    
    
        //Beim ersten Durchlauf bitte "3 Ausgabe der Anwendung" öffnen und hier die Hersteller ID und Produkt ID entnehmen.
        //Die entnommenen Daten müssen in Widget.h eingetragen werden, andernfalls gibt es keine Kommunikation zwischen Controller und Qt.
        qDebug() << "Erreichte Ports: " << QSerialPortInfo::availablePorts().length();
        foreach(const QSerialPortInfo &serialPortInfo, QSerialPortInfo::availablePorts()){
            qDebug() << "Hersteller ID: " << serialPortInfo.hasVendorIdentifier();
            if(serialPortInfo.hasVendorIdentifier()){
                qDebug() << "Hersteller ID: " << serialPortInfo.vendorIdentifier();
            }
            qDebug() << "Produkt ID: " << serialPortInfo.hasProductIdentifier();
            if(serialPortInfo.hasProductIdentifier()){
                qDebug() << "Produkt ID: " << serialPortInfo.productIdentifier();
            }
        }
    
        foreach(const QSerialPortInfo &serialPortInfo, QSerialPortInfo::availablePorts()){
            if(serialPortInfo.hasVendorIdentifier() && serialPortInfo.hasProductIdentifier()){
                if(serialPortInfo.vendorIdentifier() == arduino_uno_vendor_id){
                    if(serialPortInfo.productIdentifier() == arduino_uno_product_id){
                        arduino_port_name = serialPortInfo.portName();
                        arduino_is_available = true;
                    }
                }
            }
        }
    
        if(arduino_is_available){
            // open and configure the serialport
            arduino->setPortName(arduino_port_name);
            arduino->open(QSerialPort::ReadWrite);
            arduino->setBaudRate(QSerialPort::Baud115200);
            arduino->setDataBits(QSerialPort::Data8);
            arduino->setParity(QSerialPort::NoParity);
            arduino->setStopBits(QSerialPort::OneStop);
            arduino->setFlowControl(QSerialPort::NoFlowControl);
        }else
        {
            // give error message if not available
            QMessageBox::warning(this, "Port error", "Couldn't find the Arduino!");
        }
    }
    
    Widget::~Widget()
    {
        delete ui;
    }
    
    void Widget::on_encenderPushButton_clicked()
    {
        if(arduino->isWritable()){
            arduino->write("8, 255");
        }else{
            qDebug() << "Couldn't write to serial!";
        }
    }
    
    void Widget::on_apagarPushButton_clicked()
    {
    
        if(arduino->isWritable()){
            arduino->write("8, 0");
        }else{
            qDebug() << "Couldn't write to serial!";
        }
    }
    
    void Widget::on_LED_7_0N_clicked()
    {
        if(arduino->isWritable()){
            arduino->write("7, 255");
        }else{
            qDebug() << "Couldn't write to serial!";
        }
    }
    
    void Widget::on_LED_7_OFF_clicked()
    {
        if(arduino->isWritable()){
            arduino->write("7, 0");
        }else{
            qDebug() << "Couldn't write to serial!";
        }
    
    }
    

  • Lifetime Qt Champion

    Hi,

    Do you mean read from your serial port ? If so then use the readyRead signal to know when data is available and process it in the slot you connect to that slot.

    On a side note, you are not checking that your serial port is opened successfully.



  • also please consider adding in your loop in the arduino code a function to send the status of the pin only when asked else it will trigger the emit in Qt few million times a second - witch you do not want

    pseudo code

    in Qt
    void askForPinStatus(int pinNo) {
    serial.write(statuscommand.append(pinNo));
    }
    
    in constructor {
    connect seria, &serialClass::readyRead, this, &thisClassName::thisSlotProcessing);
    }
    
    thisSlotProcessing(QByteArray data){
    pinstatus.pinNo = data.first4bytes
    pinstatus.pinStatus = data.nextBytes
    }
    

    keep in mind that this is just pseudocode and is without any check - you should implement a lot of checks like to see is data received complete or it is not corrupted, ....... hope you've got the idea

    in arduino jest read in the loop all the serial and if you get a command from the serial then make a software interrupt and execute it

    hope that helps...


  • Qt Champions 2018

    @arsinte_andrei

    it will trigger the emit in Qt few million times a second - witch you do not want

    Rather a few hundred times a second. Serial ports are really slow compared to modern computation speed.



  • okay thank you for the answers.

    I want to read for example my integers value in Qt not the serial.

    Arduino:

    float INT_TEST = 23.3; 
    

    this float I will read in Qt and show it on lcd for example.


  • Lifetime Qt Champion

    Hi
    Well if your
    float INT_TEST = 23.3;
    lives in Arduino and you want to show it in another app, then you
    will have to sent the value over say serial to the "lcd" app.

    If the INT_TEST is already where you want to display it, im not sure i understand what
    you ask.



  • Hi
    you understanded right.
    I want to read in Qt my "INT_TEST" value (witch its in Arduino).
    I don't know how.



  • @NotYourFan you have to understand that Qt is not running in Arduino (or better sad in MCU) so what you have to do is to send that variable with serial.write(int_test) to serial and then use a program made in Qt to read it...



  • I understand that Qt is not running in Arduino ... that's why I have one code für my MCU and one Code for the GUI ....
    The question was how to send the data from my MCU to Qt and read the float in Qt ...



  • @NotYourFan using the serial - that is very easy
    firstly you have to design a protocol between your computer and Arduino using the serial interface.
    like: [command][parameter]
    then all you have to do is just to communicate between them based on commands sent from your computer software and not from Arduino - except for some critical errors if you want to - else you will have many messages coming in that you have to process - depending on the serial speed.

    so basically in your loop in Arduino, you should have a function that reads the serial and process it

    pseudo code

    void process|Incomming Serial(serial message){
    if (message.startsWith(command1)){
    do command 1
    } else if (message.startsWith(command2)){
    process command 2;
    read the parameter of the command 2
    }
    // and so on
    }
    

    in Qt you do something very similar

    onReadyRead(){
    QByteArray myMessaage = seriall.readAll;
    if myMessage.startsWith("command1"){
    do command 1 read parameter 1 and so on
    }
    }
    

    and the communication between them should be something like
    [command].[parameter] // or depending on your wish
    pinNo.1.1 // could mean switch pin 1 to 1 -On
    readValue.2 // could mean that the Arduino to reply back what is the value of the pin 2

    in order to unload the serial traffic I do recommend you to use not strings as commands but hex codes - anyway start first with strings until you get pretty confident in what are you doing and then switch to hex



  • @NotYourFan oh, I've forgotten to add that you need a serial port on your computer and in Qt, you have to select that com / or a USB serial adaptor and to be 100% sure that your operating system have the drivers loaded up first



  • my Serial communication works perfect (look at the code on the Top that I posted)

    I can actually control gpios with buttons.

    In short time I will install a temperature sensor and read the float in Arduino.
    Thats the reason I posted here the question.


  • Qt Champions 2018

    @NotYourFan @SGaist already suggested to use readyRead() signal to read from the serial port - did you try? What exactly is the problem?


Log in to reply