Apprenez à programmer les cartes ESP32 ou ESP8266 avec MicroPython pour publier les lectures du capteur BME280 (température, humidité et pression) via MQTT sur n’importe quelle plate-forme prenant en charge MQTT ou tout client MQTT. À titre d’exemple, nous publierons les lectures des capteurs sur le tableau de bord Node-RED.

Lecture recommandée: Qu’est-ce que MQTT et comment ça marche
Noter: ce tutoriel est compatible avec les cartes de développement ESP32 et ESP8266.
Aperçu du projet
Le diagramme suivant montre une vue d’ensemble de haut niveau du projet que nous allons construire.

- L’ESP demande des lectures de température et d’humidité du capteur BME280 ;
- Les relevés de température sont publiés dans le esp/bme280/température sujet;
- Les relevés d’humidité sont publiés dans le esp/bme280/humidité sujet;
- Les relevés de pression sont publiés dans le esp/bme280/pression sujet;
- Node-RED est abonné à ces sujets ;
- Node-RED reçoit les lectures des capteurs et les affiche sur des jauges ;
- Vous pouvez recevoir les lectures sur n’importe quelle autre plate-forme prenant en charge MQTT et gérer les lectures comme vous le souhaitez.
Conditions préalables
Avant de poursuivre ce didacticiel, assurez-vous de remplir les conditions préalables suivantes :
Pour suivre ce tutoriel, vous avez besoin du firmware MicroPython installé dans vos cartes ESP32 ou ESP8266. Vous avez également besoin d’un IDE pour écrire et télécharger le code sur votre carte. Nous vous suggérons d’utiliser Thonny IDE ou uPyCraft IDE :
Courtier MQTT

