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
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
2
3
4
5
6
7
8
9
//Needed for I2C port
10
//Needed for I2C port
11
//Needed for I2C port
12
//Needed for I2C port
13
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
// CI2C_H
1
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
2
3
4
5
6
7
8
// 0x40 + bit LSB à 0 pour write
9
10
11
12
13
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
// CCAPTEURTEMPHUMI2C_H
1
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
2
3
4
5
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
// CIHMAPPSHT20_H
1
2
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
}