Skip to content
  • Categories
  • Recent
  • Tags
  • Popular
  • Users
  • Groups
  • Search
  • Get Qt Extensions
  • Unsolved
Collapse
Brand Logo
  1. Home
  2. Qt Development
  3. General and Desktop
  4. Signal receiving problem from Arduino to Qt graphics view
Qt 6.11 is out! See what's new in the release blog

Signal receiving problem from Arduino to Qt graphics view

Scheduled Pinned Locked Moved Unsolved General and Desktop
18 Posts 4 Posters 5.0k 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.
  • Macive XiongM Macive Xiong

    Hi @SGaist

    I tried to convert the values of X from 94 to 512 and put ellipses on these positions by values of X. So it supposed to be a line if it works fine. Any suggestion??

    Hi @VRonin ,

    Thank you so much for your information. Sorry I am a very new on Qt. I understand the problem is the "readAll()" command but I don't know what else can I change. Is the readFortune the solution??

    Hi @jazzycamel,

    Thank you so much for your help. I tried the first solution but it didn't work. It shows a message that my Qt.exe has stopped working. The code is:

    void MainWindow::updateP(){
        const QByteArray data = arduino->readAll();
        QTextStream stream(data);
        QString line;
        while(stream.readLineInto(&line)){
            line.replace(" ","").replace("\n","");
            if(line.length()<=0) continue;
            QStringList bits=line.split("=");
            if(bits[0]!="x") continue;
            bool ok;
            int x=bits[1].toInt(&ok);
            if(!ok) continue;
    
            //set scene
            QBrush redBrush(Qt::red);
            QPen blackpen(Qt::black);
            blackpen.setWidth(1);
    
            //qDebug() << "x1:" << x1;
            //qDebug() << "y1:" << y1;
            ellipse = scene->addEllipse(x, 100, 10, 10, blackpen, redBrush);
        }
    }
    void MainWindow::readSerial()
    {
        this->updateP();
    }
    

    The stopped working message

    Then I tried the second solution, the QRegularExpression:

    void MainWindow::updateP()
    {
            const QByteArray data = arduino->readAll();
            QTextStream stream(data);
            QString line;
            while(stream.readLineInto(&line)){
                QRegularExpression re("x = ([0-9]{2,3})");
                QRegularExpressionMatch match=re.match(line);
                if(!match.hasMatch()) continue;
                QString matched=match.captured(1);
                bool ok;
                int x=matched.toInt(&ok);
                if(!ok) continue;
    
            //set scene
            QBrush redBrush(Qt::red);
            QPen blackpen(Qt::black);
            blackpen.setWidth(1);
    
            //qDebug() << "x1:" << x1;
            //qDebug() << "y1:" << y1;
            ellipse = scene->addEllipse(x, 100, 10, 10, blackpen, redBrush);
        }
    }
    
    
    void MainWindow::readSerial()
    {
        this->updateP();
    }
    

    It shows like this

    My Arduino code is the same:

    void setup() {
      Serial.begin(9600);
    
    }
    
    void loop() { 
      for ( int x = 94; x <=512; x++){
        delay(100);
        Serial.print("x = ");
        Serial.println(x);
      }
    }
    

    Thank you guys for the answers. It's really helpful, but my project is still not working, please give me more information and solution... I appreciate it.

    jazzycamelJ Offline
    jazzycamelJ Offline
    jazzycamel
    wrote on last edited by
    #8

    @Macive-Xiong

    Ok, I don't know why your program isn't working or why its hanging. The following is a fully working example that I've tested with an Arduino Uno running your code connected to my MacBook Pro running the following (compiled with Qt5.6):

    Forum2.pro

    QT       += core gui serialport
    
    greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
    
    TARGET = Forum2
    TEMPLATE = app
    
    
    SOURCES += main.cpp\
            mainwindow.cpp
    
    HEADERS  += mainwindow.h
    

    mainwindow.h

    #ifndef MAINWINDOW_H
    #define MAINWINDOW_H
    
    #include <QMainWindow>
    
    class QSerialPort;
    class QGraphicsScene;
    class QGraphicsView;
    
    class MainWindow : public QMainWindow
    {
        Q_OBJECT
    
    public:
        MainWindow(QWidget *parent = 0);
        ~MainWindow();
    
    public slots:
        void updateP();
    
    private:
        QGraphicsScene *scene;
        QGraphicsView *view;
        QSerialPort *arduino;
        bool open;
    };
    
    #endif // MAINWINDOW_H
    

    mainwindow.cpp

    #include <QRegularExpression>
    #include <QTextStream>
    #include <QDebug>
    #include <QtSerialPort>
    #include <QGraphicsScene>
    #include <QGraphicsView>
    
    #include "mainwindow.h"
    
    MainWindow::MainWindow(QWidget *parent)
        : QMainWindow(parent), open(false)
    {
        this->resize(1024,768);
    
        scene=new QGraphicsScene(this);
        scene->setSceneRect(0,0,1024,768);
        view=new QGraphicsView(scene, this);
        setCentralWidget(view);
    
        arduino=new QSerialPort("/dev/ttys002");
        arduino->setBaudRate(QSerialPort::Baud9600);
        connect(arduino, SIGNAL(readyRead()), this, SLOT(updateP()));
        if(!arduino->open(QSerialPort::ReadOnly)){
            qDebug() << "Failed to open serial port!";
            return;
        }
        open=true;
    }
    
    MainWindow::~MainWindow(){}
    
    void MainWindow::updateP(){
        if(!open) return;
    
        QTextStream stream(arduino);
        QString line;
        while(stream.readLineInto(&line)){
            QRegularExpression re("x = ([0-9]{2,3})");
            QRegularExpressionMatch match=re.match(line);
            if(!match.hasMatch()) continue;
            QString matched=match.captured(1);
            bool ok;
            int x=matched.toInt(&ok);
            if(!ok) continue;
    
            QBrush redBrush(Qt::red);
            QPen blackPen(Qt::black, 1.);
            scene->addEllipse(x, 768/2., 20, 20, blackPen, redBrush);
        }
    }
    

    main.cpp

    #include "mainwindow.h"
    #include <QApplication>
    
    int main(int argc, char *argv[])
    {
        QApplication a(argc, argv);
        MainWindow w;
        w.show();
    
        return a.exec();
    }
    

    You will need to change the name of the serial/COM port being passed to QSerialPort in line 20 of mainwindow.cpp.

    I hope this gets you up and running :)

    For the avoidance of doubt:

    1. All my code samples (C++ or Python) are tested before posting
    2. As of 23/03/20, my Python code is formatted to PEP-8 standards using black from the PSF (https://github.com/psf/black)
    Macive XiongM 1 Reply Last reply
    2
    • jazzycamelJ jazzycamel

      @Macive-Xiong

      Ok, I don't know why your program isn't working or why its hanging. The following is a fully working example that I've tested with an Arduino Uno running your code connected to my MacBook Pro running the following (compiled with Qt5.6):

      Forum2.pro

      QT       += core gui serialport
      
      greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
      
      TARGET = Forum2
      TEMPLATE = app
      
      
      SOURCES += main.cpp\
              mainwindow.cpp
      
      HEADERS  += mainwindow.h
      

      mainwindow.h

      #ifndef MAINWINDOW_H
      #define MAINWINDOW_H
      
      #include <QMainWindow>
      
      class QSerialPort;
      class QGraphicsScene;
      class QGraphicsView;
      
      class MainWindow : public QMainWindow
      {
          Q_OBJECT
      
      public:
          MainWindow(QWidget *parent = 0);
          ~MainWindow();
      
      public slots:
          void updateP();
      
      private:
          QGraphicsScene *scene;
          QGraphicsView *view;
          QSerialPort *arduino;
          bool open;
      };
      
      #endif // MAINWINDOW_H
      

      mainwindow.cpp

      #include <QRegularExpression>
      #include <QTextStream>
      #include <QDebug>
      #include <QtSerialPort>
      #include <QGraphicsScene>
      #include <QGraphicsView>
      
      #include "mainwindow.h"
      
      MainWindow::MainWindow(QWidget *parent)
          : QMainWindow(parent), open(false)
      {
          this->resize(1024,768);
      
          scene=new QGraphicsScene(this);
          scene->setSceneRect(0,0,1024,768);
          view=new QGraphicsView(scene, this);
          setCentralWidget(view);
      
          arduino=new QSerialPort("/dev/ttys002");
          arduino->setBaudRate(QSerialPort::Baud9600);
          connect(arduino, SIGNAL(readyRead()), this, SLOT(updateP()));
          if(!arduino->open(QSerialPort::ReadOnly)){
              qDebug() << "Failed to open serial port!";
              return;
          }
          open=true;
      }
      
      MainWindow::~MainWindow(){}
      
      void MainWindow::updateP(){
          if(!open) return;
      
          QTextStream stream(arduino);
          QString line;
          while(stream.readLineInto(&line)){
              QRegularExpression re("x = ([0-9]{2,3})");
              QRegularExpressionMatch match=re.match(line);
              if(!match.hasMatch()) continue;
              QString matched=match.captured(1);
              bool ok;
              int x=matched.toInt(&ok);
              if(!ok) continue;
      
              QBrush redBrush(Qt::red);
              QPen blackPen(Qt::black, 1.);
              scene->addEllipse(x, 768/2., 20, 20, blackPen, redBrush);
          }
      }
      

      main.cpp

      #include "mainwindow.h"
      #include <QApplication>
      
      int main(int argc, char *argv[])
      {
          QApplication a(argc, argv);
          MainWindow w;
          w.show();
      
          return a.exec();
      }
      

      You will need to change the name of the serial/COM port being passed to QSerialPort in line 20 of mainwindow.cpp.

      I hope this gets you up and running :)

      Macive XiongM Offline
      Macive XiongM Offline
      Macive Xiong
      wrote on last edited by
      #9

      Hi @jazzycamel ,

      Your every answer is really helpful. Thank you so much for this. I copied the exactly the same code you provide and change the serial port.
      My graphicsView seems like

      Can you take a screen shot on your graphicsView screen for me? And any suggestion?? I think the graphicsView should be the line which is connected by the ellipses from x = 94 to x = 512. Thank you so much.

      jazzycamelJ 1 Reply Last reply
      0
      • Macive XiongM Macive Xiong

        Hi @jazzycamel ,

        Your every answer is really helpful. Thank you so much for this. I copied the exactly the same code you provide and change the serial port.
        My graphicsView seems like

        Can you take a screen shot on your graphicsView screen for me? And any suggestion?? I think the graphicsView should be the line which is connected by the ellipses from x = 94 to x = 512. Thank you so much.

        jazzycamelJ Offline
        jazzycamelJ Offline
        jazzycamel
        wrote on last edited by
        #10

        @Macive-Xiong

        Probably a timing issue. Try putting a longer delay between the Serial.println() in the Arduino code and see if it improves. Mine looks like the following:

        Output Screenshot

        For the avoidance of doubt:

        1. All my code samples (C++ or Python) are tested before posting
        2. As of 23/03/20, my Python code is formatted to PEP-8 standards using black from the PSF (https://github.com/psf/black)
        Macive XiongM 1 Reply Last reply
        0
        • jazzycamelJ jazzycamel

          @Macive-Xiong

          Probably a timing issue. Try putting a longer delay between the Serial.println() in the Arduino code and see if it improves. Mine looks like the following:

          Output Screenshot

          Macive XiongM Offline
          Macive XiongM Offline
          Macive Xiong
          wrote on last edited by Macive Xiong
          #11

          Hi @jazzycamel

          I tried to extend my delay time but it didn't work. And I thought it's about the data rate problem. So I changed the Serial.begin from 9600 to 115200. And it works fine. Even my original code is fine:)

          0_1472656321946_2016-08-31 (5).png

          But here are some questions, why there are so many red ellipse running in the same time? Despite I set it as "for" loop. But is the second ellipse supposed to be set after first ellipse run to the end??

          And about the code you provided:

          QRegularExpression re("x = ([0-9]{2,3})");
          

          the class information says is a pattern, but why [0-9]{2,3}?

          Thank you so much for your help:)

          1 Reply Last reply
          0
          • VRoninV Offline
            VRoninV Offline
            VRonin
            wrote on last edited by VRonin
            #12

            The fact that it's not a continuing series of data is probably due to the fact that you read half lines that are skipped by if(!match.hasMatch()) continue;. This is the problem with readAll I was talking about.

            try replacing

            if(!match.hasMatch()) continue;
            

            with

            if(!match.hasMatch()){
            qDebug() << "Row Skipped";
            continue;
            }
            

            and see how many get skipped

            QRegularExpression uses perl regular expression. there are whole books written on this sintax, a quick reference can be found here http://www.regular-expressions.info/refquick.html

            "x = ([0-9]{2,3})" means "x = " followed by 2 or 3 digits, the parethesis are used to capture part of the text that is then retrieved by match.captured(1);

            "La mort n'est rien, mais vivre vaincu et sans gloire, c'est mourir tous les jours"
            ~Napoleon Bonaparte

            On a crusade to banish setIndexWidget() from the holy land of Qt

            1 Reply Last reply
            2
            • jazzycamelJ Offline
              jazzycamelJ Offline
              jazzycamel
              wrote on last edited by
              #13

              @Macive-Xiong

              There are so many red ellipses because you draw a new one for each value of x rather than moving the original one. Try adding the ellipse once in the MainWindow constructor and then calling ellipse->setPos(x,10); in MainWindow::updateP().

              As @VRonin points out (and as I've said in my posts), this is a very basic, idealised example of how to read and process data from an asynchronous stream. You should probably add available data to a buffer each time readyRead() is emitted and then process it such that partially received data is not lost/thrown away.

              Below is a slightly more complex version of above (still not complete!) and here is a video of it working (I'm sending a Sine function from the Arduino):

              mainwindow.h

              #ifndef MAINWINDOW_H
              #define MAINWINDOW_H
              
              #include <QMainWindow>
              
              class QSerialPort;
              class QGraphicsScene;
              class QGraphicsView;
              class QGraphicsEllipseItem;
              
              class MainWindow : public QMainWindow
              {
                  Q_OBJECT
              
              public:
                  MainWindow(QWidget *parent = 0);
                  ~MainWindow();
              
              public slots:
                  void updateP();
              
              private:
                  QGraphicsScene *scene;
                  QGraphicsView *view;
                  QGraphicsEllipseItem *ellipse;
                  QSerialPort *arduino;
                  bool open;
              };
              
              #endif // MAINWINDOW_H
              

              mainwindow.cpp

              #include <QRegularExpression>
              #include <QTextStream>
              #include <QDebug>
              #include <QtSerialPort>
              #include <QGraphicsScene>
              #include <QGraphicsView>
              #include <QGraphicsEllipseItem>
              
              #include "mainwindow.h"
              
              MainWindow::MainWindow(QWidget *parent)
                  : QMainWindow(parent), open(false)
              {
                  this->resize(1024,768);
              
                  scene=new QGraphicsScene(this);
                  scene->setSceneRect(0,0,1024,768);
                  view=new QGraphicsView(scene, this);
                  setCentralWidget(view);
              
                  arduino=new QSerialPort("/dev/ttys005");
                  arduino->setBaudRate(QSerialPort::Baud9600);
                  connect(arduino, SIGNAL(readyRead()), this, SLOT(updateP()));
                  if(!arduino->open(QSerialPort::ReadOnly)){
                      qDebug() << "Failed to open serial port!";
                      return;
                  }
                  open=true;
              
                  QBrush redBrush(Qt::red);
                  QPen blackPen(Qt::black, 1.);
                  ellipse=scene->addEllipse(0, 768/2., 20, 20, blackPen, redBrush);
              }
              
              MainWindow::~MainWindow(){}
              
              void MainWindow::updateP(){
                  if(!open) return;
              
                  QTextStream stream(arduino);
                  QString line;
                  while(stream.readLineInto(&line)){
                      QRegularExpression re("x = ([0-9]{2,3})");
                      QRegularExpressionMatchIterator i=re.globalMatch(line);
                      while(i.hasNext()){
                          QRegularExpressionMatch match=i.next();
                          if(!match.hasMatch()){
                              qDebug() << "No match!";
                              continue;
                          }
                          QString matched=match.captured(1);
                          bool ok=false;
                          int x=matched.toInt(&ok);
                          if(!ok){
                              qDebug() << "Could not convert \"" << matched <<"\" to an integer!";
                              continue;
                          }
                          ellipse->setPos(x,0.);
                      }
                  }
              }
              

              For the avoidance of doubt:

              1. All my code samples (C++ or Python) are tested before posting
              2. As of 23/03/20, my Python code is formatted to PEP-8 standards using black from the PSF (https://github.com/psf/black)
              Macive XiongM 1 Reply Last reply
              2
              • jazzycamelJ jazzycamel

                @Macive-Xiong

                There are so many red ellipses because you draw a new one for each value of x rather than moving the original one. Try adding the ellipse once in the MainWindow constructor and then calling ellipse->setPos(x,10); in MainWindow::updateP().

                As @VRonin points out (and as I've said in my posts), this is a very basic, idealised example of how to read and process data from an asynchronous stream. You should probably add available data to a buffer each time readyRead() is emitted and then process it such that partially received data is not lost/thrown away.

                Below is a slightly more complex version of above (still not complete!) and here is a video of it working (I'm sending a Sine function from the Arduino):

                mainwindow.h

                #ifndef MAINWINDOW_H
                #define MAINWINDOW_H
                
                #include <QMainWindow>
                
                class QSerialPort;
                class QGraphicsScene;
                class QGraphicsView;
                class QGraphicsEllipseItem;
                
                class MainWindow : public QMainWindow
                {
                    Q_OBJECT
                
                public:
                    MainWindow(QWidget *parent = 0);
                    ~MainWindow();
                
                public slots:
                    void updateP();
                
                private:
                    QGraphicsScene *scene;
                    QGraphicsView *view;
                    QGraphicsEllipseItem *ellipse;
                    QSerialPort *arduino;
                    bool open;
                };
                
                #endif // MAINWINDOW_H
                

                mainwindow.cpp

                #include <QRegularExpression>
                #include <QTextStream>
                #include <QDebug>
                #include <QtSerialPort>
                #include <QGraphicsScene>
                #include <QGraphicsView>
                #include <QGraphicsEllipseItem>
                
                #include "mainwindow.h"
                
                MainWindow::MainWindow(QWidget *parent)
                    : QMainWindow(parent), open(false)
                {
                    this->resize(1024,768);
                
                    scene=new QGraphicsScene(this);
                    scene->setSceneRect(0,0,1024,768);
                    view=new QGraphicsView(scene, this);
                    setCentralWidget(view);
                
                    arduino=new QSerialPort("/dev/ttys005");
                    arduino->setBaudRate(QSerialPort::Baud9600);
                    connect(arduino, SIGNAL(readyRead()), this, SLOT(updateP()));
                    if(!arduino->open(QSerialPort::ReadOnly)){
                        qDebug() << "Failed to open serial port!";
                        return;
                    }
                    open=true;
                
                    QBrush redBrush(Qt::red);
                    QPen blackPen(Qt::black, 1.);
                    ellipse=scene->addEllipse(0, 768/2., 20, 20, blackPen, redBrush);
                }
                
                MainWindow::~MainWindow(){}
                
                void MainWindow::updateP(){
                    if(!open) return;
                
                    QTextStream stream(arduino);
                    QString line;
                    while(stream.readLineInto(&line)){
                        QRegularExpression re("x = ([0-9]{2,3})");
                        QRegularExpressionMatchIterator i=re.globalMatch(line);
                        while(i.hasNext()){
                            QRegularExpressionMatch match=i.next();
                            if(!match.hasMatch()){
                                qDebug() << "No match!";
                                continue;
                            }
                            QString matched=match.captured(1);
                            bool ok=false;
                            int x=matched.toInt(&ok);
                            if(!ok){
                                qDebug() << "Could not convert \"" << matched <<"\" to an integer!";
                                continue;
                            }
                            ellipse->setPos(x,0.);
                        }
                    }
                }
                
                Macive XiongM Offline
                Macive XiongM Offline
                Macive Xiong
                wrote on last edited by Macive Xiong
                #14

                @jazzycamel and @VRonin

                Thank you guys so much for your help. Your answer is extremely helpful for novice:)

                I am wondering if I could control both X and Y in the same time, my Arduino code is :

                
                
                void setup() {
                  Serial.begin(115200);
                
                }
                
                void loop() { 
                
                int x1 = 10;
                int y1 = 15;
                int y = y1;
                
                while (y<=100)
                   {
                     
                     for ( int x = x1; x <= 100; x++) {
                       delay(100);
                       Serial.print("x = ");
                       Serial.println(x);
                     }
                
                     y += 10;
                     Serial.print("y = ");
                     Serial.println(y);
                
                     for (int x = 100; x >= x1; x--) {
                       delay(100);
                       Serial.print("x = ");
                       Serial.println(x);
                     }
                
                     y += 10;
                
                     Serial.print("y = ");
                     Serial.println(y);
                   }
                
                }
                

                The graphicsView is supposed to be like

                How can I change the code? I think the readAll should be replaced by read x and y data separately, and the QRegularExpression also need to include y.

                const QByteArray data = arduino->readAll();
                        QTextStream stream(data);
                        QString line;
                        while(stream.readLineInto(&line)){
                            QRegularExpression re("x = ([0-9]{2,3})");
                            QRegularExpressionMatch match=re.match(line);
                            if(!match.hasMatch()){
                                qDebug()<<"ROW Skipped";
                                continue;
                            }
                            QString matched=match.captured(1);
                            bool ok;
                            int x=matched.toInt(&ok);
                            int y=matched.toInt(&ok);
                            if(!ok) continue;
                
                //set scene
                        QBrush redBrush(Qt::red);
                        QPen blackpen(Qt::black);
                        blackpen.setWidth(1);
                
                
                        ellipse = scene->addEllipse(x, y, 10, 10, blackpen, redBrush);
                
                

                I've tried this code and it will update x for x and y since I read all signal. Is there any suggestion? Thank you so much:)

                1 Reply Last reply
                0
                • jazzycamelJ Offline
                  jazzycamelJ Offline
                  jazzycamel
                  wrote on last edited by
                  #15

                  @Macive-Xiong

                  Very doable, you just need to extend the regular expression to capture the letter before the = as well as the value that follows, like so:

                  QRegularExpression re("([x,y]) = ([0-9]{2,3})");
                  

                  See the example code below and this video of the output.

                  mainwindow.h

                  #ifndef MAINWINDOW_H
                  #define MAINWINDOW_H
                  
                  #include <QMainWindow>
                  
                  class QSerialPort;
                  class QGraphicsScene;
                  class QGraphicsView;
                  class QGraphicsEllipseItem;
                  
                  class MainWindow : public QMainWindow
                  {
                      Q_OBJECT
                  
                  public:
                      MainWindow(QWidget *parent = 0);
                      ~MainWindow();
                  
                  public slots:
                      void updateP();
                  
                  private:
                      QGraphicsScene *scene;
                      QGraphicsView *view;
                      QGraphicsEllipseItem *ellipse;
                      QSerialPort *arduino;
                      bool open;
                      int x,y;
                  };
                  
                  #endif // MAINWINDOW_H
                  

                  mainwindow.cpp

                  #include <QRegularExpression>
                  #include <QTextStream>
                  #include <QDebug>
                  #include <QtSerialPort>
                  #include <QGraphicsScene>
                  #include <QGraphicsView>
                  #include <QGraphicsEllipseItem>
                  
                  #include "mainwindow.h"
                  
                  MainWindow::MainWindow(QWidget *parent)
                      : QMainWindow(parent), open(false), x(0), y(0)
                  {
                      this->resize(1024,768);
                  
                      scene=new QGraphicsScene(this);
                      scene->setSceneRect(0,0,1024,768);
                      view=new QGraphicsView(scene, this);
                      setCentralWidget(view);
                  
                      arduino=new QSerialPort("/dev/ttys003");
                      arduino->setBaudRate(QSerialPort::Baud9600);
                      connect(arduino, SIGNAL(readyRead()), this, SLOT(updateP()));
                      if(!arduino->open(QSerialPort::ReadOnly)){
                          qDebug() << "Failed to open serial port!";
                          return;
                      }
                      open=true;
                  
                      QBrush redBrush(Qt::red);
                      QPen blackPen(Qt::black, 1.);
                      ellipse=scene->addEllipse(0, 0, 20, 20, blackPen, redBrush);
                  }
                  
                  MainWindow::~MainWindow(){}
                  
                  void MainWindow::updateP(){
                      if(!open) return;
                  
                      QTextStream stream(arduino);
                      QString line;
                      while(stream.readLineInto(&line)){
                          QRegularExpression re("([x,y]) = ([0-9]{2,3})");
                          QRegularExpressionMatchIterator i=re.globalMatch(line);
                          while(i.hasNext()){
                              QRegularExpressionMatch match=i.next();
                              if(!match.hasMatch()){
                                  qDebug() << "No match!";
                                  continue;
                              }
                              QString xory=match.captured(1);
                              QString matched=match.captured(2);
                  
                              bool ok=false;
                              if(xory=="x") x=matched.toInt(&ok);
                              else if(xory=="y") y=matched.toInt(&ok);
                              else continue;
                              if(!ok){
                                  qDebug() << "Could not convert \"" << matched <<"\" to an integer!";
                                  continue;
                              }
                              ellipse->setPos(x,y);
                          }
                      }
                  }
                  

                  For the avoidance of doubt:

                  1. All my code samples (C++ or Python) are tested before posting
                  2. As of 23/03/20, my Python code is formatted to PEP-8 standards using black from the PSF (https://github.com/psf/black)
                  Macive XiongM 1 Reply Last reply
                  2
                  • jazzycamelJ jazzycamel

                    @Macive-Xiong

                    Very doable, you just need to extend the regular expression to capture the letter before the = as well as the value that follows, like so:

                    QRegularExpression re("([x,y]) = ([0-9]{2,3})");
                    

                    See the example code below and this video of the output.

                    mainwindow.h

                    #ifndef MAINWINDOW_H
                    #define MAINWINDOW_H
                    
                    #include <QMainWindow>
                    
                    class QSerialPort;
                    class QGraphicsScene;
                    class QGraphicsView;
                    class QGraphicsEllipseItem;
                    
                    class MainWindow : public QMainWindow
                    {
                        Q_OBJECT
                    
                    public:
                        MainWindow(QWidget *parent = 0);
                        ~MainWindow();
                    
                    public slots:
                        void updateP();
                    
                    private:
                        QGraphicsScene *scene;
                        QGraphicsView *view;
                        QGraphicsEllipseItem *ellipse;
                        QSerialPort *arduino;
                        bool open;
                        int x,y;
                    };
                    
                    #endif // MAINWINDOW_H
                    

                    mainwindow.cpp

                    #include <QRegularExpression>
                    #include <QTextStream>
                    #include <QDebug>
                    #include <QtSerialPort>
                    #include <QGraphicsScene>
                    #include <QGraphicsView>
                    #include <QGraphicsEllipseItem>
                    
                    #include "mainwindow.h"
                    
                    MainWindow::MainWindow(QWidget *parent)
                        : QMainWindow(parent), open(false), x(0), y(0)
                    {
                        this->resize(1024,768);
                    
                        scene=new QGraphicsScene(this);
                        scene->setSceneRect(0,0,1024,768);
                        view=new QGraphicsView(scene, this);
                        setCentralWidget(view);
                    
                        arduino=new QSerialPort("/dev/ttys003");
                        arduino->setBaudRate(QSerialPort::Baud9600);
                        connect(arduino, SIGNAL(readyRead()), this, SLOT(updateP()));
                        if(!arduino->open(QSerialPort::ReadOnly)){
                            qDebug() << "Failed to open serial port!";
                            return;
                        }
                        open=true;
                    
                        QBrush redBrush(Qt::red);
                        QPen blackPen(Qt::black, 1.);
                        ellipse=scene->addEllipse(0, 0, 20, 20, blackPen, redBrush);
                    }
                    
                    MainWindow::~MainWindow(){}
                    
                    void MainWindow::updateP(){
                        if(!open) return;
                    
                        QTextStream stream(arduino);
                        QString line;
                        while(stream.readLineInto(&line)){
                            QRegularExpression re("([x,y]) = ([0-9]{2,3})");
                            QRegularExpressionMatchIterator i=re.globalMatch(line);
                            while(i.hasNext()){
                                QRegularExpressionMatch match=i.next();
                                if(!match.hasMatch()){
                                    qDebug() << "No match!";
                                    continue;
                                }
                                QString xory=match.captured(1);
                                QString matched=match.captured(2);
                    
                                bool ok=false;
                                if(xory=="x") x=matched.toInt(&ok);
                                else if(xory=="y") y=matched.toInt(&ok);
                                else continue;
                                if(!ok){
                                    qDebug() << "Could not convert \"" << matched <<"\" to an integer!";
                                    continue;
                                }
                                ellipse->setPos(x,y);
                            }
                        }
                    }
                    
                    Macive XiongM Offline
                    Macive XiongM Offline
                    Macive Xiong
                    wrote on last edited by Macive Xiong
                    #16

                    Hi @jazzycamel ,

                    Thanks for your answer, these are all really helpful.
                    I have tried the code your provide on the potentialmeter signal received, it doesn't work, you have any suggestion??

                    My code:
                    mainwindow.h

                    #ifndef MAINWINDOW_H
                    #define MAINWINDOW_H
                    
                    #include <QMainWindow>
                    #include <QGraphicsEllipseItem>
                    
                    class QSerialPort;
                    class QGraphicsScene;
                    class QGraphicsView;
                    
                    
                    class MainWindow : public QMainWindow
                    {
                        Q_OBJECT
                    
                    public:
                        MainWindow(QWidget *parent = 0);
                        ~MainWindow();
                    
                    public slots:
                        void updateP();
                        void readSerial();
                    
                    private:
                        QGraphicsScene *scene;
                        QGraphicsView *view;
                        QSerialPort *arduino;
                        QGraphicsEllipseItem *ellipse;
                        bool open;
                    };
                    
                    #endif // MAINWINDOW_H
                    
                    

                    mainwindow.cpp

                    #include <QRegularExpression>
                    #include <QTextStream>
                    #include <QDebug>
                    #include <QtSerialPort>
                    #include <QGraphicsScene>
                    #include <QGraphicsView>
                    #include <QGraphicsEllipseItem>
                    
                    #include "mainwindow.h"
                    
                    MainWindow::MainWindow(QWidget *parent)
                        : QMainWindow(parent), open(false)
                    {
                        this->resize(1024,768);
                    
                        scene=new QGraphicsScene(this);
                        scene->setSceneRect(0,0,1024,768);
                        view=new QGraphicsView(scene, this);
                        setCentralWidget(view);
                    
                        arduino=new QSerialPort("COM5");
                        arduino->setBaudRate(QSerialPort::Baud115200);
                        connect(arduino, SIGNAL(readyRead()), this, SLOT(updateP()));
                        if(!arduino->open(QSerialPort::ReadWrite)){
                            qDebug() << "Failed to open serial port!";
                            return;
                        }
                        open=true;
                    
                    }
                    
                    MainWindow::~MainWindow(){}
                    
                    void MainWindow::updateP(){
                        if(!open) return;
                    
                        QTextStream stream(arduino);
                        QString line;
                        while(stream.readLineInto(&line)){
                            QRegularExpression re("x = ([0-9]{2,3})");
                            QRegularExpressionMatch match=re.match(line);
                            if(!match.hasMatch()) continue;
                            QString matched=match.captured(1);
                            bool ok;
                            float x=matched.toFloat(&ok);
                            if(!ok) continue;
                    
                            QBrush redBrush(Qt::red);
                            QPen blackPen(Qt::black, 1.);
                            scene->addEllipse(x, 300, 20, 20, blackPen, redBrush);
                    }
                    }
                    void MainWindow::readSerial()
                    {
                        this->updateP();
                    }
                    

                    But this code is perfectly working on for loop"x from 0 to 512".

                    My Arduino code for potentialmeter signal:

                    void setup() {:
                      Serial.begin(115200);
                    }
                    void loop() {
                      float x = analogRead (A0);
                      Serial.println(x);
                      delay(5);      
                    }
                    

                    And here is an extra question, how can I write the code only for receiving the value I want to? For example, I have different variable in Arduino x1, x2, y1, y2. But I only want to get the signal of x1 and y1, how can I modify the code?

                    Thank you so much:)

                    1 Reply Last reply
                    0
                    • jazzycamelJ Offline
                      jazzycamelJ Offline
                      jazzycamel
                      wrote on last edited by
                      #17

                      @Macive-Xiong

                      You've changed your Arduino code. You used to print x = 96 for example, but now you are only printing 96. The regular expression expects the first format. Also, the regular expression works for values 10 - 999, the range of analogRead() is 0-1023. If you want to use the current (value only) format for the full range of analogRead() then I suggest you change the regular expressions as follows:

                      QRegularExpression re("([0-9]{1,4})");
                      

                      And then, after converting the matched string to an integer, check if its in the desired range:

                      bool ok=false;
                      int x=matched.toInt(&ok);
                      if(!ok){
                          qDebug() << "Could not convert \"" << matched <<"\" to an integer!";
                          continue;
                      }
                      if(x<0 || x>1023){
                          qDebug() << "Value of x (" << x << ") out of range!";
                          continue;
                      }
                      

                      For the avoidance of doubt:

                      1. All my code samples (C++ or Python) are tested before posting
                      2. As of 23/03/20, my Python code is formatted to PEP-8 standards using black from the PSF (https://github.com/psf/black)
                      Macive XiongM 1 Reply Last reply
                      0
                      • jazzycamelJ jazzycamel

                        @Macive-Xiong

                        You've changed your Arduino code. You used to print x = 96 for example, but now you are only printing 96. The regular expression expects the first format. Also, the regular expression works for values 10 - 999, the range of analogRead() is 0-1023. If you want to use the current (value only) format for the full range of analogRead() then I suggest you change the regular expressions as follows:

                        QRegularExpression re("([0-9]{1,4})");
                        

                        And then, after converting the matched string to an integer, check if its in the desired range:

                        bool ok=false;
                        int x=matched.toInt(&ok);
                        if(!ok){
                            qDebug() << "Could not convert \"" << matched <<"\" to an integer!";
                            continue;
                        }
                        if(x<0 || x>1023){
                            qDebug() << "Value of x (" << x << ") out of range!";
                            continue;
                        }
                        
                        Macive XiongM Offline
                        Macive XiongM Offline
                        Macive Xiong
                        wrote on last edited by Macive Xiong
                        #18

                        @jazzycamel

                        Thank you so much for your help, it totally works!
                        Here are few question:

                        1.What if I would like to send the decimal numbers to Qt and do some calculation, what should I modify the codes?
                        Say, I would like to send x & y from 1.34 to 4.96 to Qt. I change the code like:

                        void MainWindow::updateP(){
                            if(!open) return;
                        
                            QTextStream stream(arduino);
                            QString line;
                            while(stream.readLineInto(&line)){
                                QRegularExpression re("([x,y]) = ([0-9]{-1,4})");
                                QRegularExpressionMatchIterator i=re.globalMatch(line);
                                while(i.hasNext()){
                                    QRegularExpressionMatch match=i.next();
                                    if(!match.hasMatch()){
                                        qDebug() << "No match!";
                                        continue;
                                    }
                                    QString xory=match.captured(1);
                                    QString matched=match.captured(2);
                        
                                    bool ok=false;
                                    if(xory=="x") x=matched.toFloat(&ok);
                                    else if(xory=="y") y=matched.toFloat(&ok);
                                    else continue;
                                    if(!ok){
                                        qDebug() << "Could not convert \"" << matched <<"\" to an integer!";
                                        continue;
                                    }
                                    QBrush redBrush(Qt::red);
                                    QPen blackPen(Qt::black, 1.);
                                    scene->addEllipse(x*102, y*102, 10, 10, blackPen, redBrush);
                                }
                            }
                        }
                        
                        
                        
                        1. my graphicsView still set weird ellipse on a unset position:
                          Like this
                          The ellipses on the left side, I didn't set the position on that but there are still some ellipses, I already set my BaudRate to 115200 and it's the best I could get so far...

                        And this

                        The ellipses on the top side of the graphics view is not set, I don't know why there are so many signals to set the ellipses. Please give me some suggestion here.

                        1. If I want to close Arduino reading by click a button, what kind of command should I add in my button_clicked?
                        void MainWindow::on_Reset_btn_clicked()
                        {
                        
                        }
                        

                        Any suggestion?
                        Thank you so much!!:)

                        1 Reply Last reply
                        0

                        • Login

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