Pour utiliser MQTT, vous avez besoin d’un courtier. nous utiliserons Courtier en moustiques installé sur un Raspberry Pi. Lisez Comment installer Mosquitto Broker sur Raspberry Pi.
Si vous n’êtes pas familier avec MQTT, assurez-vous de lire notre didacticiel d’introduction : Qu’est-ce que MQTT et comment cela fonctionne
Pièces requises
Pour ce tutoriel, vous avez besoin des pièces suivantes :
Vous pouvez utiliser les liens précédents ou aller directement sur MakerAdvisor.com/tools pour trouver toutes les pièces pour vos projets au meilleur prix !
Bibliothèque umqtttsimple
Pour utiliser MQTT avec l’ESP32/ESP8266 et MicroPython, nous utiliserons le umqttsimplebibliothèque .py. Suivez les instructions suivantes pour l’IDE que vous utilisez :
- A. Télécharger la bibliothèque umqttsimple avec uPyCraft IDE
- B. Télécharger la bibliothèque umqttsimple avec Thonny IDE
try:
import usocket as socket
except:
import socket
import ustruct as struct
from ubinascii import hexlify
class MQTTException(Exception):
pass
class MQTTClient:
def __init__(self, client_id, server, port=0, user=None, password=None, keepalive=0,
ssl=False, ssl_params={}):
if port == 0:
port = 8883 if ssl else 1883
self.client_id = client_id
self.sock = None
self.server = server
self.port = port
self.ssl = ssl
self.ssl_params = ssl_params
self.pid = 0
self.cb = None
self.user = user
self.pswd = password
self.keepalive = keepalive
self.lw_topic = None
self.lw_msg = None
self.lw_qos = 0
self.lw_retain = False
def _send_str(self, s):
self.sock.write(struct.pack("!H", len(s)))
self.sock.write(s)
def _recv_len(self):
n = 0
sh = 0
while 1:
b = self.sock.read(1)[0]
n |= (b & 0x7f) << sh
if not b & 0x80:
return n
sh += 7
def set_callback(self, f):
self.cb = f
def set_last_will(self, topic, msg, retain=False, qos=0):
assert 0 <= qos <= 2
assert topic
self.lw_topic = topic
self.lw_msg = msg
self.lw_qos = qos
self.lw_retain = retain
def connect(self, clean_session=True):
self.sock = socket.socket()
addr = socket.getaddrinfo(self.server, self.port)[0][-1]
self.sock.connect(addr)
if self.ssl:
import ussl
self.sock = ussl.wrap_socket(self.sock, **self.ssl_params)
premsg = bytearray(b"x10 ")
msg = bytearray(b"x04MQTTx04x02 ")
sz = 10 + 2 + len(self.client_id)
msg[6] = clean_session << 1
if self.user is not None:
sz += 2 + len(self.user) + 2 + len(self.pswd)
msg[6] |= 0xC0
if self.keepalive:
assert self.keepalive < 65536
msg[7] |= self.keepalive >> 8
msg[8] |= self.keepalive & 0x00FF
if self.lw_topic:
sz += 2 + len(self.lw_topic) + 2 + len(self.lw_msg)
msg[6] |= 0x4 | (self.lw_qos & 0x1) << 3 | (self.lw_qos & 0x2) << 3
msg[6] |= self.lw_retain << 5
i = 1
while sz > 0x7f:
premsg[i] = (sz & 0x7f) | 0x80
sz >>= 7
i += 1
premsg[i] = sz
self.sock.write(premsg, i + 2)
self.sock.write(msg)
#print(hex(len(msg)), hexlify(msg, ":"))
self._send_str(self.client_id)
if self.lw_topic:
self._send_str(self.lw_topic)
self._send_str(self.lw_msg)
if self.user is not None:
self._send_str(self.user)
self._send_str(self.pswd)
resp = self.sock.read(4)
assert resp[0] == 0x20 and resp[1] == 0x02
if resp[3] != 0:
raise MQTTException(resp[3])
return resp[2] & 1
def disconnect(self):
self.sock.write(b"xe0 ")
self.sock.close()
def ping(self):
self.sock.write(b"xc0 ")
def publish(self, topic, msg, retain=False, qos=0):
pkt = bytearray(b"x30 ")
pkt[0] |= qos << 1 | retain
sz = 2 + len(topic) + len(msg)
if qos > 0:
sz += 2
assert sz < 2097152
i = 1
while sz > 0x7f:
pkt[i] = (sz & 0x7f) | 0x80
sz >>= 7
i += 1
pkt[i] = sz
#print(hex(len(pkt)), hexlify(pkt, ":"))
self.sock.write(pkt, i + 1)
self._send_str(topic)
if qos > 0:
self.pid += 1
pid = self.pid
struct.pack_into("!H", pkt, 0, pid)
self.sock.write(pkt, 2)
self.sock.write(msg)
if qos == 1:
while 1:
op = self.wait_msg()
if op == 0x40:
sz = self.sock.read(1)
assert sz == b"x02"
rcv_pid = self.sock.read(2)
rcv_pid = rcv_pid[0] << 8 | rcv_pid[1]
if pid == rcv_pid:
return
elif qos == 2:
assert 0
def subscribe(self, topic, qos=0):
assert self.cb is not None, "Subscribe callback is not set"
pkt = bytearray(b"x82 ")
self.pid += 1
struct.pack_into("!BH", pkt, 1, 2 + 2 + len(topic) + 1, self.pid)
#print(hex(len(pkt)), hexlify(pkt, ":"))
self.sock.write(pkt)
self._send_str(topic)
self.sock.write(qos.to_bytes(1, "little"))
while 1:
op = self.wait_msg()
if op == 0x90:
resp = self.sock.read(4)
#print(resp)
assert resp[1] == pkt[2] and resp[2] == pkt[3]
if resp[3] == 0x80:
raise MQTTException(resp[3])
return
# Wait for a single incoming MQTT message and process it.
# Subscribed messages are delivered to a callback previously
# set by .set_callback() method. Other (internal) MQTT
# messages processed internally.
def wait_msg(self):
res = self.sock.read(1)
self.sock.setblocking(True)
if res is None:
return None
if res == b"":
raise OSError(-1)
if res == b"xd0": # PINGRESP
sz = self.sock.read(1)[0]
assert sz == 0
return None
op = res[0]
if op & 0xf0 != 0x30:
return op
sz = self._recv_len()
topic_len = self.sock.read(2)
topic_len = (topic_len[0] << 8) | topic_len[1]
topic = self.sock.read(topic_len)
sz -= topic_len + 2
if op & 6:
pid = self.sock.read(2)
pid = pid[0] << 8 | pid[1]
sz -= 2
msg = self.sock.read(sz)
self.cb(topic, msg)
if op & 6 == 2:
pkt = bytearray(b"x40x02 ")
struct.pack_into("!H", pkt, 2, pid)
self.sock.write(pkt)
elif op & 6 == 4:
assert 0
# Checks whether a pending message from server is available.
# If not, returns immediately with None. Otherwise, does
# the same processing as wait_msg.
def check_msg(self):
self.sock.setblocking(False)
return self.wait_msg()
A. Télécharger la bibliothèque umqttsimple avec uPyCraft IDE
1. Créez un nouveau fichier en appuyant sur le Nouveau fichier bouton.

2. Copiez le umqttsimple le code de la bibliothèque dedans. Vous pouvez accéder au umqttsimple code de la bibliothèque dans le lien suivant :
3. Enregistrez le fichier en appuyant sur le Sauvegarder bouton.

4. Appelez ce nouveau fichier « umqttsimple.py » et appuyez sur d’accord.

5. Clique le Télécharger et exécuter bouton.

6. Le fichier doit être enregistré sur le appareil dossier avec le nom « umqttsimple.py» comme le montre la figure ci-dessous.

