Lecture de la température et de l'humidité

Question

Concevez une application graphique Qt permettant d'afficher la température et l'humidité (capteur SHT20 sur le diagramme structurel).

Indice

Il faut utiliser la classe de gestion de l'I2C, créer une classe pour le capteur et enfin rassembler tout cela dans une application.

Solution

Sources de l'application exemple

Le fichier de projet appsht20.pro :

1
#-------------------------------------------------
2
#
3
# Project created by QtCreator 2017-12-20T14:49:44
4
#
5
#-------------------------------------------------
6
7
QT       += core gui
8
9
greaterThan(QT_MAJOR_VERSION, 4): QT += widgets
10
11
TARGET = appSHT20
12
TEMPLATE = app
13
14
# The following define makes your compiler emit warnings if you use
15
# any feature of Qt which as been marked as deprecated (the exact warnings
16
# depend on your compiler). Please consult the documentation of the
17
# deprecated API in order to know how to port your code away from it.
18
DEFINES += QT_DEPRECATED_WARNINGS
19
20
# You can also make your code fail to compile if you use deprecated APIs.
21
# In order to do so, uncomment the following line.
22
# You can also select to disable deprecated APIs only up to a certain version of Qt.
23
#DEFINES += QT_DISABLE_DEPRECATED_BEFORE=0x060000    # disables all the APIs deprecated before Qt 6.0.0
24
25
26
SOURCES += main.cpp\
27
        cihmappsht20.cpp \
28
    ../biblis/ci2c.cpp \
29
    ccapteur_i2c_sht20_nth.cpp
30
31
HEADERS  += cihmappsht20.h \
32
    ../biblis/ci2c.h \
33
    ccapteur_i2c_sht20_nth.h
34
35
FORMS += cihmappsht20.ui

Le fichier décrivant l'interface graphique :

1
<?xml version="1.0" encoding="UTF-8"?>
2
<ui version="4.0">
3
 <class>CIhmAppSHT20</class>
4
 <widget class="QMainWindow" name="CIhmAppSHT20">
5
  <property name="geometry">
6
   <rect>
7
    <x>0</x>
8
    <y>0</y>
9
    <width>225</width>
10
    <height>391</height>
11
   </rect>
12
  </property>
13
  <property name="windowTitle">
14
   <string>CIhmAppSHT20</string>
15
  </property>
16
  <widget class="QWidget" name="centralWidget">
17
   <widget class="QPushButton" name="pbTemp">
18
    <property name="geometry">
19
     <rect>
20
      <x>40</x>
21
      <y>10</y>
22
      <width>141</width>
23
      <height>29</height>
24
     </rect>
25
    </property>
26
    <property name="text">
27
     <string>Lire Température</string>
28
    </property>
29
   </widget>
30
   <widget class="QPushButton" name="pbHum">
31
    <property name="geometry">
32
     <rect>
33
      <x>40</x>
34
      <y>40</y>
35
      <width>141</width>
36
      <height>29</height>
37
     </rect>
38
    </property>
39
    <property name="text">
40
     <string>Lire Humidité</string>
41
    </property>
42
   </widget>
43
   <widget class="QTextEdit" name="textEdit">
44
    <property name="geometry">
45
     <rect>
46
      <x>10</x>
47
      <y>80</y>
48
      <width>201</width>
49
      <height>231</height>
50
     </rect>
51
    </property>
52
   </widget>
53
  </widget>
54
  <widget class="QMenuBar" name="menuBar">
55
   <property name="geometry">
56
    <rect>
57
     <x>0</x>
58
     <y>0</y>
59
     <width>225</width>
60
     <height>26</height>
61
    </rect>
62
   </property>
63
  </widget>
64
  <widget class="QToolBar" name="mainToolBar">
65
   <attribute name="toolBarArea">
66
    <enum>TopToolBarArea</enum>
67
   </attribute>
68
   <attribute name="toolBarBreak">
69
    <bool>false</bool>
70
   </attribute>
