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
Forum Updated to NodeBB v4.3 + New Features

Signal receiving problem from Arduino to Qt graphics view

Scheduled Pinned Locked Moved Unsolved General and Desktop
18 Posts 4 Posters 4.7k 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