Docteur en thermique et énergétique je me passionne pour la physique, l'informatique, les mathématiques appliquées et l'électronique. Après une thèse de doctorat sur la modélisation d'un gazéifieur solaire et phase hétérogène et un post-doctorat sur le confort thermique non stationnaire et non uniforme dans le bâtiment, je travaille actuellement sur la conception d'un laser impulsionnel paramétrique.
Published

jeu. 31 août 2017

←Home

Développement d'un capteur de température sous micropython avec un ESP8266 et un TMP102.

Introduction¶

Les objets connectés sont à la mode. On les trouve dans un très grand nombre d'applications, allant des capteurs de températures, aux pesées-personne en passant par les montres. Dans cet article, nous allons nous intéresser à la conception un capteur de température connecté. Nous utiliserons un ESP8266 sous micropython et un GYTMP102.

ESP8266¶

Wikipedia l'introduit de la manière suivante:

L’ESP8266 est un circuit intégré à microcontrôleur avec connexion WiFi développé par le fabricant chinois Espressif. En août 2014, les passionnés d’électronique commencent à s’intéresser à la version ESP-01 de ce circuit intégré produite par une entreprise tierce, AI-Thinker. Celui-ci, de taille réduite, permet de connecter un microcontrôleur à un réseau WiFi et d’établir des connexions TCP/IP avec des commandes Hayes. La traduction progressive de la documentation (à l'origine uniquement en chinois) motivée par le bas prix du circuit a permis le développement d'une communauté de développeurs et de passionnés de l'ESP8266.

Si je devais le résumé rapidement c'est un arduino en plus puissant et moins cher avec le wifi intégré, mais un nombre de GPIO moins important. Du fait de son hardware plus puissant, il a permis la communauté de porter de nombreux langages sur ce microcontrôleur:

  • Avec des scripts Lua, interprétés ou compilés, avec le firmware NodeMCU
  • En C++, avec l’IDE Arduino
  • En JavaScript, avec le firmware Espruino
  • En MicroPython, avec le firmware MicroPython
  • En C, avec le SDK d’Espressif
  • En C, avec le SDK esp-open-sdk3 basé sur la chaîne de compilation GCC

Micropython¶

Dans cet article nous utiliserons Micropython, qui est une implémentation logicielle du langage de programmation Python 3, écrit en C, et optimisé pour fonctionner sur des microcontrôleurs. Dans cet article nous utiliserons la version 1.9.2.

GYTMP102¶

Le GYTMP102 est un capteur de température très abordable, basé sur le TMP102 avec une précision de 0,5°C et qui communique l'information via une interface I2C. Des photos du capteur se trouvent ci-dessous:

alt1 alt1

Connecter la sonde et le microcontrôleur¶

Pour connecter la sonde et le microcontrôleur, nous allons utiliser l'I2C qui est un bus informatique très utilisé.

Wikipedia l'introduit de la manière suivante:

I2C (signifie : Inter-Integrated Circuit, en anglais) est un bus informatique qui a émergé de la « guerre des standards » lancée par les acteurs du monde électronique. Conçu par Philips pour les applications de domotique et d’électronique domestique, il permet de relier facilement un microprocesseur et différents circuits, notamment ceux d’un téléviseur moderne : récepteur de la télécommande, réglages des amplificateurs basses fréquences, tuner, horloge, gestion de la prise péritel, etc.

Physiquement, il comprend 2 fils: SCL et SDA, respectivement les lignes d'horloge et de données qu'il va nous falloir connecter au microcontrôleur.

Pour l'ESP8266 sous micropython et comme expliqué dans la documentation, le pilote I2C est implémenté de manière logiciel, fonctionne sur toutes les broches et est accessible via la classe machine.I2C.

Ci-dessous une représentation de l'ESP8266 avec les caractéristiques des GPIO et surtout leurs numéros qu'il nous faudra connaitre pour spécifier l'interface i2c.

Drawing

Maintenant, il nous faut savoir comment communiquer avec notre capteur, adresses, fréquence, etc. Toutes les informations nécessaires sont en général disponibles dans la documentation du capteur. Pour le capteur qui nous intéresse elle se trouve ici.

Avant d'aller plus loin, vérifions que notre notebook est bien connecté à l'ESP8266.

In [1]:
print("Le microcontroleur est connecté au kernel")
Le microcontroleur est connecté au kernel

On importe les modules pour crée une interface I2C.

In [2]:
from machine import Pin, I2C

On connect le capteur. SCL est connecté sur le GPIO 14 et SDA sur le GPIO 12.

Drawing

On crée une interface I2C sur les GPIO ou nous avons connecté le capteur.

In [3]:
i2c = I2C(scl=Pin(14), sda=Pin(12))

On scanne l'interface i2c pour connaitre les adresses des objets présents.

In [4]:
#On regarde les adresses possibles
adresse = i2c.scan()
if len(adresse) == 1:
    print("l'adresse est:", adresse[0])
else:
    print("il y a plusieurs objets sur le bus i2c")
l'adresse est: 72

La documentation nous explique qu'il y a deux modes. Un mode normal sur 12 bits et un mode étendu sur 13 bits pour mesurer des températures supérieures à 128°C. Nous nous intéresserons au mode normal.

Nous allons interroger le capteur et lire les 2 premiers bytes (1 bytes = 1 octet = 8 bits)

In [5]:
#Nombre de bytes à lire
nb_bytes = 2
#On stocke les bytes dans 'reg'
reg = i2c.readfrom(adresse[0], nb_bytes)
print("Nous avons donc deux bytes:",reg)
Nous avons donc deux bytes: b'\x18\x90'

D'aprés la documentation, le premier byte est le "most significant byte" (MSB), le deuxieme est le "less significant byte" (LSB).

In [6]:
#Byte 1 is the most significant byte (MSB)
MSB = reg[0]
#Byte 2 is the less significant byte (LSB)
LSB = reg[1]
print("MSB:",bin(MSB),"LSB:",bin(LSB))
MSB: 0b11000 LSB: 0b10010000

Nous allons regarder si la température est négative. Pour que la température soit négative, il faut que le 1er bit de MSB soit égal à 1. Pour tester le 1er bit, on décale MSB de 7 bits sur la droite. Tous les nouveaux bits qui apparaissent valent 0. Nous aurons donc la valeur 0 si le 1er bit vaut 0 et la valeur 1 si le 1er bit vaut 1.

In [7]:
negative = (MSB >> 7) == 1
print("Température est négative:",negative)
Température est négative: False

Température positive¶

Nous voulons maintenant connaitre la valeur de la température. Pour ce faire, nous devons tout d'abord concaténer les 12 bits qui nous intéressent. Nous avons récupéré 2 bytes (octets) soit 16 bits. Pour le mode normal sur 12 bits la documentation nous explique qu'il faut tous les bits de MSB et les 4 premiers de LSB. Pour ce faire, nous allons prendre le premier byte et décaler de 8 bits "vers la gauche" de manière à pouvoir lui ajouter LSB. Nous ajouterons LSB et nous décalerons les 16 bits de 4 bits "vers la droite" de manière à ne tenir compte que des 12 bits qui nous intéressent. Il faut ensuite convertir les 12 bits en chiffre décimal (ce que python fait automatiquement), et enfin multiplier ce chiffre par la résolution (0.0625) pour avoir la température.

Regardons comment cela se formalise:

In [8]:
bits_16 = (MSB << 8) + LSB
bits_12 = bits_16 >> 4
temperature = bits_12 * 0.0625
print(temperature)
24.5625

Que l'on peut écrire de manière plus concise !

In [9]:
print((((MSB << 8) | LSB) >> 4) * 0.0625)
24.5625

Température négative¶

Ne pouvant pas faire de mesure de température négative facilement en cette période de l'année, nous allons utiliser les 12 bits codant la température -25°C dans la documentation. Les 12 bits encodant -25°C sont les suivants:'111001110000'. Pour décoder une température négative, il faut récupérer le complément, lui ajouter 1, puis le multiplier par la résolution. Construire le complément consiste à remplacer les 1 par 0 et les 0 par 1.

In [10]:
moins_25 = '111001110000'
complement_moins_25 = ''
for i in range(len(moins_25)):
    if moins_25[i] == '1':
        complement_moins_25 = complement_moins_25 + '0'
    else:
        complement_moins_25 = complement_moins_25 + '1'
print('Le complement est:', complement_moins_25)
Le complement est: 000110001111
In [11]:
t_m25 = int(complement_moins_25, 2) + 1
t_m25 *= -0.0625
print('la température est:', t_m25)
la température est: -25.0

La méthode que nous venons d'appliquer est intéressante d'un point de vue pédagogique, mais peu efficient. Mais nous pouvons arriver au même résultat de manière beaucoup plus efficace.

In [12]:
nb_bits = 12
moins_25_int = int(moins_25, 2)
complement_moins_25 = moins_25_int - (1 << nb_bits)
t_m25 = complement_moins_25 * 0.0625
print('la température est:', t_m25)
la température est: -25.0

La fonction finale¶

Nous construisons une fonction qui effectue toutes les étapes que nous venons de détailler:

In [13]:
def temperature_tmp102(bus,adresse):
    nb_bytes = 2 #nb bytes a lire
    nb_bits = 12 #nb bits encodage température
    reg = bus.readfrom(adresse, nb_bytes) #lecture des bytes
    MSB, LSB = reg[0], reg[1]
    negative = (MSB >> 7) == 1 #test température négative
    t_12_bits = (((MSB << 8) | LSB) >> 4) #récupération des 12bits de la température
    if negative == True:
        t_12_bits = t_12_bits - (1 << nb_bits)
    temperature = t_12_bits * 0.0625
    return temperature

Nous allons tester notre fonction en mesurant la température chaque seconde pendant 10s.

In [14]:
import utime

bus = I2C(scl=Pin(14), sda=Pin(12))
add = 72
temperature = []
for i in range(10):
    temperature.append(temperature_tmp102(bus,add))
    utime.sleep(1)

print(temperature)
[24.625, 24.5625, 24.5625, 24.5625, 24.5625, 24.5625, 24.5625, 24.5625, 24.5625, 24.5625]

Conclusion¶

Dans cet article, nous avons utilisé un ESP8266 couplé à un TMP102 pour construire un capteur de température sous micropython. Il est ensuite possible de crée une interface web, héberger sur l'ESP8266, qui affiche la température. Il est aussi possible de la transmettre via le protocole MQTT ou de stoker les valeurs dans la mémoire interne. Ces éléments seront traités dans un prochain article.

Go Top