Maintenant, vous pouvez utiliser les fonctionnalités de la bibliothèque dans votre code en important la bibliothèque.
B. Télécharger la bibliothèque umqttsimple avec Thonny IDE
1. Copiez le code de la bibliothèque dans un nouveau fichier. le Le code de la bibliothèque umqttsimple peut être trouvé ici.
2. Aller à Déposer > Enregistrer sous…

3. Sélectionnez enregistrer dans « Périphérique MicroPython » :

4. Nommez votre fichier comme umqttsimple.py et appuyez sur le bouton OK :

Et c’est tout. La bibliothèque a été téléchargée sur votre tableau. Pour vous assurer qu’il a été téléchargé avec succès, accédez à Fichier > Enregistrer sous… et sélectionnez le périphérique MicroPython. Votre fichier doit y figurer :

Après avoir téléchargé la bibliothèque sur votre tableau, vous pouvez utiliser les fonctionnalités de la bibliothèque dans votre code en important la bibliothèque.
Bibliothèque MicroPython BME280
La bibliothèque à lire à partir du capteur BME280 ne fait pas partie par défaut de la bibliothèque MicroPython standard. Vous devez donc télécharger la bibliothèque suivante sur votre carte ESP32/ESP8266 (enregistrez-la sous le nom BME280.py).
from machine import I2C
import time
# BME280 default address.
BME280_I2CADDR = 0x76
# Operating Modes
BME280_OSAMPLE_1 = 1
BME280_OSAMPLE_2 = 2
BME280_OSAMPLE_4 = 3
BME280_OSAMPLE_8 = 4
BME280_OSAMPLE_16 = 5
# BME280 Registers
BME280_REGISTER_DIG_T1 = 0x88 # Trimming parameter registers
BME280_REGISTER_DIG_T2 = 0x8A
BME280_REGISTER_DIG_T3 = 0x8C
BME280_REGISTER_DIG_P1 = 0x8E
BME280_REGISTER_DIG_P2 = 0x90
BME280_REGISTER_DIG_P3 = 0x92
BME280_REGISTER_DIG_P4 = 0x94
BME280_REGISTER_DIG_P5 = 0x96
BME280_REGISTER_DIG_P6 = 0x98
BME280_REGISTER_DIG_P7 = 0x9A
BME280_REGISTER_DIG_P8 = 0x9C
BME280_REGISTER_DIG_P9 = 0x9E
BME280_REGISTER_DIG_H1 = 0xA1
BME280_REGISTER_DIG_H2 = 0xE1
BME280_REGISTER_DIG_H3 = 0xE3
BME280_REGISTER_DIG_H4 = 0xE4
BME280_REGISTER_DIG_H5 = 0xE5
BME280_REGISTER_DIG_H6 = 0xE6
BME280_REGISTER_DIG_H7 = 0xE7
BME280_REGISTER_CHIPID = 0xD0
BME280_REGISTER_VERSION = 0xD1
BME280_REGISTER_SOFTRESET = 0xE0
BME280_REGISTER_CONTROL_HUM = 0xF2
BME280_REGISTER_CONTROL = 0xF4
BME280_REGISTER_CONFIG = 0xF5
BME280_REGISTER_PRESSURE_DATA = 0xF7
BME280_REGISTER_TEMP_DATA = 0xFA
BME280_REGISTER_HUMIDITY_DATA = 0xFD
class Device:
"""Class for communicating with an I2C device.
Allows reading and writing 8-bit, 16-bit, and byte array values to
registers on the device."""
def __init__(self, address, i2c):
"""Create an instance of the I2C device at the specified address using
the specified I2C interface object."""
self._address = address
self._i2c = i2c
def writeRaw8(self, value):
"""Write an 8-bit value on the bus (without register)."""
value = value & 0xFF
self._i2c.writeto(self._address, value)
def write8(self, register, value):
"""Write an 8-bit value to the specified register."""
b=bytearray(1)
b[0]=value & 0xFF
self._i2c.writeto_mem(self._address, register, b)
def write16(self, register, value):
"""Write a 16-bit value to the specified register."""
value = value & 0xFFFF
b=bytearray(2)
b[0]= value & 0xFF
b[1]= (value>>8) & 0xFF
self.i2c.writeto_mem(self._address, register, value)
def readRaw8(self):
"""Read an 8-bit value on the bus (without register)."""
return int.from_bytes(self._i2c.readfrom(self._address, 1),'little') & 0xFF
def readU8(self, register):
"""Read an unsigned byte from the specified register."""
return int.from_bytes(
self._i2c.readfrom_mem(self._address, register, 1),'little') & 0xFF
def readS8(self, register):
"""Read a signed byte from the specified register."""
result = self.readU8(register)
if result > 127:
result -= 256
return result
def readU16(self, register, little_endian=True):
"""Read an unsigned 16-bit value from the specified register, with the
specified endianness (default little endian, or least significant byte
first)."""
result = int.from_bytes(
self._i2c.readfrom_mem(self._address, register, 2),'little') & 0xFFFF
if not little_endian:
result = ((result << 8) & 0xFF00) + (result >> 8)
return result
def readS16(self, register, little_endian=True):
"""Read a signed 16-bit value from the specified register, with the
specified endianness (default little endian, or least significant byte
first)."""
result = self.readU16(register, little_endian)
if result > 32767:
result -= 65536
return result
def readU16LE(self, register):
"""Read an unsigned 16-bit value from the specified register, in little
endian byte order."""
return self.readU16(register, little_endian=True)
def readU16BE(self, register):
"""Read an unsigned 16-bit value from the specified register, in big
endian byte order."""
return self.readU16(register, little_endian=False)
def readS16LE(self, register):
"""Read a signed 16-bit value from the specified register, in little
endian byte order."""
return self.readS16(register, little_endian=True)
def readS16BE(self, register):
"""Read a signed 16-bit value from the specified register, in big
endian byte order."""
return self.readS16(register, little_endian=False)
class BME280:
def __init__(self, mode=BME280_OSAMPLE_1, address=BME280_I2CADDR, i2c=None,
**kwargs):
# Check that mode is valid.
if mode not in [BME280_OSAMPLE_1, BME280_OSAMPLE_2, BME280_OSAMPLE_4,
BME280_OSAMPLE_8, BME280_OSAMPLE_16]:
raise ValueError(
'Unexpected mode value {0}. Set mode to one of '
'BME280_ULTRALOWPOWER, BME280_STANDARD, BME280_HIGHRES, or '
'BME280_ULTRAHIGHRES'.format(mode))
self._mode = mode
# Create I2C device.
if i2c is None:
raise ValueError('An I2C object is required.')
self._device = Device(address, i2c)
# Load calibration values.
self._load_calibration()
self._device.write8(BME280_REGISTER_CONTROL, 0x3F)
self.t_fine = 0
def _load_calibration(self):
self.dig_T1 = self._device.readU16LE(BME280_REGISTER_DIG_T1)
self.dig_T2 = self._device.readS16LE(BME280_REGISTER_DIG_T2)
self.dig_T3 = self._device.readS16LE(BME280_REGISTER_DIG_T3)
self.dig_P1 = self._device.readU16LE(BME280_REGISTER_DIG_P1)
self.dig_P2 = self._device.readS16LE(BME280_REGISTER_DIG_P2)
self.dig_P3 = self._device.readS16LE(BME280_REGISTER_DIG_P3)
self.dig_P4 = self._device.readS16LE(BME280_REGISTER_DIG_P4)
self.dig_P5 = self._device.readS16LE(BME280_REGISTER_DIG_P5)
self.dig_P6 = self._device.readS16LE(BME280_REGISTER_DIG_P6)
self.dig_P7 = self._device.readS16LE(BME280_REGISTER_DIG_P7)
self.dig_P8 = self._device.readS16LE(BME280_REGISTER_DIG_P8)
self.dig_P9 = self._device.readS16LE(BME280_REGISTER_DIG_P9)
self.dig_H1 = self._device.readU8(BME280_REGISTER_DIG_H1)
self.dig_H2 = self._device.readS16LE(BME280_REGISTER_DIG_H2)
self.dig_H3 = self._device.readU8(BME280_REGISTER_DIG_H3)
self.dig_H6 = self._device.readS8(BME280_REGISTER_DIG_H7)
h4 = self._device.readS8(BME280_REGISTER_DIG_H4)
h4 = (h4 << 24) >> 20
self.dig_H4 = h4 | (self._device.readU8(BME280_REGISTER_DIG_H5) & 0x0F)
h5 = self._device.readS8(BME280_REGISTER_DIG_H6)
h5 = (h5 << 24) >> 20
self.dig_H5 = h5 | (
self._device.readU8(BME280_REGISTER_DIG_H5) >> 4 & 0x0F)
def read_raw_temp(self):
"""Reads the raw (uncompensated) temperature from the sensor."""
meas = self._mode
self._device.write8(BME280_REGISTER_CONTROL_HUM, meas)
meas = self._mode << 5 | self._mode << 2 | 1
self._device.write8(BME280_REGISTER_CONTROL, meas)
sleep_time = 1250 + 2300 * (1 << self._mode)
sleep_time = sleep_time + 2300 * (1 << self._mode) + 575
sleep_time = sleep_time + 2300 * (1 << self._mode) + 575
time.sleep_us(sleep_time) # Wait the required time
msb = self._device.readU8(BME280_REGISTER_TEMP_DATA)
lsb = self._device.readU8(BME280_REGISTER_TEMP_DATA + 1)
xlsb = self._device.readU8(BME280_REGISTER_TEMP_DATA + 2)
raw = ((msb << 16) | (lsb << 8) | xlsb) >> 4
return raw
def read_raw_pressure(self):
"""Reads the raw (uncompensated) pressure level from the sensor."""
"""Assumes that the temperature has already been read """
"""i.e. that enough delay has been provided"""
msb = self._device.readU8(BME280_REGISTER_PRESSURE_DATA)
lsb = self._device.readU8(BME280_REGISTER_PRESSURE_DATA + 1)
xlsb = self._device.readU8(BME280_REGISTER_PRESSURE_DATA + 2)
raw = ((msb << 16) | (lsb << 8) | xlsb) >> 4
return raw
def read_raw_humidity(self):
"""Assumes that the temperature has already been read """
"""i.e. that enough delay has been provided"""
msb = self._device.readU8(BME280_REGISTER_HUMIDITY_DATA)
lsb = self._device.readU8(BME280_REGISTER_HUMIDITY_DATA + 1)
raw = (msb << 8) | lsb
return raw
def read_temperature(self):
"""Get the compensated temperature in 0.01 of a degree celsius."""
adc = self.read_raw_temp()
var1 = ((adc >> 3) - (self.dig_T1 << 1)) * (self.dig_T2 >> 11)
var2 = ((
(((adc >> 4) - self.dig_T1) * ((adc >> 4) - self.dig_T1)) >> 12) *
self.dig_T3) >> 14
self.t_fine = var1 + var2
return (self.t_fine * 5 + 128) >> 8
def read_pressure(self):
"""Gets the compensated pressure in Pascals."""
adc = self.read_raw_pressure()
var1 = self.t_fine - 128000
var2 = var1 * var1 * self.dig_P6
var2 = var2 + ((var1 * self.dig_P5) << 17)
var2 = var2 + (self.dig_P4 << 35)
var1 = (((var1 * var1 * self.dig_P3) >> 8) +
((var1 * self.dig_P2) >> 12))
var1 = (((1 << 47) + var1) * self.dig_P1) >> 33
if var1 == 0:
return 0
p = 1048576 - adc
p = (((p << 31) - var2) * 3125) // var1
var1 = (self.dig_P9 * (p >> 13) * (p >> 13)) >> 25
var2 = (self.dig_P8 * p) >> 19
return ((p + var1 + var2) >> 8) + (self.dig_P7 << 4)
def read_humidity(self):
adc = self.read_raw_humidity()
# print 'Raw humidity = {0:d}'.format (adc)
h = self.t_fine - 76800
h = (((((adc << 14) - (self.dig_H4 << 20) - (self.dig_H5 * h)) +
16384) >> 15) * (((((((h * self.dig_H6) >> 10) * (((h *
self.dig_H3) >> 11) + 32768)) >> 10) + 2097152) *
self.dig_H2 + 8192) >> 14))
h = h - (((((h >> 15) * (h >> 15)) >> 7) * self.dig_H1) >> 4)
h = 0 if h < 0 else h
h = 419430400 if h > 419430400 else h
return h >> 12
@property
def temperature(self):
"Return the temperature in degrees."
t = self.read_temperature()
ti = t // 100
td = t - ti * 100
return "{}.{:02d}C".format(ti, td)
@property
def pressure(self):
"Return the temperature in hPa."
p = self.read_pressure() // 256
pi = p // 100
pd = p - pi * 100
return "{}.{:02d}hPa".format(pi, pd)
@property
def humidity(self):
"Return the humidity in percent."
h = self.read_humidity()
hi = h // 1024
hd = h * 100 // 1024 - hi * 100
return "{}.{:02d}%".format(hi, hd)
Schéma : ESP32 avec BME280
Câbler le Capteur BME280 à la carte de développement ESP32 comme indiqué dans le schéma suivant.

