Sommaire
Objectif
Récupérer la température, le taux d’humidité ainsi que la pression atmosphérique d’un BME/BP280 et l’envoyer sur le serveur domoticz avec un Raspberry Zero W
Matériel
- Raspeberry Zero W
- Capteur BMP280 https://www.amazon.fr/gp/product/B07KY8WY4M/ref=ppx_yo_dt_b_asin_title_o07_s00?ie=UTF8&psc=1 (par exemple mais moins cher sur AliExpress)
Montage
![](https://journaldunarchiviste.fr/wp-content/uploads/2020/04/20200420_185718-225x300.jpg)
- GPIO2 = alim
- GPIO39 = grnd
- GPIO3 = SDA
- GPIO5 = SCL
![](https://journaldunarchiviste.fr/wp-content/uploads/2020/04/r0WBMP280-1024x642.png)
Voici un lien l’organisation des GPIO : https://pinout.xyz/pinout/pin1_3v3_power#
Code
Pré-requis
Au préalable installer i2c-tools : sudo apt-get update
sudo apt-get install i2c-tools
Puis, si ce n’est pas déjà fait, activer l’usage du i2c sur raspbian, faire sudo raspi-config puis se rendre dans le menu 5 puis P5.
![](https://journaldunarchiviste.fr/wp-content/uploads/2020/04/raspi_config_1.png)
![](https://journaldunarchiviste.fr/wp-content/uploads/2020/04/raspi_config_2.png)
enfin, sudo i2cdetect -y 1
, ce qui devrait vous mettre quelque chose qui ressemble à l’image suivante :
![](https://journaldunarchiviste.fr/wp-content/uploads/2020/04/i2c_1.png)
A partir de là votre BMP communique avec le raspberry, reste à comprendre.
Lire le BMP280
J’ai récupéré ce script à cette adresse : https://bitbucket.org/MattHawkinsUK/rpispy-misc/raw/master/python/bme280.py
#!/usr/bin/python # -------------------------------------- # ___ ___ _ ____ # / _ \/ _ \(_) __/__ __ __ # / , _/ ___/ /\ \/ _ \/ // / # /_/|_/_/ /_/___/ .__/\_, / # /_/ /___/ # # bme280.py # Read data from a digital pressure sensor. # # Official datasheet available from : # https://www.bosch-sensortec.com/bst/products/all_products/bme280 # # Author : Matt Hawkins # Date : 25/07/2016 # # http://www.raspberrypi-spy.co.uk/ # https://bitbucket.org/MattHawkinsUK/rpispy-misc/raw/master/python/bme280.py # -------------------------------------- import smbus import time from ctypes import c_short # Default device I2C address DEVICE = 0x76 # Rev 2 Pi, Pi 0, Pi 2 & Pi 3 uses bus 1 # Rev 1 Pi uses bus 0 bus = smbus.SMBus(1) def getShort(data, index): # return two bytes from data as a signed 16-bit value return c_short((data[index + 1] << 8) + data[index]).value def getUShort(data, index): # return two bytes from data as an unsigned 16-bit value return (data[index + 1] << 8) + data[index] def getChar(data, index): # return one byte from data as a signed char result = data[index] if result > 127: result -= 256 return result def getUChar(data, index): # return one byte from data as an unsigned char result = data[index] & 0xFF return result def readBME280ID(addr=DEVICE): # Chip ID Register Address REG_ID = 0xD0 (chip_id, chip_version) = bus.read_i2c_block_data(addr, REG_ID, 2) return (chip_id, chip_version) def readBME280All(addr=DEVICE): # Register Addresses REG_DATA = 0xF7 REG_CONTROL = 0xF4 REG_CONTROL_HUM = 0xF2 # Oversample setting - page 27 OVERSAMPLE_TEMP = 2 OVERSAMPLE_PRES = 2 MODE = 1 # Oversample setting for humidity register - page 26 OVERSAMPLE_HUM = 2 bus.write_byte_data(addr, REG_CONTROL_HUM, OVERSAMPLE_HUM) control = OVERSAMPLE_TEMP << 5 | OVERSAMPLE_PRES << 2 | MODE bus.write_byte_data(addr, REG_CONTROL, control) # Read blocks of calibration data from EEPROM # See Page 22 data sheet cal1 = bus.read_i2c_block_data(addr, 0x88, 24) cal2 = bus.read_i2c_block_data(addr, 0xA1, 1) cal3 = bus.read_i2c_block_data(addr, 0xE1, 7) # Convert byte data to word values dig_T1 = getUShort(cal1, 0) dig_T2 = getShort(cal1, 2) dig_T3 = getShort(cal1, 4) dig_P1 = getUShort(cal1, 6) dig_P2 = getShort(cal1, 8) dig_P3 = getShort(cal1, 10) dig_P4 = getShort(cal1, 12) dig_P5 = getShort(cal1, 14) dig_P6 = getShort(cal1, 16) dig_P7 = getShort(cal1, 18) dig_P8 = getShort(cal1, 20) dig_P9 = getShort(cal1, 22) dig_H1 = getUChar(cal2, 0) dig_H2 = getShort(cal3, 0) dig_H3 = getUChar(cal3, 2) dig_H4 = getChar(cal3, 3) dig_H4 = (dig_H4 << 24) >> 20 dig_H4 = dig_H4 | (getChar(cal3, 4) & 0x0F) dig_H5 = getChar(cal3, 5) dig_H5 = (dig_H5 << 24) >> 20 dig_H5 = dig_H5 | (getUChar(cal3, 4) >> 4 & 0x0F) dig_H6 = getChar(cal3, 6) # Wait in ms (Datasheet Appendix B: # Measurement time and current calculation) wait_time = 1.25 + (2.3 * OVERSAMPLE_TEMP) +\ ((2.3 * OVERSAMPLE_PRES) + 0.575) + ((2.3 * OVERSAMPLE_HUM) + 0.575) # Wait the required time time.sleep(wait_time / 1000) # Read temperature/pressure/humidity data = bus.read_i2c_block_data(addr, REG_DATA, 8) pres_raw = (data[0] << 12) | (data[1] << 4) | (data[2] >> 4) temp_raw = (data[3] << 12) | (data[4] << 4) | (data[5] >> 4) hum_raw = (data[6] << 8) | data[7] # Refine temperature var1 = ((((temp_raw >> 3) - (dig_T1 << 1))) * (dig_T2)) >> 11 var2 = (((((temp_raw >> 4) - (dig_T1)) * ((temp_raw >> 4) - (dig_T1))) >> 12) * (dig_T3)) >> 14 t_fine = var1 + var2 temperature = float(((t_fine * 5) + 128) >> 8) # Refine pressure and adjust for temperature var1 = t_fine / 2.0 - 64000.0 var2 = var1 * var1 * dig_P6 / 32768.0 var2 = var2 + var1 * dig_P5 * 2.0 var2 = var2 / 4.0 + dig_P4 * 65536.0 var1 = (dig_P3 * var1 * var1 / 524288.0 + dig_P2 * var1) / 524288.0 var1 = (1.0 + var1 / 32768.0) * dig_P1 if var1 == 0: pressure = 0 else: pressure = 1048576.0 - pres_raw pressure = ((pressure - var2 / 4096.0) * 6250.0) / var1 var1 = dig_P9 * pressure * pressure / 2147483648.0 var2 = pressure * dig_P8 / 32768.0 pressure = pressure + (var1 + var2 + dig_P7) / 16.0 # Refine humidity humidity = t_fine - 76800.0 humidity = (hum_raw - (dig_H4 * 64.0 + dig_H5 / 16384.0 * humidity))\ * (dig_H2 / 65536.0 * (1.0 + dig_H6 / 67108864.0 * humidity * (1.0 + dig_H3 / 67108864.0 * humidity))) humidity = humidity * (1.0 - dig_H1 * humidity / 524288.0) if humidity > 100: humidity = 100 elif humidity < 0: humidity = 0 return temperature / 100.0, pressure / 100.0, humidity def main(): temperature, pressure, humidity = readBME280All() weather = [temperature, pressure, humidity] return weather if __name__ == "__main__": (chip_id, chip_version) = readBME280ID() print("Chip ID :", chip_id) print("Version :", chip_version) temperature, pressure, humidity = readBME280All() print("Temperature : ", temperature, "C") print("Pressure : ", pressure, "hPa") print("Humidity : ", humidity, "%")
Vous noterez le DEVICE = 0x76
ligne 27 qui correspond à ce qu’il y avait d’affiché avec la commande sudo i2cdetect -y 1
.
Avant de le faire fonctionner, n’oubliez pas d’installer smbus
à coup de pip install smbus
; une fois que cela est fait vous pouvez faire python bme.py
là où vous avez mis le fichier sur le Raspberry , ce qui vous donnera :
~/bme $ python bme.py ('Chip ID :', 96) ('Version :', 0) ('Temperature : ', 20.34, 'C') ('Pressure : ', 1002.2085705444156, 'hPa') ('Humidity : ', 60.38054404621201, '%')
Donc, une température de 20.34° C, une pression atmosphérique de 1002.20 hPa, et une humidité de 60%. Maintenant, envoyons cela à Domoticz.
Communication avec Domoticz
Toujours le même principe que pour le poulailler ou encore le relai : un fichier send_domoticz avec une tache dans le cron.
#!/usr/bin/python from bme import main from requests.auth import HTTPBasicAuth import requests import sys # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # fonctions # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ def maj_widget(val_url): requete = 'http://' + domoticz_ip + ':' + domoticz_port + val_url # print requete r = requests.get(requete, auth=HTTPBasicAuth(user, password)) if r.status_code != 200: print("Erreur API Domoticz") # 0=Normal # 1=Comfortable # 2=Dry # 3=Wet def humidity_status(val): if 0 <= val <= 75: humidity_status = 0 elif 76 <= val <= 79: humidity_status = 1 elif 80 <= val <= 94: humidity_status = 2 elif 95 <= val <= 100: humidity_status = 3 return humidity_status # 0 = No info # 1 = Sunny # 2 = Partly cloudy # 3 = Cloudy # 4 = Rain def barometer_forecast(val): if val < 1006: weather = 4 elif 1007 <= val <= 1013: weather = 3 elif 1014 <= val <= 1020: weather = 2 elif val > 1020: weather = 1 else: weather = 0 return weather # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # les parametres de Domoticz # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ domoticz_ip = '' domoticz_port = '8080' user = '' password = '' domoticz_idx = '' # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # recuperation des informations des capteurs # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ value = main() temperature = int(value[0]) pressure = int(value[1]) humidity = int(value[2]) hum_stat = humidity_status(humidity) bar_for = barometer_forecast(int(pressure)) if humidity is not None and temperature is not None and pressure is not None: # https://www.domoticz.com/wiki/Domoticz_API/JSON_URL%27s#Temperature.2Fhumidity.2Fbarometer # modele url : /json.htm?type=command¶m=udevice&idx=IDX&nvalue=0& # svalue=TEMP;HUM;HUM_STAT;BAR;BAR_FOR # l URL Domoticz pour le widget virtuel url = '/json.htm?type=command¶m=udevice&idx=' + str(domoticz_idx) url += '&nvalue=0&svalue=' url += str('{0:0.1f};{1:0.1f};{2:0};{3:0.1f};{4:0}').format(temperature, humidity, hum_stat, pressure, bar_for) print(url) maj_widget(url) else: print('Probleme avec la lecture du BME280') sys.exit(1)
Pour l’automatisation avec le cron voir : https://journaldunarchiviste.fr/2019/01/15/domotique-poulailler-connecte-partie-2/#Temperature_et_humidite
Il faut également ajuster la fonction barometer_forecast
; en effet la pression atmosphérique dépend de votre localisation, en particulier de l’altitude, pour plus de renseignement lire : http://leguidemeteo.com/prevoir-le-temps-a-partir-de-son-barometre/
Note : la partie identification nécessite d'avoir configuré son accès à domoticz par un identifiant et un mot de passe.
Configuration domoticz
Il faut créer un capteur virtuel : les explications en capture d’écran
![](https://journaldunarchiviste.fr/wp-content/uploads/2020/04/domo_1-1024x592.png)
Une fois cela fait, il faut créer le dispositif pour le capteur
![](https://journaldunarchiviste.fr/wp-content/uploads/2020/04/domo_2-1024x60.png)
![](https://journaldunarchiviste.fr/wp-content/uploads/2020/04/domo_3.png)
Une fois que cela est fait, on alimente le script send_domoticz.py
avec le bon idx
![](https://journaldunarchiviste.fr/wp-content/uploads/2020/04/domo_4-1024x304.png)
Résultat
En lançant le script avec la commande python send_domo.py
vous aurez un résultat comme celui-ci /json.htm?type=command¶m=udevice&idx=19&nvalue=0&svalue=18.0;66.0;0;1003.0;4
ce qui mettra à jour Domotitcz. Sur l’interface Domoticz, un joli capteur, avec possibilité d’envoyer des notifications via Télégram.
![](https://journaldunarchiviste.fr/wp-content/uploads/2020/04/domo_5.png)
Voici des statistiques sur le mois précédent d’un autre BMP280 installé depuis plus d’un an dans le jardin.
![](https://journaldunarchiviste.fr/wp-content/uploads/2020/04/domo_bmp-1-1024x291.png)
Le code est disponible sur ce dépôt github : https://github.com/fz3p/weatherstation ; cependant il sert également à envoyer les données d’un DHT11.