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.5k 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.
  • jazzycamelJ Offline
    jazzycamelJ Offline
    jazzycamel
    wrote on last edited by
    #3

    @Macive-Xiong

    As I said in my reply to you other post and @SGaist has said in the previous reply, you need to process the output from the Arduino/Serial Port. toInt() won't pick numbers out of the string and ignore the rest, you have to parse out the numbers and then convert it. Your updateP() method might look something like the following:

    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;
    
            // Your drawing code here...
        }
    }
    

    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)
    VRoninV 1 Reply Last reply
    0
    • VRoninV Offline
      VRoninV Offline
      VRonin
      wrote on last edited by
      #4

      Also, your code is affected by a problem shared by many others: readAll() see https://forum.qt.io/topic/70620/wierd-behavior-with-qserialport-readline/3

      "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
      1
      • jazzycamelJ jazzycamel

        @Macive-Xiong

        As I said in my reply to you other post and @SGaist has said in the previous reply, you need to process the output from the Arduino/Serial Port. toInt() won't pick numbers out of the string and ignore the rest, you have to parse out the numbers and then convert it. Your updateP() method might look something like the following:

        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;
        
                // Your drawing code here...
            }
        }
        
        VRoninV Offline
        VRoninV Offline
        VRonin
        wrote on last edited by
        #5

        @jazzycamel I would have used a regular expression to parse the output to be honest...

        "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
        0
        • jazzycamelJ Offline
          jazzycamelJ Offline
          jazzycamel
          wrote on last edited by jazzycamel
          #6

          @VRonin

          I agree a regular expression would be better, I was just trying to make it simpler by using a step-by-step approach to parsing :)

          The regular expression version might look like the following:

          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;
          
                  // Your drawing code here...
              }
          }
          

          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
          1
          • jazzycamelJ jazzycamel

            @VRonin

            I agree a regular expression would be better, I was just trying to make it simpler by using a step-by-step approach to parsing :)

            The regular expression version might look like the following:

            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;
            
                    // Your drawing code here...
                }
            }
            
            Macive XiongM Offline
            Macive XiongM Offline
            Macive Xiong
            wrote on last edited by Macive Xiong
            #7

            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 1 Reply Last reply
            0
            • 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