Apprenez à utiliser les GPIO ESP32 avec notre guide : Référence de brochage ESP32 : Quelles broches GPIO devriez-vous utiliser ?
Schéma : ESP8266 NodeMCU avec BME280
Si vous utilisez un ESP8266 NodeMCU, suivez plutôt le schéma suivant.

Apprenez à utiliser les GPIO ESP8266 avec notre guide : Référence de brochage ESP8266 : Quelles broches GPIO devriez-vous utiliser ?
Code
Après avoir téléchargé les bibliothèques sur l’ESP32 ou l’ESP8266, copiez le code suivant dans le main.py déposer. Il publie la température, l’humidité et la pression sur le esp/bme280/température, esp/bme280/humidité et esp/bme280/pression sujets toutes les 5 secondes.
# Complete project details at https://Raspberryme.com/micropython-mqtt-publish-bme280-esp32-esp8266/
import time
from umqttsimple import MQTTClient
import ubinascii
import machine
import micropython
import network
import esp
import BME280
from machine import Pin, I2C
esp.osdebug(None)
import gc
gc.collect()
ssid = 'REPLACE_WITH_YOUR_SSID'
password = 'REPLACE_WITH_YOUR_PASSWORD'
mqtt_server="192.168.1.XXX"
#EXAMPLE IP ADDRESS
#mqtt_server="192.168.1.106"
client_id = ubinascii.hexlify(machine.unique_id())
topic_pub_temp = b'esp/bme280/temperature'
topic_pub_hum = b'esp/bme280/humidity'
topic_pub_pres = b'esp/bme280/pressure'
last_message = 0
message_interval = 5
station = network.WLAN(network.STA_IF)
station.active(True)
station.connect(ssid, password)
while station.isconnected() == False:
pass
print('Connection successful')
# ESP32 - Pin assignment
i2c = I2C(scl=Pin(22), sda=Pin(21), freq=10000)
# ESP8266 - Pin assignment
#i2c = I2C(scl=Pin(5), sda=Pin(4), freq=10000)
bme = BME280.BME280(i2c=i2c)
def connect_mqtt():
global client_id, mqtt_server
client = MQTTClient(client_id, mqtt_server)
#client = MQTTClient(client_id, mqtt_server, user=your_username, password=your_password)
client.connect()
print('Connected to %s MQTT broker' % (mqtt_server))
return client
def restart_and_reconnect():
print('Failed to connect to MQTT broker. Reconnecting...')
time.sleep(10)
machine.reset()
def read_bme_sensor():
try:
temp = b'%s' % bme.temperature[:-1]
#temp = (b'{0:3.1f},'.format((bme.read_temperature()/100) * (9/5) + 32))
hum = b'%s' % bme.humidity[:-1]
pres = b'%s'% bme.pressure[:-3]
return temp, hum, pres
#else:
# return('Invalid sensor readings.')
except OSError as e:
return('Failed to read sensor.')
try:
client = connect_mqtt()
except OSError as e:
restart_and_reconnect()
while True:
try:
if (time.time() - last_message) > message_interval:
temp, hum, pres = read_bme_sensor()
print(temp)
print(hum)
print(pres)
client.publish(topic_pub_temp, temp)
client.publish(topic_pub_hum, hum)
client.publish(topic_pub_pres, pres)
last_message = time.time()
except OSError as e:
restart_and_reconnect()
Comment fonctionne le code
Importez les bibliothèques suivantes :
import time
from umqttsimple import MQTTClient
import ubinascii
import machine
import micropython
import network
import esp
import BME280
from machine import Pin, I2C
Dans les variables suivantes, vous devez entrer vos informations d’identification réseau et l’adresse IP de votre courtier.
ssid = 'REPLACE_WITH_YOUR_SSID'
password = 'REPLACE_WITH_YOUR_PASSWORD'
mqtt_server="REPLACE_WITH_YOUR_MQTT_BROKER_IP"
Par exemple, l’adresse IP de notre courtier est : 192.168.1.106.
mqtt_server="192.168.1.106"
Noter: lisez ce tutoriel pour voir comment obtenir l’adresse IP de votre courtier.
Pour créer un client MQTT, nous devons obtenir l’ID unique ESP. C’est ce que nous faisons dans la ligne suivante (elle est enregistrée sur le identité du client variable).
client_id = ubinascii.hexlify(machine.unique_id())
Ensuite, créez les sujets dans lesquels vous souhaitez que votre ESP publie. Dans notre exemple, il publiera la température sur le esp/bme280/température sujet, humidité sur le esp/bme280/humidité sujet et la pression sur le esp/bme280/pression sujet.
topic_pub_temp = b'esp/bme280/temperature'
topic_pub_hum = b'esp/bme280/humidity'
topic_pub_pres = b'esp/bme280/pressure'
Ensuite, créez les variables suivantes :
last_message = 0
message_interval = 5
le Dernier message La variable sera conservée la dernière fois qu’un message a été envoyé. le intervalle_message est le temps entre chaque message envoyé. Ici, nous le réglons sur 5 secondes (cela signifie qu’un nouveau message sera envoyé toutes les 5 secondes). Vous pouvez le changer si vous voulez.
Après cela, connectez l’ESP à votre réseau local.
station = network.WLAN(network.STA_IF)
station.active(True)
station.connect(ssid, password)
while station.isconnected() == False:
pass
print('Connection successful')
Créé un i2c instance sur les broches ESP32 I2C pour communiquer avec le capteur BME280 :
i2c = I2C(scl=Pin(22), sda=Pin(21), freq=10000)
Si vous utilisez un ESP8266, utilisez plutôt la ligne suivante (pour utiliser les broches I2C par défaut de l’ESP8266).
#i2c = I2C(scl=Pin(5), sda=Pin(4), freq=10000)
Créez une instance BME280 sur les broches ESP I2C :
bme = BME280.BME280(i2c=i2c)
Connectez-vous au courtier MQTT
le connect_mqtt() La fonction crée un client MQTT et se connecte à votre courtier.
def connect_mqtt():
global client_id, mqtt_server
client = MQTTClient(client_id, mqtt_server)
#client = MQTTClient(client_id, mqtt_server, user=your_username, password=your_password)
client.connect()
print('Connected to %s MQTT broker' % (mqtt_server))
return client
Si votre courtier MQTT requiert un nom d’utilisateur et un mot de passe, vous devez utiliser la ligne suivante pour transmettre le nom d’utilisateur et le mot de passe de votre courtier comme arguments.
client = MQTTClient(client_id, mqtt_server, user=your_username, password=your_password)
Redémarrer et se reconnecter
le restart_and_reconnect() La fonction réinitialise la carte ESP32/ESP8266. Cette fonction sera appelée si nous ne sommes pas en mesure de publier les lectures via MQTT au cas où le courtier se déconnecterait.
def restart_and_reconnect():
print('Failed to connect to MQTT broker. Reconnecting...')
time.sleep(10)
machine.reset()
Lire le capteur BME280
Nous avons créé une fonction appelée read_bme_sensor() qui renvoie les lectures actuelles de température, d’humidité et de pression du capteur BME280 et gère toutes les exceptions, au cas où nous ne serions pas en mesure d’obtenir les lectures du capteur.
def read_bme_sensor():
try:
temp = b'%s' % bme.temperature[:-1]
#temp = (b'{0:3.1f},'.format((bme.read_temperature()/100) * (9/5) + 32))
hum = b'%s' % bme.humidity[:-1]
pres = b'%s'% bme.pressure[:-3]
return temp, hum, pres
#else:
# return('Invalid sensor readings.')
except OSError as e:
return('Failed to read sensor.')
En savoir plus sur l’obtention des lectures du capteur BME280 : MicroPython : BME280 avec ESP32 et ESP8266 (pression, température, humidité)
Publication de messages MQTT
Dans la boucle while, nous publions de nouvelles lectures BME280 toutes les 5 secondes.
Tout d’abord, nous vérifions s’il est temps d’obtenir de nouvelles lectures :
if (time.time() - last_message) > message_interval:
Si c’est le cas, demandez de nouvelles lectures au capteur BME280 en appelant le read_bme_sensor() une fonction. La température est enregistrée sur le température variable, l’humidité est enregistrée sur le Hum variable et la pression sur le presse variable.
temp, hum, pres = read_bme_sensor()
Enfin, publiez les lectures en utilisant le publier() méthode sur le client objet. le publier() La méthode accepte comme arguments le sujet et le message, comme suit :
client.publish(topic_pub_temp, temp)
client.publish(topic_pub_hum, hum)
client.publish(topic_pub_pres, pres)
Enfin, mettez à jour l’heure à laquelle le dernier message a été envoyé :
last_message = time.time()
Si l’ESP32 ou l’ESP8266 se déconnecte du courtier et que nous ne sommes pas en mesure de publier les lectures, appelez le restart_and_reconnect() fonction pour réinitialiser la carte ESP et essayer de vous reconnecter au courtier.
except OSError as e:
restart_and_reconnect()
Après avoir téléchargé le code, vous devriez obtenir de nouvelles lectures de capteur sur la coque toutes les 5 secondes.
Maintenant, passez à la section suivante pour préparer Node-RED à recevoir les lectures que l’ESP publie.
Préparation du tableau de bord Node-RED
L’ESP32 ou l’ESP8266 publie des relevés de température toutes les 10 secondes sur le esp/bme280/température, esp/bme280/humidité et esp/bme280/pression les sujets. Désormais, vous pouvez utiliser n’importe quel tableau de bord prenant en charge MQTT ou tout autre appareil prenant en charge MQTT pour vous abonner à ces sujets et recevoir les lectures.
À titre d’exemple, nous allons créer un flux simple à l’aide de Node-RED pour vous abonner à ces sujets et afficher les lectures sur les jauges.
Si vous n’avez pas installé Node-RED, suivez les tutoriels suivants :
Après avoir exécuté Node-RED sur votre Raspberry Pi, accédez à votre adresse IP Raspberry Pi suivie de :1880.
http://raspberry-pi-ip-address:1880
L’interface Node-RED devrait s’ouvrir. Faites glisser trois nœuds MQTT dans les nœuds et trois nœuds de jauge vers le flux.

Cliquez sur le nœud MQTT et modifiez ses propriétés.

Le champ Serveur fait référence au courtier MQTT. Dans notre cas, le courtier MQTT est le Raspberry Pi, il est donc défini sur localhost:1883. Si vous utilisez un courtier Cloud MQTT, vous devez modifier ce champ.
Insérez le sujet auquel vous souhaitez vous abonner et la QoS. Ce nœud MQTT précédent est abonné au esp/bme280/température sujet.
Cliquez sur l’autre MQTT dans les nœuds et modifiez ses propriétés avec le même serveur, mais pour les autres rubriques : esp/bme280/humidité et esp/bme280/pression.
Cliquez sur les nœuds de la jauge et modifiez ses propriétés pour chaque lecture. Le nœud suivant est défini pour les lectures de température. Modifiez l’autre nœud du graphique pour les lectures d’humidité.

Câblez vos nœuds comme indiqué ci-dessous :

Enfin, déployez votre flux (appuyez sur le bouton en haut à droite).

Alternativement, vous pouvez aller à Menu > Importer et copiez ce qui suit dans votre Presse-papiers pour créer votre flux Node-RED.
[{"id":"5a45b8da.52b0d8","type":"mqtt in","z":"b01416d3.f69f38","name":"","topic":"esp/bme280/temperature","qos":"1","datatype":"auto","broker":"8db3fac0.99dd48","x":310,"y":60,"wires":[["3042e15e.80a4ee"]]},{"id":"3042e15e.80a4ee","type":"ui_gauge","z":"b01416d3.f69f38","name":"","group":"37de8fe8.46846","order":2,"width":0,"height":0,"gtype":"gage","title":"Temperature","label":"ºC","format":"{{value}}","min":0,"max":"40","colors":["#00b500","#f7df09","#ca3838"],"seg1":"","seg2":"","x":590,"y":60,"wires":[]},{"id":"8ff168f0.0c74a8","type":"mqtt in","z":"b01416d3.f69f38","name":"","topic":"esp/bme280/humidity","qos":"1","datatype":"auto","broker":"8db3fac0.99dd48","x":300,"y":140,"wires":[["29251f29.6687c"]]},{"id":"29251f29.6687c","type":"ui_gauge","z":"b01416d3.f69f38","name":"","group":"37de8fe8.46846","order":2,"width":0,"height":0,"gtype":"gage","title":"Humidity","label":"%","format":"{{value}}","min":"30","max":"100","colors":["#53a4e6","#1d78a9","#4e38c9"],"seg1":"","seg2":"","x":580,"y":140,"wires":[]},{"id":"294f7eea.999d72","type":"mqtt in","z":"b01416d3.f69f38","name":"","topic":"esp/bme280/pressure","qos":"1","datatype":"auto","broker":"8db3fac0.99dd48","x":300,"y":220,"wires":[["58610d70.bb9764"]]},{"id":"58610d70.bb9764","type":"ui_gauge","z":"b01416d3.f69f38","name":"","group":"37de8fe8.46846","order":4,"width":0,"height":0,"gtype":"gage","title":"Pressure","label":"hPa","format":"{{value}}","min":0,"max":"1200","colors":["#b366ff","#8000ff","#440088"],"seg1":"","seg2":"","x":580,"y":220,"wires":[]},{"id":"8db3fac0.99dd48","type":"mqtt-broker","z":"","name":"","broker":"localhost","port":"1883","clientid":"","usetls":false,"compatmode":false,"keepalive":"60","cleansession":true,"birthTopic":"","birthQos":"0","birthPayload":"","closeTopic":"","closeQos":"0","closePayload":"","willTopic":"","willQos":"0","willPayload":""},{"id":"37de8fe8.46846","type":"ui_group","z":"","name":"BME280","tab":"53b8c8f9.cfbe48","order":1,"disp":true,"width":"6","collapse":false},{"id":"53b8c8f9.cfbe48","type":"ui_tab","z":"","name":"Home","icon":"dashboard","order":2,"disabled":false,"hidden":false}]
Manifestation
Accédez à votre adresse IP Raspberry Pi suivie de :1880/ui.
http://raspberry-pi-ip-address:1880/ui
Vous devriez avoir accès aux relevés actuels de température, d’humidité et de pression du BME280 sur le tableau de bord. Vous pouvez utiliser d’autres nœuds de type tableau de bord pour afficher les lectures de différentes manières.

C’est ça! Vos cartes ESP32 ou ESP8266 publient les lectures de température, d’humidité et de pression BME280 sur Node-RED via MQTT à l’aide de MicroPython.
Conclusion
MQTT est un excellent protocole de communication pour échanger de petites quantités de données entre les appareils IoT. Dans ce didacticiel, vous avez appris à publier les lectures d’un capteur BME280 avec l’ESP32 et l’ESP8266 à l’aide de MicroPython sur différents sujets MQTT. Ensuite, vous pouvez utiliser n’importe quel appareil ou plate-forme domotique pour vous abonner à ces sujets et recevoir les lectures.
Au lieu d’un capteur BME280, vous pouvez utiliser n’importe quel autre capteur comme le capteur DHT11 ou DHT22 ou le capteur de température DS18B20.
Nous avons d’autres projets/tutoriels liés au capteur BME280 qui pourraient également vous plaire :
Apprenez-en plus sur MicroPython avec notre livre électronique : Programmation MicroPython à l’aide d’ESP32/ESP8266.