71
  </widget>
72
  <widget class="QStatusBar" name="statusBar"/>
73
 </widget>
74
 <layoutdefault spacing="6" margin="11"/>
75
 <resources/>
76
 <connections/>
77
</ui>

Ces fichiers sont disponibles dans le dépôt biblis de github.

Les fichiers de la classe I2C CI2c.h et CI2c.cpp :

1
#ifndef CI2C_H
2
#define CI2C_H
3
4
#include <QObject>
5
#include <QMutex>
6
#include <QMutexLocker>
7
#include <QDebug>
8
#include <stdio.h>
9
#include <unistd.h>				//Needed for I2C port
10
#include <fcntl.h>				//Needed for I2C port
11
#include <sys/ioctl.h>			//Needed for I2C port
12
#include <linux/i2c-dev.h>		//Needed for I2C port
13
#include <strings.h>
14
15
class CI2c : public QObject
16
{
17
    Q_OBJECT
18
19
public:
20
    // creation destruction de l'objet
21
    static CI2c *getInstance(QObject *parent = 0, char no = '1');
22
    static void freeInstance();
23
    int lire(unsigned char addr, unsigned char *buffer, int lg);
24
    int ecrire(unsigned char addr, unsigned char *buffer, int lg);
25
26
private:
27
    explicit CI2c(QObject *parent = 0, char noBus = '1');
28
    int init();
29
    QObject *m_parent;
30
    QMutex m_mutexI2c;
31
    int getNbLink();
32
    int m_addr;   // Adresse du composant I2C
33
    char m_noBus;   // No d'accès au fichier /dev
34
    int m_fileI2c;  // descripteur du fichier i2C
35
    int m_nbLink;
36
    static CI2c *m_singleton;
37
38
signals:
39
    void sigErreur(QString msg);
40
};
41
42
#endif // CI2C_H
1
#include "ci2c.h"
2
3
CI2c::CI2c(QObject *parent, char noBus) :
4
    QObject(parent)
5
{
6
    m_parent = parent;
7
    m_noBus = noBus;
8
    m_nbLink=0;
9
} // constructeur
10
11
CI2c * CI2c::m_singleton = NULL;
12
13
int CI2c::lire(unsigned char addr,  unsigned char *buffer, int lg)
14
{
15
    if(ioctl(m_fileI2c, I2C_SLAVE, addr)!=0) {  // Règle le driver I2C sur l'adresse.
16
        QString mess="CI2c::lire Erreur ioctl acces au bus I2C";
17
//        qDebug() << mess;
18
        emit sigErreur(mess);
19
        return -1;
20
    } // if ioctl
21
    bzero(buffer, lg);
22
    QMutexLocker lock(&this->m_mutexI2c);  // verrouillage du mutex. Il est libéré en sortie de méthode
23
24
    int nb=read(m_fileI2c, buffer, lg);
25
//    qDebug() << "CI2c:lire: " << buffer[0] << " " << buffer[1] << buffer[2] << " " << buffer[3] << buffer[4] << " " << buffer[5];
26
    return nb;
27
} // lire
28
29
int CI2c::ecrire(unsigned char addr, unsigned char *buffer, int lg)
30
{
31
    if(ioctl(m_fileI2c, I2C_SLAVE, addr)!=0) {  // Règle le driver I2C sur l'adresse.
32
        QString mess="CI2c::ecrire Erreur ioctl acces au bus I2C";
33
//        qDebug() << mess;
34
        emit sigErreur(mess);
35
        return -1;
36
    } // if ioctl
37
38
    QMutexLocker lock(&this->m_mutexI2c);  // verrouillage du mutex. Il est libéré en sortie de méthode
39
40
    int nb=write(m_fileI2c, buffer, lg);
41
//    qDebug() << "CI2c:ecrire: nb=" << nb << " : " << buffer[0] << " " << buffer[1] << buffer[2];
42
    return nb;
43
} // ecrire
44
45
int CI2c::init()
46
{
47
    char filename[20];
48
    sprintf(filename, "/dev/i2c-%c",m_noBus);
49
    if((m_fileI2c=open(filename, O_RDWR))==-1) {  // ouvre le fichier virtuel d'accès à l'I2C
50
        QString mess="CI2c::init Erreur ouverture acces au bus I2C";
51
//        qDebug() << mess;
52
        emit sigErreur(mess);
53
        return -1;
54
    } // if open
55
    return m_fileI2c;
56
} // init
57
58
int CI2c::getNbLink()
59
{
60
    return m_nbLink;
61
} // getNbLink
62
63
CI2c *CI2c::getInstance(QObject *parent, char no)
64
{
65
    if (m_singleton == NULL)
66
    {
67
        qDebug("L'objet CI2c est créé");
68
        m_singleton =  new CI2c(parent, no);
69
        m_singleton->init();
70
        m_singleton->m_nbLink=1;
71
    }
72
    else
73
    {
74
        m_singleton->m_nbLink++;
75
        qDebug("singleton est déjà existant");
76
    }
77
    return m_singleton;
78
} // getInstance
79
80
void CI2c::freeInstance()
81
{
82
    if (m_singleton != NULL)
83
      {
84
            m_singleton->m_nbLink--;
85
            if (m_singleton->m_nbLink==0) {
86
                close(m_singleton->m_fileI2c);
87
                delete m_singleton;
88
                m_singleton = NULL;
89
            } // if mNbLink
90
      } // if null
91
} // freeInstance

