Problème en lecture/écriture de badge RFID mifare classic avec Raspberry et CR038
-
@jym92 Ohlala, je vois très bien le soucis... Dans Qt, il y a plusieurs règles "de base" à respecter pour éviter les ennuis, et l'une d'elle c'est de ne jamais utiliser QThread comme classe de base, mais de créer une "worker class" que l'on va faire travailler dans un thread dédié.
Il y a plusieurs bonnes raisons à cela, et ce serait trop long a expliquer comme ça, je vous conseille d'aller lire les article suivants:
- http://blog.debao.me/2013/08/how-to-use-qthread-in-the-right-way-part-1/
- https://www.toptal.com/qt/qt-multithreading-c-plus-plus
- https://hub.packtpub.com/multithreading-qt/
Pour résumer, je dirais:
a. créer une classe RfidReader qui va faire la gestion du port série / lecture du RFID
b. créer une instance de cette classe
c. créer une instance de QThread et "déplacé" l'instance de la worker class vers ce thread
d. utiliser des connection signals/slots pour transférer les données du thread de travail vers le thread principal, comme ça c'est Qt qui s'occupe de faire les copies et vous éviter de devoir gérer les accès multi-thread.Autres règles de base pour Qt
- ne jamais bloquer le thread principal, sinon votre IHM devient inutilisable!!
- toutes les actions IHM/graphique doivent être exécutées dans le thread principale
-
Bonjour @KroMignon ,
j'ai crée la classe RFIDreader(cpp + h) dans la laquelle j'ai rangé toutes mes fonctions de base RFID telles que LedOn, LedOff, read, write....
et j'ai fait du coup du ménage dans mon thread RFID ;)
par contre j'ai une question, j'ai commencé à mettre en place ce qui est indiqué dans ce tuto : https://hub.packtpub.com/multithreading-qt/
cependant j'ai plusieures questions :
1- dans mon Thread RFID j'aurai ma déclaration de port série, les routines d’exécution RFID qui y seront appelées ainsi que ceci :
class Thread : public QThread { Q_OBJECT protected: void run() { Object* myObject = new Object(); connect(myObject, &Object::started, this, &Thread::doWork); exec(); } private slots: void doWork(); };
C'est bien ça ? (bien-sur j'adapterai les noms...)
2- Pour ce qui est de la classe worker , je suis censé le mettre où ?
(fichier indépendant RfidWorker(cpp+h) ou dans RFIDThread )class Worker : public QObject { Q_OBJECT public slots: void doWork() { emit result("workers are the best"); } signals: void result(QString data); };
D'ailleurs cette classe worker ne sert qu'a faire le lien ou bien c'est la que je dois implémenté le déroulement de mon thread ?
3- ça sert à quoi ça ?
connect(thread, &QThread::finished, worker, &QObject::deleteLater); connect(this, &MainWindow::startWork, worker, &Worker::doWork); connect(worker, &Worker::resultReady, this, handleResult);
Sachant que dans mon cas, mon Thread a seulement pour role d'indiquer si un badge et son montant ... donc je pensais passer ces 2 infos au Thread principal (mainwindow) via 2 variables globales (un bool et un int)...
merci d'avance si tu peux à toutes mes interrogations ;)
-
@jym92 Bonjour, hmm je ne sais pas si j'ai bien compris la structure que vous avez décidé d'implémenter...
Je vais broder autour de ce que j'ai cru comprendre... désolé si je suis à côté de la plaquePour moi, il suffit de créer une seule classe qui va faire la gestion du port série, la fameuse "RfidWorker".
Cette classe va avoir un signal "newTag" et des slots "start" et "stop", quelque chose comme ça:class RfIdWorker : public QObject { Q_OBJECT public: explicit RfIdWorker (QObject * parent); ... public slots: void start(); void stop(); signals: void newTag(QString tagID, int tagValue); };
Après pour démarrer l'utilisation du Rfid:
auto * rfWorker = new RfIdWorker(); auto* rfThread = new QThread(); // start RF ID Reader on thread start connect(rfThread, &QThread::started, rfWorker , &RfIdWorker::start); // stop RF ID Reader on main application exit connect(qApp, &QApplication::aboutToQuit, rfWorker, &QObject::deleteLater); // delete thread on worker end connect(rfWorker, &QObject::destroyed, rfThread, [rfThread](QObject *) { if(rfThread.isRunning()) { rfThread.quit(); rfThread.wait(); } rfThread.deleteLater(); } , Qt::DirectConnection); // needs "DirectConnection" to work // to be informed about new RF ID tag connect(rfWorker, &RfIdWorker::newTag, this, &MyMainClass::newRfIdTag); // move worker object to worker thread rfWorker.moveToThread(rfThread); // last but not least, start worker thread rfThread.start();
Dans le slot start, le port série est initialisé et démarré.
Dans le slot stop; le port série est fermé.En gros, voici comment je ferai.
-
Ok je vois c'est déja un peu plus clair pour moi ...
Donc j'aurai juste une classe "RFIDworker" et un thread "RFIDThread", et mes fonctions de base pour le RFID seront contenu et appelée dans la classe "RFIDworker".
J'ai bien saisi pour l'initialisation de port série ainsi que pour l'init du thread et du Qobject qui se feront dans mainwindow.
Cependant j'aurai besoin de mettre en place une boucle infini ou un timer me permettant de scanner en boucle si il y a un new tag...
Je dois mettre ça en place dans la classe RFIDworker en créant un slot "onWork" qui contiendra une boucle infini qui scannera puis déclenchera le signal Newtag ?
ou je ma boucle déclenchant newtag devrait etre dans le fichier RFIDThread ?désolé pour mes questions mais je suis un peu neuf avec genre de fonctionnement à cheval entre l'embarqué et la création d'application ....
Un grand merci pour ton aide !
-
@jym92 Pour moi, il suffit de créer une classe qui sait décoder les trames de ton (c'est au moins mon 3ème message... je passe au tutoiement ;-) ) récepteur RFID.
Je continue sur l'exemple d'avant:
class RfIdWorker : public QObject { Q_OBJECT public: explicit RfIdWorker (QObject * parent); ... public slots: void start(); void stop(); private slots: void checkRFID(); signals: void newTag(QString tagID, int tagValue); private: QSerialPort *m_serial; };
Et du côté C++
RfIdWorker:RfIdWorker (QObject *parent): QObject(parent), m_serial(Q_NULLPTR) { } void RfIdWorker::start() { if(!m_serial) { m_serial = new QSerialPort(this); // serial port initialistion ... connect(m_serial, &QSerialPort::readyRead, this, &RfIdWorker::checkRFID); } m_serial.open(); } void RfIdWorker::stop() { if(m_serial && m_serial.isOpen()) { m_serial.close(); } } void RfIdWorker::checkRFID() { while(!m_serial->atEnd()) { QByteArray rfIdRaw = m_serial->readAll(); // process data ... if(!tag.isEmpty()) emit newTag(tag, value); } }
Ce n'est qu'un squelette, mais ça donne une idée de l'architecture
-
Alors il me semble avoir bien suivi tes consignes, le Thread se lance puis le worker et tout semble bien tourner au vu du debug ...
Cependant comme auparavant il semblerait que lorsque j'essaye d'envoyer des commandes par le port série rien ne se passe(une led sur mon ftdi devrait indiquer l'émission de données).Je ne comprends pas pourquoi mon worker ne pourrait pas interagir avec mon port série "ttyusb0"...
voici ce que j'ai fait :
RFIDThread.cpp:
/********************************************************************* RFID THRED In I2C mode ********************************************************************/ #include <QtGui> #include "RFIDthread.h" #include "global.h" #include <QDebug> #include <mainwindow.h> #include "RFIDworker.h" //static unsigned char NUID[4]; //Array for storing NUID of a MiFare card //déja déclaré en global.... à verif ! static char mode = 0; //Variable storing current mode of the program static bool Rfid_wrtitting = false; // pour appel clase // RFIDthread::RFIDthread(QObject *parent) : QThread(parent) { } /******************************************************************************************************* * ************* ---- Main de RFIDthread ---- ************ * *******************************************************************************************************/ void RFIDthread::run() { qDebug() << " Thread RFID lancé !"; } /************************************************************************************************************************ ******************** ---- FIN du Main de RFIDthread ---- *********************** **************************************************************************************************************************/
Pour ce qui est RFIDworker :
static QSerialPort *serialRFID; //RFIDworker :: RFIDworker (QObject *parent): QObject(parent), serialRFID(Q_NULLPTR) RFIDworker::RFIDworker(QObject *parent): QObject(parent) { } void RFIDworker::start() { if(!serialRFID) { serialRFID = new QSerialPort(this); // serial port initialistion // ----- INIT SERIAL RFID ----// serialRFID->setPortName("ttyUSB0"); serialRFID->setBaudRate(QSerialPort::Baud19200); serialRFID->setDataBits(QSerialPort::Data8); serialRFID->setParity(QSerialPort::NoParity); serialRFID->setStopBits(QSerialPort::OneStop); serialRFID->setFlowControl(QSerialPort::NoFlowControl); serialRFID->open(QIODevice::ReadWrite); connect(serialRFID, &QSerialPort::readyRead, this, &RFIDworker::checkRFID); if (serialRFID->isOpen() == true) { qDebug() << "Serial ttyUSB0(USB0) is opened"; } else { qDebug() << "Connexion impossible RFID ! "; } // lancement de la routine recherche badge checkRFID(); } } void RFIDworker::stop() { if(serialRFID && serialRFID->isOpen()) { serialRFID->close(); } } void RFIDworker::checkRFID() { while(1) { led_on(); delay(400); led_off(); delay(400); } }
et enfin voila comment je démarre le tout dans mainwindow :
// ------------ Lancement du Thread RFID et du worker lié -----------------// auto* rfWorker = new RFIDworker(); auto* rfThread = new RFIDthread(); // start RF ID Reader on thread start connect(rfThread, &QThread::started, rfWorker , &RFIDworker::start); // stop RF ID Reader on main application exit connect(qApp, &QApplication::aboutToQuit, rfWorker, &QObject::deleteLater); // delete thread on worker end connect(rfWorker, &QObject::destroyed, rfThread, [rfThread](QObject *) { if(rfThread->isRunning()) { rfThread->quit(); rfThread->wait(); } rfThread->deleteLater(); } , Qt::DirectConnection); // needs "DirectConnection" to work // to be informed about new RF ID tag //connect(rfWorker, &RFIDworker::newTag, this, &MyMainClass::newRfIdTag); // move worker object to worker thread rfWorker->moveToThread(rfThread); // last but not least, start worker thread rfThread->start();
remarque : ce morceau de code est situé dans le init de mainwindow.cpp.
Enfin j'ai également noté que le fait de déclarer un second port série dans un Thread différent semble brouiller mon premier port série lorsque celui-ci essaye d’émettre des données, il croit voir une réponse (il s'agit du port série réserver au PIC et les fils sont en l'air ...).
Une idée pour que je puisse interagir avec le port série depuis mon worker ?
Une idée d'ou peut venir le conflit entre les 2 ports séries ?
merci d'avance ;)
-
La variable static QSerialPort est une mauvaise idée. Il n'y a aucune raison qu'elle soit déclarée static. Elle devrait être un membre du worker object.
-
merci de ta réponse @SGaist , je viens de le paramètre extern dans mon fichier global avec :
//global.h extern QSerialPort* serialRFID; extern QSerialPort* serial; //global.cpp QSerialPort* serial; QSerialPort* serialRFID;
Mais cela ne change rien, j'ai pas de réaction sur le port série ....
Comment je peux ajouter mon port série à Qserialport serialRFID à mon worker object ?
-
@jym92 Comme l'a déjà souligné @SGaist, l'utilisation de la variables statiques est en générale une très mauvaise idée en C++. A moins de vouloir partager une variable entre plusieurs instances de cette classe, mais c'est un cas d'usage très particulier.
Encore une fois, il n'est pas utile de créer une classe dérivée de QThread!. De plus, je fait de faire une propre implémentation du slot run() fait en sorte de ne pas créer, ni démarrer une EventQueue pour ce thread, donc le mécanisme de signals/slots de Qt ne fonctionnera pas avec ce thread!
Après, à quoi sert
RFIDworker::checkRFID()
? A part bloquer le thread dans une boucle infinie ;-)
Bref là également une très mauvaise idée, je veut dire par là, pas 'Qt Conforme'.
Pour que le mécanisme signals/slots fonctionne, il faut une EventQueue et ne faut pas bloquer le thread dans une boucle infinie!Je reprends mon exemple de WorkerClass
class RfIdWorker : public QObject { Q_OBJECT public: explicit RfIdWorker (QObject * parent); ... public slots: void start(); void stop(); private slots: void checkRFID(); void ledTimer(); signals: void newTag(QString tagID, int tagValue); private: QSerialPort *m_serial; QTimer *m_timer; bool m_ledState; };
Pour le C++:
RfIdWorker:RfIdWorker (QObject *parent) : QObject(parent) , m_serial(Q_NULLPTR) , m_timer(Q_NULLPTR) , m_ledState(false) { } void RfIdWorker::start() { if(!m_ledTimer) { m_ledTimer = new QTimer(this); m_ledTimer->setSingleShot(false); m_ledTiler->setInterval(400); connect(m_ledTimer, &QTimer::timeout, this, &RfIdWorker::ledTimer); } if(!m_serial) { m_serial = new QSerialPort(this); // serial port initialistion ... connect(m_serial, &QSerialPort::readyRead, this, &RfIdWorker::checkRFID); } m_serial>open(); m_ledTimer->start(); } void RfIdWorker::stop() { if(m_serial && m_serial->isOpen()) { m_serial->close(); } if(m_ledTimer && m_ledTimer->isActive()) m_ledTimer->stop(); } void RfIdWorker::ledTimer() { if(m_ledState) led_on(); else led_off(); m_ledState = !m_ledState; } void RfIdWorker::checkRFID() { while(!m_serial->atEnd()) { QByteArray rfIdRaw = m_serial->readAll(); // process data ... if(!tag.isEmpty()) emit newTag(tag, value); } }
-
Bonjour,
Tout d'abord je vous remercie pour vos conseils et je commence à petit à petit à saisir la logique un peu tordu de Qt ;p
J'ai du coup modifier mon worker pour passer le port serie en private à la classe et j'ai mis en place le fonctionnement via le timer au lieu de la boucle infini.
Cependant le timer ne démarre pas alors qu'au vu des lignes de debug tout semble bien se lancer sauf le timer ...
voici le code du worker.h :
#ifndef RFIDworker_H #define RFIDworker_H #include <QObject> #include <QtSerialPort> class RFIDworker : public QObject { Q_OBJECT public: explicit RFIDworker(QObject *parent= nullptr); public slots: void start(); void stop(); private slots: void checkRFID(); void ledTimer(); signals: void newTag(QString tagID, int tagValue); private: QSerialPort *RFIDserial; QTimer *m_timer; bool m_ledState; }; //====================================================================== //************ RFID CR038 fonctions : ****** // //====================================================================== //*******************************************// //Turn on MiFare module LED subroutine void led_on(QSerialPort *RFIDport); //*******************************************// //Turn on MiFare module LED subroutine void led_off(QSerialPort *RFIDport);
et du worker.cpp :
RFIDworker::RFIDworker(QObject *parent): QObject(parent) , RFIDserial(Q_NULLPTR) , m_timer(Q_NULLPTR) , m_ledState(false) { } void RFIDworker::start() { if(!m_timer) { m_timer = new QTimer(this); m_timer->setSingleShot(false); m_timer->setInterval(400); connect(m_timer, &QTimer::timeout, this, &RFIDworker::ledTimer); } if(!RFIDserial) { RFIDserial = new QSerialPort(this); // serial port initialistion // ----- INIT SERIAL RFID ----// RFIDserial->setPortName("ttyUSB0"); RFIDserial->setBaudRate(QSerialPort::Baud19200); RFIDserial->setDataBits(QSerialPort::Data8); RFIDserial->setParity(QSerialPort::NoParity); RFIDserial->setStopBits(QSerialPort::OneStop); RFIDserial->setFlowControl(QSerialPort::NoFlowControl); RFIDserial->open(QIODevice::ReadWrite); connect(RFIDserial, &QSerialPort::readyRead, this, &RFIDworker::checkRFID); if (RFIDserial->isOpen() == true) { qDebug() << "Serial ttyUSB0(USB0) is opened"; } else { qDebug() << "Connexion impossible RFID ! "; } // lancement timer m_timer->start(); } } void RFIDworker::stop() { if(serialRFID && serialRFID->isOpen()) { serialRFID->close(); } if(m_timer && m_timer->isActive()) m_timer->stop(); } void RFIDworker::ledTimer() { if(m_ledState) led_on(RFIDserial); else led_off(RFIDserial); m_ledState = !m_ledState; qDebug() << "passage dans Ledtimer"; } void RFIDworker::checkRFID() { while(!RFIDserial->atEnd()) { qDebug() << "passage dans checkRFID"; //QByteArray rfIdRaw = RFIDserial->readAll(); // process data /* if(!tag.isEmpty()) emit newTag(tag, value); */ } } //====================================================================== //************ RFID CR038 fonctions : ****** // //====================================================================== //****************************************** //Turn on MiFare module LED subroutine void led_on(QSerialPort *RFIDport) { // on envoit tout d'un coup ! QByteArray da(LED_ON, sizeof(LED_ON)); RFIDport->write(da); //delay(200) QByteArray ba; while(!RFIDport->isOpen()); ba = RFIDport->readAll(); qDebug() << "reception LED_ON :" << ba; } //******************************************* //Turn on MiFare module LED subroutine void led_off(QSerialPort *RFIDport) { QByteArray da(LED_OFF, sizeof(LED_OFF)); RFIDport->write(da); QByteArray ba; //delay(200) while(!RFIDport->isOpen()); ba = RFIDport->readAll(); qDebug() << "reception LED_OFF :" << ba; }
Coté init dans le mainwindow j'ai rien changé ....
en réponse console j'ai :
Serial ttyUSB0(USB0) is opened Thread RFID lancé !
donc le worker a bien été lancé ainsi que le thread RFID.
Une idée ? J'ai oublié un truc ?
J'ai essayé d'échanger Tx et Rx coté connectique mais rien ne se passe...
et je devrais quand même avoir des lignes de debug coté worker qui indique le déroulement du ledtimer...J'essaye de coller au mieu à la "QT conforme" mais vu que mon projet est a cheval entre une IHM et de l'embarqué pur c'est pas simple...
Merci pour votre aide ;)
-
@jym92 said in Problème en lecture/écriture de badge RFID mifare classic avec Raspberry et CR038:
Coté init dans le mainwindow j'ai rien changé ....
Le problème est là à mon avis, est-ce ton thread est une instance de QThread?
Est-ce que tu as bien supprimé ta classe RFIDthread qui ne sert à rien?//auto* rfThread = new RFIDthread(); auto* rfThread = new QThread();
-
@jym92 said in Problème en lecture/écriture de badge RFID mifare classic avec Raspberry et CR038:
'essaye de coller au mieu à la "QT conforme" mais vu que mon projet est a cheval entre une IHM et de l'embarqué pur c'est pas simple...
Le mode de fonctionnement de Qt peut sembler à première vue un peu étrange, mais c'est en fait très performant. Donc, pour de l'embarquer pas un soucis, bien au contraire.
Je te conseille vivement de prendre le temps de lire et comprendre les articles suivants:- https://woboq.com/blog/how-qt-signals-slots-work.html
- https://woboq.com/blog/how-qt-signals-slots-work-part2-qt5.html
- https://woboq.com/blog/how-qt-signals-slots-work-part3-queuedconnection.html
Ceci va t'aider à mieux cerner la philosophie de Qt et le pourquoi comment du mécanisme signals/slots.
-
Effectivement tu avais raison, je n'avais pas supprimé mon fichier RFIDThread car je pensais qu'il été utile a lancement de la classe et l'appel au niveau du mainwindow était faux...
voila mon appel au niveau de mainwindow :
// ------------ Lancement du Thread RFID worker -----------------// auto* rfThread = new QThread(); auto* rfWorker = new RFIDworker(); // start RF ID Reader on thread start connect(rfThread, &QThread::started, rfWorker , &RFIDworker::start); // stop RF ID Reader on main application exit connect(qApp, &QApplication::aboutToQuit, rfWorker, &QObject::deleteLater); // delete thread on worker end connect(rfWorker, &QObject::destroyed, rfThread, [rfThread](QObject *) { if(rfThread->isRunning()) { rfThread->quit(); rfThread->wait(); } rfThread->deleteLater(); } , Qt::DirectConnection); // needs "DirectConnection" to work // to be informed about new RF ID tag //connect(rfWorker, &RFIDworker::newTag, this, &MyMainClass::newRfIdTag); // move worker object to worker thread rfWorker->moveToThread(rfThread); // last but not least, start worker thread rfThread->start();
Du coup dans mon Thread tout fonctionne comme je le veux, à savoir j'envois des commandes via le Timer et je reçois automatiquement mes réponses dans CheckRFID ;)
Cependant un autre problème apparaît que je suspectais déjà,à savoir l'envoi et la réception de données sur mon port série USB0 brouille ma réception de donnés sur le port UART5 qui est en l'air mais normalement relié à un PIC.
Voila comment je déclare la communication série avec le PIC dans mon mainwindow :
//----------------------- Parametrage de la liaison serie -------------------------------------- // QList<QSerialPortInfo> listPsi; // liste des ports série existant listPsi = QSerialPortInfo::availablePorts(); // récupère les ports série disponibles for(int i=0 ; i<listPsi.size() ; i++) qDebug() << "Communiquer : " << listPsi.at(i).portName() <<" " << listPsi.at(i).description(); serial = new QSerialPort(this); // se connecte au port série déja existant nommé "ttyAMA0" // remarque port serie (si uart0, uart4 et uart5 activé via config): // uart 0 = Ama0 pin8(tx) et 10(Rx) // USB0 // RFID PN532 // uart 5 = Ama2 pin32 et 33 // PIC // ----- INIT SERIAL PIC ----// serial->setPortName("ttyAMA2"); serial->setBaudRate(QSerialPort::Baud115200); serial->setDataBits(QSerialPort::Data8); serial->setParity(QSerialPort::NoParity); serial->setStopBits(QSerialPort::OneStop); serial->setFlowControl(QSerialPort::NoFlowControl); serial->open(QIODevice::ReadWrite); if (serial->isOpen() == true) { qDebug() << "Serial ttyAMA2(uart5) is opened"; connect(serial, SIGNAL(readyRead()),this,SLOT(on_Received_Data())); } else { qDebug() << "Connexion impossible PIC ! "; }
et la reception des données je fais :
// boucle activé sur reception de données serie : void MainWindow::on_Received_Data() { // ------- choses à faire - RX side ------- qDebug() << "reception données :"; QByteArray ba; ba = serial->readAll(); ui->label_uart_pic->setText("Données reçues : " + ba ); qDebug() << ba; }
Le fonctionnement est quasi le meme que pour le rfid j'ai un timer qui tourne qui vérifie l'état d'un bouton poussoir et qui suivant son état allume une led et envoie un une commande au Pic qui lui répond.
Une idée pour résoudre ce conflit au niveau des port séries ?
Y'a pas moyen de d'interdire au mainwindow l'accés au port USB0 ?ce genre de problème est juste impensable coté C embarqué classique ;)
( on envoi/reçoit sur un port et un port en l'air reçoit des données...)Un grand merci pour ton aide @KroMignon !
-
@jym92 said in Problème en lecture/écriture de badge RFID mifare classic avec Raspberry et CR038:
ce genre de problème est juste impensable coté C embarqué classique ;)
( on envoi/reçoit sur un port et un port en l'air reçoit des données...)Ca n'a rien à voir avec le langage de programmation C ANSI ou C++, c'est une question d'organisation du code...
Tu auras le même type de problème quelque soit le langage utilisé (même C#).
Si tu autorises tout le monde à accéder à tous les ports série, et bien c'est la cacophonie assurée!Pour ton projet, il te faut définir:
- une classe qui va s'occuper du dialogue avec ton lecture RFID
- une classe qui va s'occuper du dialogue avec ton PIC
Après tu fais le lien entre tes instances avec l'aide de signaux et slots.
En gros, dans ta classe RFID (RFIDworker) tu ajoutes un signal pour demander le contrôle de la LED (par exemple
setLedState(bool state)
):class RFIDworker : public QObject { Q_OBJECT public: explicit RFIDworker(QObject *parent= nullptr); ... signals: void setLedState(bool state); ... };
comme ça tu peux demander d'allumer ou éteindre la LED avec
emit setLedState(true);
/emit setLedState(false);
Dans ta classe PIC (PicManager), tu vas créer un slot pour la commande de la LED RFID:class PicManager: public QObject { Q_OBJECT public: explicit PicManager(QObject *parent= nullptr); ... public: void setRfidLedState(bool state); ... };
Chaque class va s'occuper de son port série et tout le monde sera content.
Bref, comme écrit plus haut, c'est une question d'organisation du code. Le C++ permet de simplement cloisonner tout le monde, encore faut-il le faire, ça c'est à la charge du développeur!
-
OK ok je vois du coup c'est juste un problème d'organisation du code, il faut à chaque fois définir une classe spécifique au port Série utilisé...
Et si jamais j'ai besoin j'ai besoin d'écrire ou de lancer des commandes sur l'un des ports séries depuis le mainwindows, j'appelle alors des fonctions de cette classe.
OK je mets en place une classe spécifique pour la gestion du port série de mon PIC sur le même modèle que celle utilisée par le RFID.
Je vous tiens au jus si tout ça fonctionne, merci ;)
-
@jym92 Exactement, et dans l'absolue tu pourrais utiliser plusieurs lecteurs RFID ou PIC, il te suffit de créer autant d'instances des classes correspondantes.
Et c'est là que le C++ (ou C#) prends largement l'avantage sur la programmation en C ANSI. -
@jym92 Autre info au passage, rien ne t'oblige à faire du multi-threading avec ton application. Je pense que tu devrais largement t'en sortir uniquement avec le thread principal.
Dans ce cas, il te suffit de légèrement modifier ta séquence d'init:auto* rfWorker = new RFIDworker(); // stop RF ID Reader on main application exit connect(qApp, &QApplication::aboutToQuit, rfWorker, &QObject::deleteLater); #if USE_MULTITHREAD auto* rfThread = new QThread(); // start RF ID Reader on thread start connect(rfThread, &QThread::started, rfWorker , &RFIDworker::start); // delete thread on worker end connect(rfWorker, &QObject::destroyed, rfThread, [rfThread](QObject *) { if(rfThread->isRunning()) { rfThread->quit(); rfThread->wait(); } rfThread->deleteLater(); } , Qt::DirectConnection); // needs "DirectConnection" to work // to be informed about new RF ID tag //connect(rfWorker, &RFIDworker::newTag, this, &MyMainClass::newRfIdTag); // move worker object to worker thread rfWorker->moveToThread(rfThread); // last but not least, start worker thread rfThread->start(); #else rfWorker->start(); #endif
Et de même pour l'instance de ta classe de gestion du PIC.
-
Grande nouvelle ! Tout fonctionne comme je le souhaite !
j'ai même essayé de saturé le port série lié au PIC en lui envoyant des commandes depuis une Arduino vers la Raspberry en même temps que le RFID fonctionne et je n'ai vu aucun problème ;)
Je suis parti sur un Thread/Worker spécifique à chaque port série car pour le moment je n'ai qu'un PIC et un RFID mais je vais devoir ajouter encore 2 port séries pour un gprs et un monnayeur.
Je pense que dans mon cas ce cloisonnement par Thread pour chaque port série évite tout risque de débordement ou de paralysie de l'IHM.Je vais maintenant continuer à travailler sur l’accès aux données de mon RFID(acces block).
Un grand merci pour votre aide ! ;)