From 5d7e482b2baaa35a205b06021f282d10bd271cd3 Mon Sep 17 00:00:00 2001 From: Walter Gussmann Date: Sat, 30 Jun 2018 10:53:38 +0200 Subject: [PATCH] Upload files to 'python' --- python/Adafruit_BME280.py | 214 ++++++++++++++++++++++++++++++++++++++ python/README.md | 74 +++++++++++++ python/bme280-messen.py | 21 ++++ 3 files changed, 309 insertions(+) create mode 100644 python/Adafruit_BME280.py create mode 100644 python/README.md create mode 100644 python/bme280-messen.py diff --git a/python/Adafruit_BME280.py b/python/Adafruit_BME280.py new file mode 100644 index 0000000..c2bcda2 --- /dev/null +++ b/python/Adafruit_BME280.py @@ -0,0 +1,214 @@ +# Copyright (c) 2014 Adafruit Industries +# Author: Tony DiCola +# +# Based on the BMP280 driver with BME280 changes provided by +# David J Taylor, Edinburgh (www.satsignal.eu) +# +# Permission is hereby granted, free of charge, to any person obtaining a copy +# of this software and associated documentation files (the "Software"), to deal +# in the Software without restriction, including without limitation the rights +# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +# copies of the Software, and to permit persons to whom the Software is +# furnished to do so, subject to the following conditions: +# +# The above copyright notice and this permission notice shall be included in +# all copies or substantial portions of the Software. +# +# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN +# THE SOFTWARE. +import logging +import time + + +# BME280 default address. +BME280_I2CADDR = 0x77 + +# 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 BME280(object): + def __init__(self, mode=BME280_OSAMPLE_1, address=BME280_I2CADDR, i2c=None, + **kwargs): + self._logger = logging.getLogger('Adafruit_BMP.BMP085') + # 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: + import Adafruit_GPIO.I2C as I2C + i2c = I2C + self._device = i2c.get_i2c_device(address, **kwargs) + # Load calibration values. + self._load_calibration() + self._device.write8(BME280_REGISTER_CONTROL, 0x3F) + self.t_fine = 0.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) + + ''' + print '0xE4 = {0:2x}'.format (self._device.readU8 (BME280_REGISTER_DIG_H4)) + print '0xE5 = {0:2x}'.format (self._device.readU8 (BME280_REGISTER_DIG_H5)) + print '0xE6 = {0:2x}'.format (self._device.readU8 (BME280_REGISTER_DIG_H6)) + + print 'dig_H1 = {0:d}'.format (self.dig_H1) + print 'dig_H2 = {0:d}'.format (self.dig_H2) + print 'dig_H3 = {0:d}'.format (self.dig_H3) + print 'dig_H4 = {0:d}'.format (self.dig_H4) + print 'dig_H5 = {0:d}'.format (self.dig_H5) + print 'dig_H6 = {0:d}'.format (self.dig_H6) + ''' + + 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 = 0.00125 + 0.0023 * (1 << self._mode) + sleep_time = sleep_time + 0.0023 * (1 << self._mode) + 0.000575 + sleep_time = sleep_time + 0.0023 * (1 << self._mode) + 0.000575 + time.sleep(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): + """Gets the compensated temperature in degrees celsius.""" + # float in Python is double precision + UT = float(self.read_raw_temp()) + var1 = (UT / 16384.0 - self.dig_T1 / 1024.0) * float(self.dig_T2) + var2 = ((UT / 131072.0 - self.dig_T1 / 8192.0) * ( + UT / 131072.0 - self.dig_T1 / 8192.0)) * float(self.dig_T3) + self.t_fine = int(var1 + var2) + temp = (var1 + var2) / 5120.0 + return temp + + def read_pressure(self): + """Gets the compensated pressure in Pascals.""" + adc = self.read_raw_pressure() + var1 = self.t_fine / 2.0 - 64000.0 + var2 = var1 * var1 * self.dig_P6 / 32768.0 + var2 = var2 + var1 * self.dig_P5 * 2.0 + var2 = var2 / 4.0 + self.dig_P4 * 65536.0 + var1 = ( + self.dig_P3 * var1 * var1 / 524288.0 + self.dig_P2 * var1) / 524288.0 + var1 = (1.0 + var1 / 32768.0) * self.dig_P1 + if var1 == 0: + return 0 + p = 1048576.0 - adc + p = ((p - var2 / 4096.0) * 6250.0) / var1 + var1 = self.dig_P9 * p * p / 2147483648.0 + var2 = p * self.dig_P8 / 32768.0 + p = p + (var1 + var2 + self.dig_P7) / 16.0 + return p + + def read_humidity(self): + adc = self.read_raw_humidity() + # print 'Raw humidity = {0:d}'.format (adc) + h = self.t_fine - 76800.0 + h = (adc - (self.dig_H4 * 64.0 + self.dig_H5 / 16384.8 * h)) * ( + self.dig_H2 / 65536.0 * (1.0 + self.dig_H6 / 67108864.0 * h * ( + 1.0 + self.dig_H3 / 67108864.0 * h))) + h = h * (1.0 - self.dig_H1 * h / 524288.0) + if h > 100: + h = 100 + elif h < 0: + h = 0 + return h + diff --git a/python/README.md b/python/README.md new file mode 100644 index 0000000..b3de7d4 --- /dev/null +++ b/python/README.md @@ -0,0 +1,74 @@ +# Wetterdaten mit dem Raspberry Pi messen + +**Ziel:** Mit zwei Sensoren und einem Raspberry Pi soll die Temperatur, + Luftdruck und Luftfeuchtigkeit an zwei Stellen (outdoor/indoor9 gemessen werden. + +## Hardware + +- Raspberry Pi 3 (geht auch mit älteren Modellen + WLAN-Modul) +- BOSCH BME280 (Bezugsquelle: watterott.com) +- Adafruit BMP280 (Versuchsweise, ohne Luftfeuchtigkeit) + +![Sensor BME280](../img/bme280.png) + +## Anschluss der Sensoren + +``` + Sensor Raspberry Pi + GND ------- GND + NC ------- + VCC ------- +3.3V + SCL/SCK ------- SCL + SDA/SDI ------- SDA + SD0 ------- * + CS ------- +``` + +Mit SD0 kann die I2C-Adresse geändert werden. Standardmäißg besitzt der Chip +die Adresse 0x77. Wird SD0 auf HIGH gelegt, so ändert sich die Adresse zu 0x76. + +## Software + +Über Adafruit kann eine Bibliothek zu diesem Chip installiert werden. Diese +Bibliothek setzt die Installation von Adafruit_GPIO voraus. Weitere +Informationen über https://github.com/adafruit. + +Mit dieser Bibliothek können die Messdaten einfach eingelesen werden: + +``` +#!/usr/bin/python +# -*- coding: utf-8 -*- + +from Adafruit_BME280 import * +import time +import urllib + +sensor = BME280(mode=BME280_OSAMPLE_8) + +degrees = sensor.read_temperature() +pascals = sensor.read_pressure() +hectopascals = pascals / 100 +humidity = sensor.read_humidity() + +print ("Temperatur (in C) = {0:0.3f} C".format(degrees)) +print ("Luftdruck (in hPa) = {0:0.2f} hPa".format(hectopascals)) +print ("Luftfeuchtigkeit = {0:0.2f} %".format(humidity)) +``` + +## Speicherung der Messdaten auf (externer) Datenbank + +Die gemessenen Werten sollen in einer Datenbank gespeichert werden, die sich +irgendwo auf einem Server befindet. Dazu wird auf diesem Server eine +upload-php-Seite angelegt, über die mit angehängten Parametern die Speicherung +erfolgt (näheres unter mysql). + +Ergänzungen des Pythonprogramms: + +``` +import urllib + +url = "http:///upload.php?m=outdoor&t=" +str(round(degrees, 2)) + "&p=" +str(round(hectopascals, 2)) + "&f=" + str(round(humidity, 2)) +urllib.urlopen(url) +``` + + diff --git a/python/bme280-messen.py b/python/bme280-messen.py new file mode 100644 index 0000000..153435f --- /dev/null +++ b/python/bme280-messen.py @@ -0,0 +1,21 @@ +#!/usr/bin/python +# -*- coding: utf-8 -*- + +from Adafruit_BME280 import * +import urllib + +sensor = BME280(mode=BME280_OSAMPLE_8) + +degrees = sensor.read_temperature() +pascals = sensor.read_pressure() +hectopascals = pascals / 100 +humidity = sensor.read_humidity() + +url = "http:///upload.php?m=outdoor&t=" +str(round(degrees, 2)) + "&p=" +str(round(hectopascals, 2)) + "&f=" + str(round(humidity, 2)) + +urllib.urlopen(url) + +print ("Temperatur (in C) = {0:0.3f} C".format(degrees)) +print ("Luftdruck (in hPa) = {0:0.2f} hPa".format(hectopascals)) +print ("Luftfeuchtigkeit = {0:0.2f} %".format(humidity)) +