Les fichiers de la classe de gestion du capteur SHT20 ccapteur_i2c_sht20_nth.h et ccapteur_i2c_sht20_nth.cpp :

1
#ifndef CCAPTEUR_I2C_SHT20_NTH_H
2
#define CCAPTEUR_I2C_SHT20_NTH_H
3
4
#include <QObject>
5
#include <QThread>
6
#include "/home/pi/devQt/biblis/ci2c.h"
7
8
#define ADR 0x40 // 0x40 + bit LSB à 0 pour write
9
#define COM_MES_TEMP 0xf3
10
#define COM_MES_HUM 0xf5
11
#define COM_RESET 0xfe
12
#define COM_READ_REG 0xe7
13
#define COM_WRITE_REG 0xe6
14
15
class CCapteur_I2c_SHT20_NTh : public QObject
16
{
17
    Q_OBJECT
18
19
public:
20
    explicit CCapteur_I2c_SHT20_NTh(QObject *parent = 0);
21
    ~CCapteur_I2c_SHT20_NTh();
22
    float lireMesureHum();
23
    float lireMesureTemp();
24
25
private:
26
    CI2c *m_i2c;
27
28
signals:
29
    void sigErreur(QString mess);
30
31
private slots:
32
    void onErreur(QString mess);
33
};
34
35
#endif // CCAPTEURTEMPHUMI2C_H
1
#include "ccapteur_i2c_sht20_nth.h"
2
3
CCapteur_I2c_SHT20_NTh::CCapteur_I2c_SHT20_NTh(QObject *parent) :
4
    QObject(parent)
