IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Discussion :

[QSerialPort] Lecture asynchrone de données

  1. #1
    Membre à l'essai
    Homme Profil pro
    Inscrit en
    Mars 2013
    Messages
    11
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Mars 2013
    Messages : 11
    Points : 10
    Points
    10
    Par défaut [QSerialPort] Lecture asynchrone de données
    Salut,

    Je suis parti de l'exemple Command Line Reader Async Example pour lire de façon asynchrone des données port série (un Arduino dans mon cas).
    L'exemple fonctionne mais j'ai tenté d'encapsuler les fonctions de lecture dans une classe et ça coince.

    J'ai créé une classe SerialPortReader qui se contente de lire de manière asynchrone les messages qui lui arrivent et de les afficher via qDebug (dans un premier temps).
    Mon problème est que le signal readyRead() n'est jamais émis:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    connect(m_serialPort, SIGNAL(readyRead()), SLOT(readData()));
    Je ne comprends pas pourquoi le signal est émis quand je le connecte depuis la classe MainWindow et pourquoi il n'est pas émis depuis la classe SerialPortReader.

    mainwindow.cpp
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    #include "mainwindow.h"
    #include "ui_mainwindow.h"
     
    #include "arduino/serialportreader.h"
    #include <QDebug>
     
    MainWindow::MainWindow(QWidget *parent) :
        QMainWindow(parent),
        ui(new Ui::MainWindow),
        serialPort (new QSerialPort)
    {
        ui->setupUi(this);
        serialPort->setPortName("ttyUSB0");
        serialPort->setBaudRate(115200);
     
        if (!serialPort->open(QIODevice::ReadOnly)) {
            qDebug() << "MainWindow: Failed to open port " << serialPort->portName() << "error: " << serialPort->errorString();
            while (1) {};
        }
     
        // Option 1: directly connect serialPort readyRead() to MainWindow::readData()
        // Works fine
        connect(serialPort, SIGNAL(readyRead()), SLOT(readData()));
     
        // Option 2: use a SerialPortReader that internally connects readyRead to SerialPortReader::readData()
        // readyRead() is never triggered (and thus readData() never executed)
        //SerialPortReader reader (serialPort); // FIXME: Retrieve messages from the serial port
    }
     
    MainWindow::~MainWindow()
    {
        delete ui;
        serialPort->close();
    }
     
    void
    MainWindow::readData()
    {
        if (serialPort->canReadLine())
            m_readData.append(serialPort->readAll());
        else
        {
            if (!m_readData.isEmpty())
            {
                ui->label->setText(m_readData);
                qDebug () << m_readData;
                m_readData.clear();
            }
        }
    }
    serialportreader.cpp
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    #include "serialportreader.h"
    #include <QDebug>
     
    QT_USE_NAMESPACE
     
    SerialPortReader::SerialPortReader(QSerialPort *serialPort, QObject *parent):
        QObject(parent),
        m_serialPort(serialPort)
    {
        connect(m_serialPort, SIGNAL(readyRead()), SLOT(readData()));
        connect(m_serialPort, SIGNAL(error(QSerialPort::SerialPortError)), SLOT(handleError(QSerialPort::SerialPortError)));
    }
     
    SerialPortReader::~SerialPortReader()
    {
    }
     
    void SerialPortReader::readData()
    {
        qDebug () << "readData";
        if (m_serialPort->canReadLine())
            m_readData.append(m_serialPort->readAll());
        else
        {
            if (!m_readData.isEmpty())
            {
                qDebug () << m_readData;
                m_readData.clear();
            }
        }
    }
     
    void SerialPortReader::handleError(QSerialPort::SerialPortError serialPortError)
    {
        if (serialPortError == QSerialPort::ReadError)
        {
            qDebug () << "An I/O error occurred while reading the data from port" << m_serialPort->portName() << ", error:" << m_serialPort->errorString();
        }
    }
    Pourquoi le signal readyRead() n'est jamais émis dans la classe SerialPortReader ? (note: j'ai testé qu'il y avait bien des données à lire sur le port série!)
    Voilà le projet complet: serial_reader_async_test.zip

  2. #2
    Membre habitué
    Homme Profil pro
    Inscrit en
    Juillet 2010
    Messages
    107
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Juillet 2010
    Messages : 107
    Points : 189
    Points
    189
    Par défaut
    Salut,
    Problème de porté de variable :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    SerialPortReader reader (serialPort);
    reader est local à ton constructeur et donc il sera détruit à la fin du constructeur !

  3. #3
    Membre à l'essai
    Homme Profil pro
    Inscrit en
    Mars 2013
    Messages
    11
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France

    Informations forums :
    Inscription : Mars 2013
    Messages : 11
    Points : 10
    Points
    10
    Par défaut
    Ça m'est passé sous le nez j'ai bien fait de demander
    J'ai donc ajouté un pointeur vers un SerialPortReader dans les membres privées de ma classe MainWindow et on remplace ensuite

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    SerialPortReader reader (serialPort);
    par
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    reader = new SerialPortReader (serialPort);
    Voilà une version du code corrigée et complétée pour faire ce que je veux:
    serial_reader_async_fixed.zip

    Merci et à bientôt

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. Recordset, lecture d'une donnée NULL
    Par jdelges dans le forum VB 6 et antérieur
    Réponses: 2
    Dernier message: 10/10/2007, 11h42
  2. Lecture Asynchrone STDOUT & STDERR
    Par ecatum dans le forum Langage
    Réponses: 3
    Dernier message: 04/04/2007, 17h50
  3. [WIN32][TComport] Lecture Asynchrone
    Par Linkin dans le forum Delphi
    Réponses: 5
    Dernier message: 30/03/2007, 10h49
  4. lecture base de donnée avec vc++ 2005
    Par k_boy dans le forum MFC
    Réponses: 13
    Dernier message: 21/04/2006, 11h48

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo