Cours:TPgpioQT : Différence entre versions

De troyesGEII
Aller à : navigation, rechercher
(Clignotement avec QTimer)
(Sorties)
Ligne 41 : Ligne 41 :
  
  
==Sorties==
+
=Sorties=
  
===Classe Lampe===
+
==Classe Lampe==
 
On utilisera la classe Lampe pour piloter des sorties.
 
On utilisera la classe Lampe pour piloter des sorties.
  
Ligne 160 : Ligne 160 :
  
  
===Ajout de fonctionnalité à la classe Lampe===
+
==Ajout de fonctionnalité à la classe Lampe==
  
 
On souhaite pouvoir changer l'état d'une lampe (si elle est allumée elle doit s'éteindre et inversement).
 
On souhaite pouvoir changer l'état d'une lampe (si elle est allumée elle doit s'éteindre et inversement).
Ligne 169 : Ligne 169 :
  
  
=== Clignotement avec QTimer ===
+
== Clignotement avec QTimer ==
  
 
On peut facilement faire clignoter une lampe avec un <code>QTimer</code> :
 
On peut facilement faire clignoter une lampe avec un <code>QTimer</code> :
Ligne 184 : Ligne 184 :
  
  
===Cahier des charges===
+
==Cahier des charges==
  
 
Ecrire un programme qui permet de :
 
Ecrire un programme qui permet de :

Version du 16 septembre 2022 à 15:06

Retour à la liste des Tds

GPIO

Gpio rpi3.png

On dispose d'un connecteur avec un certain nombre de GPIO sur la carte rpi.

Ce sont des broches configurables qui peuvent servir de :

  • entrée logique
  • sortie logique
  • fonction particulière :
    • entrée analogique (pas sur les rpi actuelles)
    • i2c
    • spi
    • pwm
    • liaison série
    • ...

Cartographie GPIO <-> modules

Plusieurs modules sont connectés sur les ports GPIO de la Rpi :

n° GPIO Module n° GPIO Module n° GPIO Module
5 Encodeur 16 Bouton poussoir 1 (vert?) 18 Switch
6 Encodeur 17 Bouton poussoir 2 (rouge?)
22 led Rouge 24 led Verte

Préparation du projet

  • Créer un nouveau projet de type "Widget application"
  • Choisir le kit "Rpi"
  • Télécharger/décompresser et placer les fichiers de l'archive suivant dans votre projet
  • Dans l'arborescence de votre projet,
    • Ajouter des fichiers existants


Sorties

Classe Lampe

On utilisera la classe Lampe pour piloter des sorties.

lampe.h

#ifndef LAMPE_H
#define LAMPE_H

#include <QObject>
#include "gpio.h"
using namespace exploringRPi;

class Lampe : public QObject
{
    Q_OBJECT
public:
    Lampe(int nbBroche);

private :
    bool etat;
    GPIO broche;

signals:
    void nouvelEtat(bool etat);
public slots:
    void allumer();
    void eteindre();
    void setValue(bool e);
};

#endif // LAMPE_H

lampe.cpp

#include "lampe.h"

Lampe::Lampe(int nbBroche) : QObject(), broche(nbBroche)
{
    broche.setDirection(OUTPUT);
    setValue(false);
}

void Lampe::allumer()
{
    setValue(true);
}

void Lampe::eteindre()
{
    setValue(false);
}

void Lampe::setValue(bool e)
{
    if (e==true) broche.setValue(HIGH);
            else broche.setValue(LOW);
    etat = e;
    emit nouvelEtat(etat);
}

Question.jpg Faire le diagramme de classe d'après le fichier lampe.h


On va instancier la classe Lampe en précisant le numéro de GPIO utilise. Pour cela, le constructeur de la classe GPIO nécessite le passage d'un paramètre :

Lampe(int nbBroche);

2 approches sont possibles :

//1ère possibilité on l'indique dans la déclaration (mainwindow.h)
// ajout d'un attribut dans le header
#include "lampe.h"
...
class MainWindow : public QMainWindow
{
   ....
   Lampe ledRouge{20};
   ....
}
//2ère possibilité on l'indique dans la définition du constructeur
// dans le mainwindow.h
#include "gpio.h"
...
class MainWindow : public QMainWindow
{
   ....
   Lampe ledRouge;
   ....
}
...
// dans le mainwindow.cpp
....
MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent),
      ui(new Ui::MainWindow),ledRouge(16)
{
   ....
}

Question.jpg Instancier la classe Lampe et l'utiliser pour allumer la led verte à l'aide de bouton sur l'interface graphique


Ajout de fonctionnalité à la classe Lampe

On souhaite pouvoir changer l'état d'une lampe (si elle est allumée elle doit s'éteindre et inversement).

Pour ajouter cette fonctionnalité nous devons ajouter une méthode.

Question.jpg Ajouter une méthode changerEtat à la classe Lampe et l'utiliser


Clignotement avec QTimer

On peut facilement faire clignoter une lampe avec un QTimer :

  • on choisit une durée : monTimer.setInterval(dure_Ms);
  • le signal timeout est émis toutes les duree_Ms
  • il faut se connecter sur le signal, au choix :
    • connect(&monTimer,SIGNAL(timeout()),&maLampe,SLOT(toggle()));
    • connect(&monTimer,&QTimer::timeout,&maLampe,&Lampe::toggle);
  • on lance le timer : monTimer.start();

Il faut bien entendu ajouter monTimer comme un attribut de la classe MainWindow (ajouter #include <QTimer>)

Question.jpg En utilisant un QTimer, faire clignoter la lampe rouge


Cahier des charges

Ecrire un programme qui permet de :

  • allumer individuellement chaque led
  • éteindre individuellement chaque led
  • éteindre toutes les 2 leds avec 1 seul bouton
  • allumer toutes les 2 leds avec 1 seul bouton
  • éteindre toutes les 2 leds avec 1 seul bouton
  • mettre en route/arrêter individuellement le clignotement de chaque led (en utilisant un QTimer):
    • la led rouge à 1Hz
    • la led verte à 5Hz
  • quitter l'application

Entrées

On pourrait procéder de façon analogue :

#include ....
using namespace exploringRPi;
...
GPIO bp{16};
....
bp.setDirection(INPUT);
int n = bp.getValue();

Attention, en procédant de la sorte, il convient de scruter régulièrement la valeur de l'entrée pour vérifier si celle-ci n'a pas changée d'état. On peut par exemple utiliser un QTimer pour réaliser ce polling.


Comme nous réalisons une programmation événementielle, cette méthode n'est pas la plus adaptée, voyons comment faire :

  • les GPIOs se trouvent dans l'arborescence linux dans le répertoire /sys/class/gpio/
  • si une broche est configurée, la 10 par ex, on aura un répertoire : /sys/class/gpio/gpio10/
  • dans ce répertoire, il y a un fichier value
  • on va observer ce fichier /sys/class/gpio/gpio10/value qui reflète l'état de la broche
  • on demandera l'exécution d'un SLOT lors de la modification de ce fichier
  • mise en oeuvre :
// il nous faut un objet de type QFileSystemWatcher
#include <QFileSystemWatcher>

// On ajoute un attribut de type QFileSystemWatcher:
QFileSystemWatcher bpWatcher;
GPIO bp{10};
...
...
// On configure la broche en entrée:
bp.setDirection(INPUT);
// Quel type d'événement nous intéresse ? NONE, RISING, FALLING, BOTH
bp.setEdgeType(BOTH);
// On ajoute la liste des fichiers dont il faut surveiller la modification
bpWatcher.addPath("/sys/class/gpio/gpio10/value");
// Un signal "fileChanged" est généré à chaque événement surveillé (cf plus haut)
connect(&bpWatcher,SIGNAL(fileChanged(QString)), ... , SLOT( .... ));


Question.jpg Interfacer le switch pour commander la led verte

Question.jpg Interfacer les boutons poussoirs rouge et vert pour augmenter/diminuer la période de clignotement de la led rouge