5
{
6
    m_i2c = CI2c::getInstance(this, '1');
7
    connect(m_i2c, SIGNAL(sigErreur(QString)), this, SLOT(onErreur(QString)));
8
    qDebug() << "Objet CCapteur_I2c_SHT20_NTh créé !";
9
}
10
11
CCapteur_I2c_SHT20_NTh::~CCapteur_I2c_SHT20_NTh()
12
{
13
    CI2c::freeInstance();
14
    qDebug() << "Objet CCapteur_I2c_SHT20_NTh détruit !";
15
}
16
17
18
void CCapteur_I2c_SHT20_NTh::onErreur(QString mess)
19
{
20
    emit sigErreur(mess);
21
}
22
23
float CCapteur_I2c_SHT20_NTh::lireMesureHum()
24
{
25
    float hum;
26
    unsigned char lecture[3];
27
    unsigned char ecriture[1];
28
    int res;
29
30
    ecriture[0] = COM_MES_HUM;
31
    m_i2c->ecrire(ADR, ecriture, 1);
32
    usleep(100000);
33
    res=m_i2c->lire(ADR, lecture, 2);
34
    if (res != 2) {
35
        QString mess="CCapteur_I2c_SHT20_NTh::lireMesureHum ERREUR Lecture";
36
        emit sigErreur(mess);
37
        return -1;
38
    } // if res
39
    unsigned char MSB = lecture[0];
40
    unsigned char LSB = lecture[1]&0xFC;
41
    hum=((MSB<<8)+LSB);
42
    hum = -6+125*hum/65536;
43
    return hum;
44
} // lireMesHum
45
46
float CCapteur_I2c_SHT20_NTh::lireMesureTemp()
47
{
48
    float temp;
49
    unsigned char lecture[2];
50
    unsigned char ecriture[1];
51
    int res;
52
53
    ecriture[0] = COM_MES_TEMP;
54
    m_i2c->ecrire(ADR, ecriture, 1);
55
    usleep(100000);
56
    res=m_i2c->lire(ADR, lecture, 2);
57
    if (res != 2) {
58
        QString mess="CCapteur_I2c_SHT20_NTh::lireMesureTemp ERREUR Lecture";
59
        emit sigErreur(mess);
60
        return -1;
61
     } // if res
62
    unsigned char MSB = lecture[0];
63
    unsigned char LSB = lecture[1]&0xF0;
64
    temp = ((MSB<<8)+LSB);
65
    temp = -46.85+175.72*temp/65536;
66
    return temp;
67
} // lire MesTemp

Les fichiers de la classe de gestion de l'IHM de l'application :

1
#ifndef CIHMAPPSHT20_H
2
#define CIHMAPPSHT20_H
3
4
#include <QMainWindow>
5
#include "ccapteur_i2c_sht20_nth.h"
6
7
namespace Ui {
8
class CIhmAppSHT20;
9
}
10
11
class CIhmAppSHT20 : public QMainWindow
12
{
13
    Q_OBJECT
14
15
public:
16
    explicit CIhmAppSHT20(QWidget *parent = 0);
17
    ~CIhmAppSHT20();
18
19
private slots:
20
    void on_pbTemp_clicked();
21
    void on_pbHum_clicked();
22
    void onErreur(QString mess);
23
24
private:
25
    Ui::CIhmAppSHT20 *ui;
26
    CCapteur_I2c_SHT20_NTh *m_sht20;
27
};
28
29
#endif // CIHMAPPSHT20_H
1
#include "cihmappsht20.h"
2
#include "ui_cihmappsht20.h"
3
4
CIhmAppSHT20::CIhmAppSHT20(QWidget *parent) :
5
    QMainWindow(parent),
6
    ui(new Ui::CIhmAppSHT20)
7
{
8
    ui->setupUi(this);
9
    m_sht20 = new CCapteur_I2c_SHT20_NTh(this);
10
    connect(m_sht20, SIGNAL(sigErreur(QString)), this, SLOT(onErreur(QString)));
11
}
12
13
CIhmAppSHT20::~CIhmAppSHT20()
14
{
15
    delete m_sht20;
16
    delete ui;
17
}
18
19
void CIhmAppSHT20::on_pbTemp_clicked()
20
{
21
   float mesure;
22
   mesure = m_sht20->lireMesureTemp();
23
   onErreur("Température : "+QString::number(mesure, 'f',1)+" °C");
24
}
25
26
void CIhmAppSHT20::on_pbHum_clicked()
27
{
28
    float mesure;
29
    mesure = m_sht20->lireMesureHum();
30
    onErreur("Humidité : "+QString::number(mesure, 'f',1)+" %RH");
31
32
}
33
34
void CIhmAppSHT20::onErreur(QString mess)
35
{
36
    ui->textEdit->append(mess);
37
}