Einleitung
(Zurück zum Inhaltsverzeichnis)
Voraussetzung ist, das SNMP, MRTG und der I2C-Bus bereits eingerichtet sind.
Desweiteren habe ich mich an diese (private!) OID-Liste gehalten
Für diese Anleitung musste dieses BME280-Breakout-Board leiden.
Derzeit laufen 2 dieser Boards hier, eines auf einen RPi1B(r2) und eines auf einen RPi2B mit jeweils 2 unterschiedlichen Algorithmen.
Man bekommt vom Breakout-Board 3 Werte:
Temperatur
Luftfeuchtigkeit
Luftdruck
Den ersten Algorithmus findet man hier
und den zweiten hier
Errechnen kann daraus man noch 2 weitere Werte:
Taupunkt
Absolute Feuchte
Auch hier habe ich 2 Algorithmen gefunden, den ersten findet man feuchte.py
und den zweiten hier.
Und hier noch eine Anleitung zum kalibrieren des Feuchtesensors.
Für den Luftdruck könnte vielleicht diese Webseite interessant sein.
Die Client-Software ist zweiteilig, der erste Teil liest den BME280 aus und speichert die Ergebnisse in /tmp.
Der zweite Teil übernimmt die Abfragen mittels SNMP.
Das Auslesen des BME280 erfolgt alle 5 min. über Cron zu einem definierten Zeitpunkt, damit geht man auch Schwierigkeiten mit dem I2C-Bus aus dem Weg.
Der Nachteil ist, das die SD-Karte zusätzlich belastet wird.
Die Software zum Auslesen des BME280
Das erste Python-Script braucht noch eine Library von Adafruit:
sudo apt-get update
sudo apt-get install build-essential python-pip python-dev python-smbus git
git clone https://github.com/adafruit/Adafruit_Python_GPIO.git
cd Adafruit_Python_GPIO
sudo python setup.py install
Jetzt mit:
folgendes Python-Script erstellen:
#!/usr/bin/python
# Copyright (c) 2014 Adafruit Industries
# Author: Tony DiCola
#
# 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.
# coding=utf-8
import sys
import os
import logging
import time
import feuchte
import humid
version = "20170506"
# Kalibrierung
HUM_offset = -2.7
PRESS_offset = 1382
TEMP_offset = -0.900
# 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
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
sensor = BME280 (mode=BME280_OSAMPLE_8)
# print 't_fine = {0:0.3f}'.format (sensor.t_fine)
degrees = (sensor.read_temperature () + TEMP_offset)
pascals = ((sensor.read_pressure () + PRESS_offset) * 10)
humidity = (sensor.read_humidity () + HUM_offset)
# Quelle: https://bitbucket.org/m_reiter/klima
HLf = (feuchte.AF(float(humidity),float(degrees)))
DPf = (feuchte.TD(float(humidity),float(degrees)))
# Quelle: http://www.bitmania.de/index.php?page=247
dewp, awat = (humid.dewpoint(float(degrees),float(humidity)))
DPh = float (dewp)
HLh = float (awat)
def main():
optionen = "Moegliche Optionen:\n version \n all \n snmp \n file \n debug"
# Script mit diversen Optionen abarbeiten
# Ohne Option werden die Optionen ausgegeben
# version = Letztes Aenderungsdatum
# all = Lesbare Anzeige
# snmp = Werte in einzelne (7) Files nach /tmp schreiben
# file = Werte in einem Files nach /tmp schreiben
# debug = Werte fuer snmp aufbereitet (Integerzahlen)
try:
option = sys.argv[1]
except:
print optionen
sys.exit(1)
if option == "version":
print version
elif option == "all":
print 'Temp = {0:0.3f} deg C'.format (degrees)
print 'Pressure = {0:0.2f} hPa'.format (pascals / 1000)
print 'Humidity = {0:0.3f} %'.format (humidity)
print 'Taupunkt = {0:0.3f} deg C'.format (DPf)
print 'Absolute Feuchte = {0:0.3f} g/m^3'.format (HLf)
print 'Taupunkt = {0:0.3f} deg C'.format (DPh)
print 'Absolute Feuchte = {0:0.3f} g/m^3'.format (HLh)
elif option == "debug":
print 'Temp = {0:0.8f}'.format (1000*degrees)
print 'Pressure = {0:0.8f}'.format (pascals / 100)
print 'Humidity = {0:0.8f}'.format (1000*humidity)
print 'Dewpoint 1 = {0:0.8f}'.format (1000*DPf)
print 'Abs. Humidity 1 = {0:0.8f}'.format (1000*HLf)
print 'Dewpoint 2 = {0:0.8f}'.format (1000*DPh)
print 'Abs. Humidity 2 = {0:0.8f}'.format (1000*HLh)
elif option == "snmp":
op = open ('/tmp/temperature_1.snmp', 'w')
op.write ('{0:0.0f}\n'.format (1000*degrees))
op.close ()
op = open ('/tmp/pressure_1.snmp', 'w')
op.write ('{0:0.0f}\n'.format (pascals / 100))
op.close ()
op = open ('/tmp/humidity_rel_1.snmp', 'w')
op.write ('{0:0.0f}\n'.format (1000*humidity))
op.close ()
op = open ('/tmp/dew-point_1_1.snmp', 'w')
op.write ('{0:0.0f}\n'.format (1000*DPf))
op.close ()
op = open ('/tmp/humidity_abs_1_1.snmp', 'w')
op.write ('{0:0.0f}\n'.format (1000*HLf))
op.close ()
op = open ('/tmp/dew-point_1_2.snmp', 'w')
op.write ('{0:0.0f}\n'.format (1000*DPh))
op.close ()
op = open ('/tmp/humidity_abs_1_2.snmp', 'w')
op.write ('{0:0.0f}\n'.format (1000*HLh))
op.close ()
elif option == "file":
snmp = str(1000*degrees) + "\n" + str(humidity * 1000) + "\n" + str(pascals / 100) + "\n" + str(DPf * 1000) + "\n" + str(HLf * 1000) + "\n" + str(DPh * 1000) + "\n" + str(HLh * 1000)
op = open('/tmp/environment_1.snmp', 'w')
op.write (snmp)
op.close()
if __name__ == '__main__':
main()
#EOF
Alles anzeigen
Das zweite Python-Script:
#!/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/
#
#--------------------------------------
import smbus
import time
import sys
import os
import feuchte
import humid
from ctypes import c_short
from ctypes import c_byte
from ctypes import c_ubyte
version = "20170507"
# Kalibrierung
HUM_offset = -2.5
PRESS_offset = 13.87
TEMP_offset = -0.87
DEVICE = 0x77 # Default device I2C address
bus = smbus.SMBus(1) # Rev 2 Pi, Pi 2 & Pi 3 uses bus 1
# Rev 1 Pi uses bus 0
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_CONFIG = 0xF5
REG_CONTROL_HUM = 0xF2
REG_HUM_MSB = 0xFD
REG_HUM_LSB = 0xFE
# 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)
time.sleep(wait_time/1000) # Wait the required time
# 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^M 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^M
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():
optionen = "Moegliche Optionen:\n version \n all \n snmp \n file \n debug"
# Script mit diversen Optionen abarbeiten
# Ohne Option werden die Optionen ausgegeben
# version = Letztes Aenderungsdatum
# all = Lesbare Anzeige
# snmp = Werte in einzelne (7) Files nach /tmp schreiben
# file = Werte in einem File nach /tmp schreiben
# debug = Werte fuer snmp aufbereitet (Integerzahlen)
try:
option = sys.argv[1]
except:
print optionen
sys.exit(1)
temperature,pressure,humidity = readBME280All()
(chip_id, chip_version) = readBME280ID()
temperature = (temperature + TEMP_offset)
pressure = ((pressure + PRESS_offset) * 10)
humidity = (humidity + HUM_offset)
# Quella: https://biteucket.org/m_reiter/klima
HLf = (feuchte.AF(float(humidity),float(temperature)))
DPf = (feuchte.TD(float(humidity),float(temperature)))
# Quelle: http://www.bitmania.de/index.php?page=247
dewp, awat = (humid.dewpoint(float(temperature),float(humidity)))
DPh = float (dewp)
HLh = float (awat)
if option == "version":
print version
elif option == "all":
# (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 /10), "hPa"
print "Humidity = ", humidity, "%"
print 'Taupunkt = {0:0.3f} deg C'.format (DPf)
print 'Absolute Feuchte = {0:0.3f} g/m^3'.format (HLf)
print 'Taupunkt = {0:0.3f} deg C'.format (DPh)
print 'Absolute Feuchte = {0:0.3f} g/m^3'.format (HLh)
elif option == "debug":
print 'Temp = {0:0.8f}'.format (1000*temperature)
print 'Pressure = {0:0.8f}'.format (pressure)
print 'Humidity = {0:0.8f}'.format (1000*humidity)
print 'Dewpoint 1 = {0:0.8f}'.format (1000*DPf)
print 'Abs. Humidity 1 = {0:0.8f}'.format (1000*HLf)
print 'Dewpoint 2 = {0:0.8f}'.format (1000*DPh)
print 'Abs. Humidity 2 = {0:0.8f}'.format (1000*HLh)
elif option == "snmp":
op = open ('/tmp/temperature_2.snmp', 'w')
op.write ('{0:0.0f}\n'.format (1000*temperature))
op.close ()
op = open ('/tmp/pressure_2.snmp', 'w')
op.write ('{0:0.0f}\n'.format (pressure))
op.close ()
op = open ('/tmp/humidity_rel_2.snmp', 'w')
op.write ('{0:0.0f}\n'.format (1000*humidity))
op.close ()
op = open ('/tmp/dew-point_2_1.snmp', 'w')
op.write ('{0:0.0f}\n'.format (1000*DPf))
op.close ()
op = open ('/tmp/humidity_abs_2_1.snmp', 'w')
op.write ('{0:0.0f}\n'.format (1000*HLf))
op.close ()
op = open ('/tmp/dew-point_2_2.snmp', 'w')
op.write ('{0:0.0f}\n'.format (1000*DPh))
op.close ()
op = open ('/tmp/humidity_abs_2_2.snmp', 'w')
op.write ('{0:0.0f}\n'.format (1000*HLh))
op.close ()
elif option == "file":
snmp = str(1000*temperature) + "\n" + str(1000*humidity) + "\n" + str(pressure) + "\n" + str(1000*DPf) + "\n" + str(1000*HLf) + "\n" + str(1000*DPh) + "\n" + str(1000*HLh)
op = open('/tmp/environment_2.snmp', 'w')
op.write (snmp)
op.close()
if __name__=="__main__":
main()
Alles anzeigen
Beide Scripte werden mit:
python bme280_1.py option oder python bme280_2.py option aufgerufen.
version = Nur das Datum der letzten Änderung
all = Die Werte in lesbarer Form
snmp = 7 Files in /tmp mit der Endung .snmp
file = 1 File in /tmp mit der Endung .snmp
debug = Die Werte so wie sie in den Files in /tmp stehen werden
Beide Scripte wurden durch die Taupunkt- und abs. Feuchte-Berechnung, eine Kalibrierung,
eine Debug-Ausgabe und das Abspeichern der ermittelten Werte in /tmp ergänzt.
Taupunktes und absolute Luftfeuchtigkeit
Was hier noch fehlt, sind die beiden Programme für das berechnen des Taupunktes und der absoluten Luftfeuchtigkeit.
Die Files feuchte.py und humid.py werden in /usr/local/bin abgelegt und brauchen nicht weiter bearbeitet werden.
#!/usr/bin/env python
# coding: utf-8
""" Absolute Feuchte und Taupunkt aus relativer Feuchte und Temperatur berechnen.
Quelle fuer die Formeln: http://www.wetterochs.de/wetter/feuchte.html
Variablen:
r = relative Feuchte [%]
T = Temperatur in °C
TK = Temperatur in Kelvin
TD = Taupunkttemperatur in °C
DD = Dampfdruck in hPa
SDD = Sättigungsdamfdruck in hPa
AF = absolute Feuchte in g/m^3
"""
import math
import sys
# Parameter
a = [ 7.5, 7.6 ]
b = [ 237.3, 240.7 ] # Parametersaetze fuer T >= 0 und T < 0
Rstar = 8314.3 # universelle Gaskonstante in J(Kmol*K)
mw = 18.016 # Molekulargewicht des Wasserdampfes in kg/kmol
OffsetKelvin = 273.15
def TK(T):
return T+OffsetKelvin
def SDD(T): # Saettigungsdampfdruck
if ( T >= 0 ):
i=0
else:
i=1
return 6.1078*math.pow(10,((a[i]*T)/(b[i]+T)))
def DD(r,T): # Dampfdruck
return r/100.0*SDD(T)
def TD(r,T): # Taupunkt
if ( r == 0.):
return 'U'
if ( T >= 0 ):
i=0
else:
i=1
v=math.log10(DD(r,T)/6.1078)
return b[i]*v/(a[i]-v)
def AF(r,T): # absolute Feuchte
return 100000.0*mw/Rstar*DD(r,T)/TK(T)
if __name__ == '__main__':
if len(sys.argv) == 3:
T = float(sys.argv[1])
r = float(sys.argv[2])
print "T: %7.2f °C" % T
print "RH: %7.2f %%" % r
print "TP: %7.2f °C" % TD(r,T)
print "AF: %7.2f g/m^3" % AF(r,T)
Alles anzeigen
#!/usr/bin/python
# coding=utf-8
import math
def dewpoint(t, h):
a1 = 7.45
b1 = 235
dp = float(t)
fw = float(h)
x1 = (a1*dp)/(b1+dp)
e1 = 6.1*math.exp(x1*2.3025851)
e2 = e1*fw/100
x2 = e2/6.1
x3 = 0.434292289*math.log(x2)
dew = (235*x3)/(7.45-x3)*100
dew = math.floor(dew)/100
hum = (216.7*e2)/(273.15+dp)*100
hum = round(hum)/100
dew = "%02.2f" % (dew)
hum = "%02.2f" % (hum)
dew = '{: >5}'.format(dew)
hum = '{: >5}'.format(hum)
return dew,hum
#temp = '20.8'
#hum = '52.8'
#print "Luft temp: {}°C ... hum: {}%" . format(temp, hum)
#dewp, awat = dewpoint(temp, hum)
#print("dewpoint: "+dewp+" °C (condensing)")
#print("feu: "+awat+" (g water per 1m³ air)")
Alles anzeigen
Der Cron-Job
Da ich nicht 2 Jobs gleichzeitig auf das Breakout-Board loslassen wollte, lasse ich mittels cron ein Bash-Script aufrufen:
Mit dem Inhalt:
Das nächste File anlegen:
Inhalt:
#!/bin/sh
#if [ -e /usr/local/bin/bme280_1.py ] ; then /usr/bin/python /usr/local/bin/bme280_1.py snmp 2>&1 ; fi
#sleep 1
if [ -e /usr/local/bin/bme280_1.py ] ; then /usr/bin/python /usr/local/bin/bme280_1.py file 2>&1 ; fi
sleep 1
#if [ -e /usr/local/bin/bme280_2.py ] ; then /usr/bin/python /usr/local/bin/bme280_2.py snmp 2>&1 ; fi
#sleep 1
if [ -e /usr/local/bin/bme280_2.py ] ; then /usr/bin/python /usr/local/bin/bme280_2.py file 2>&1 ; fi
Die Aufrufe mit snmp sind hier bereits auskommentiert, sie würden alle 5 Min. 14 Files auf die SD-Karte schreiben, so sind es nur 2 Files.
Die Bash-Scripte für die Option snmp
Das Abfragen der Werte über SNMP erfolgt über Bash-Scripte, die eigentlich nichts anderes tun,
als die Werte bei Anforderung des Servers herauszugeben. Da diese Scripte fast identisch sind,
habe ich die zweite (dritte, vierte) Variante auskommentiert. Die Files in /tmp werden dann erstellt,
wenn man /usr/local/bin/bme280_(1,2).py mit der Option "snmp" aufruft. Das ganze ist nicht optimal,
nur wenn man 1 oder 2 Werte braucht, sollte man diese Option wählen, alles andere sollte man schon im Pythonscript auskommentieren.
Hier ist es nur der Vollständigkeit halber.
- Temperatur
- Luftfeuchte / Humidity
- Luftdruck / Pressure
- Absolute Luftfeuchtigkeit / Absolute Humidity
- Die Ergänzung für SNMP
Code
Alles anzeigen#pass .1.3.6.1.2.1.25.1.40.1 /bin/sh /usr/local/bin/snmp_temp_1.sh #pass .1.3.6.1.2.1.25.1.41.1 /bin/sh /usr/local/bin/snmp_hum_1.sh #pass .1.3.6.1.2.1.25.1.42.1 /bin/sh /usr/local/bin/snmp_press_1.sh #pass .1.3.6.1.2.1.25.1.43.1 /bin/sh /usr/local/bin/snmp_dewpoint_1_1.sh #pass .1.3.6.1.2.1.25.1.43.2 /bin/sh /usr/local/bin/snmp_dewpoint_1_2.sh #pass .1.3.6.1.2.1.25.1.44.1 /bin/sh /usr/local/bin/snmp_Abs_Humidity_1_1.sh #pass .1.3.6.1.2.1.25.1.44.2 /bin/sh /usr/local/bin/snmp_Abs_Humidity_1_2.sh # #pass .1.3.6.1.2.1.25.1.40.3 /bin/sh /usr/local/bin/snmp_temp_2.sh #pass .1.3.6.1.2.1.25.1.41.3 /bin/sh /usr/local/bin/snmp_hum_2.sh #pass .1.3.6.1.2.1.25.1.42.3 /bin/sh /usr/local/bin/snmp_press_2.sh #pass .1.3.6.1.2.1.25.1.43.3 /bin/sh /usr/local/bin/snmp_dewpoint_2_1.sh #pass .1.3.6.1.2.1.25.1.43.4 /bin/sh /usr/local/bin/snmp_dewpoint_2_2.sh #pass .1.3.6.1.2.1.25.1.44.3 /bin/sh /usr/local/bin/snmp_Abs_Humidity_2_1.sh #pass .1.3.6.1.2.1.25.1.44.4 /bin/sh /usr/local/bin/snmp_Abs_Humidity_2_2.sh
Es gibt aber noch eine elegantere Möglichkeit, daher ist dies hier auskommentiert.
Das Bash-Script für die Option "file"
Kommen wir zur Option "file".
Hier wird das File im Python-Script zusammengebaut und mittels eines Bash-Scripts in ein Array eingelesen.
Hier ist es wichtig, das dieses Script mit der Bash aufgerufen wird, den Befehl "mapfile" habe ich nur hier gefunden.
Das Script
#!/bin/bash
# SNMP Abfragen
# 20160827 erste Version
# 20170506 Anpassung an BME280
#
# Variablen vorbelegen
DATEI=/tmp/environment_1.snmp
# DATEI=/tmp/environment_2.snmp
client=""
optionen="T H P DP1 DP2 AH1 AH2 all"
#
# Datei vorhanden?
if [ -r $DATEI ]
then
# Auslesen
mapfile -t -n 0 ZEILEN < "$DATEI"
else
exit 1
fi
# Argumente auswerten
OP=$1
#echo Debug: $OP
# No Options
if [ -z $OP ]
then
echo No Options
echo Options are: $optionen
OP="all"
# Argumente auswerten
# Temperature
elif [ $OP = "T" ]
then
echo .1.3.6.1.2.1.25.1.40.1
#echo .1.3.6.1.2.1.25.1.40.3
echo gauge
echo ${ZEILEN[0]}
echo $client
# Relative Humidity
elif [ $OP = "H" ]
then
echo .1.3.6.1.2.1.25.1.41.1
#echo .1.3.6.1.2.1.25.1.41.3
echo gauge
echo ${ZEILEN[1]}
echo $client
# Pressure
elif [ $OP = "P" ]
then
echo .1.3.6.1.2.1.25.1.42.1
#echo .1.3.6.1.2.1.25.1.42.3
echo gauge
echo ${ZEILEN[2]}
echo $client
# Dewpoint 1
elif [ $OP = "DP1" ]
then
echo .1.3.6.1.2.1.25.1.43.1
#echo .1.3.6.1.2.1.25.1.43.3
echo gauge
echo ${ZEILEN[3]}
echo $client
# Absolute Humidity 1
elif [ $OP = "AH1" ]
then
echo .1.3.6.1.2.1.25.1.44.1
# echo .1.3.6.1.2.1.25.1.44.3
echo gauge
echo ${ZEILEN[4]}
echo $client
# Dewpoint 2
elif [ $OP = "DP2" ]
then
echo .1.3.6.1.2.1.25.1.43.2
#echo .1.3.6.1.2.1.25.1.43.4
echo gauge
echo ${ZEILEN[5]}
echo $client
# Absolute Humidity 2
elif [ $OP = "AH2" ]
then
echo .1.3.6.1.2.1.25.1.44.2
#echo .1.3.6.1.2.1.25.1.44.4
echo gauge
echo ${ZEILEN[6]}
echo $client
elif [ $OP = "all" ]
then
echo ${ZEILEN[0]}
echo ${ZEILEN[1]}
echo ${ZEILEN[2]}
echo ${ZEILEN[3]}
echo ${ZEILEN[4]}
echo ${ZEILEN[5]}
echo ${ZEILEN[6]}
else
echo Wrong Option
echo Options are: $optionen
exit 1
fi
exit 0
Alles anzeigen
Und die Ergänzung für SNMP
pass .1.3.6.1.2.1.25.1.40.1 /bin/bash /usr/local/bin/bme280_1.sh T
pass .1.3.6.1.2.1.25.1.41.1 /bin/bash /usr/local/bin/bme280_1.sh H
pass .1.3.6.1.2.1.25.1.42.1 /bin/bash /usr/local/bin/bme280_1.sh P
pass .1.3.6.1.2.1.25.1.43.1 /bin/bash /usr/local/bin/bme280_1.sh DP1
pass .1.3.6.1.2.1.25.1.44.1 /bin/bash /usr/local/bin/bme280_1.sh AH1
pass .1.3.6.1.2.1.25.1.43.2 /bin/bash /usr/local/bin/bme280_1.sh DP2
pass .1.3.6.1.2.1.25.1.44.2 /bin/bash /usr/local/bin/bme280_1.sh AH2
#
pass .1.3.6.1.2.1.25.1.40.3 /bin/bash /usr/local/bin/bme280_2.sh T
pass .1.3.6.1.2.1.25.1.41.3 /bin/bash /usr/local/bin/bme280_2.sh H
pass .1.3.6.1.2.1.25.1.42.3 /bin/bash /usr/local/bin/bme280_2.sh P
pass .1.3.6.1.2.1.25.1.43.3 /bin/bash /usr/local/bin/bme280_2.sh DP1
pass .1.3.6.1.2.1.25.1.44.3 /bin/bash /usr/local/bin/bme280_2.sh AH1
pass .1.3.6.1.2.1.25.1.43.4 /bin/bash /usr/local/bin/bme280_2.sh DP2
pass .1.3.6.1.2.1.25.1.44.4 /bin/bash /usr/local/bin/bme280_2.sh AH2
Alles anzeigen
Und nun SNMP neustarten, kurz überprüfen:
snmpget -v1 -c public 192.168.2.13 .1.3.6.1.2.1.25.1.43.1
iso.3.6.1.2.1.25.1.43.1 = Gauge32: 11560
Das sollte man jetzt auch mit den anderen OIDs testen.
Die Ergänzung für MRTG
Achtung, jetzt geht es mit der Serverseite weiter.
Da ich das testweise auf den Client raspi13 installiert habe, wird dessen Config-File modifiziert. Einfach ans Ende dranhängen.
#---------------------------------------------------------------
# Raspberry Pi - Pressure 1
#---------------------------------------------------------------
Target[raspi-press_1]: .1.3.6.1.2.1.25.1.42.1&.1.3.6.1.2.1.25.1.7.0:public@raspi13
Title[raspi-press_1]: raspi13 - Pressure 1
PageTop[raspi-press_1]: <H1>raspi13 - Pressure 1</H1>
Include: raspi-I2C-press_1.inc
#---------------------------------------------------------------
# Raspberry Pi - Pressure 2
#---------------------------------------------------------------
Target[raspi-press_2]: .1.3.6.1.2.1.25.1.42.3&.1.3.6.1.2.1.25.1.7.0:public@raspi13
Title[raspi-press_2]: raspi13 - Pressure 2
PageTop[raspi-press_2]: <H1>raspi13 - Pressure 2</H1>
Include: raspi-I2C-press_2.inc
#---------------------------------------------------------------
# Raspberry Pi - Temperature 1
#---------------------------------------------------------------
Target[raspi-temp_1]: .1.3.6.1.2.1.25.1.40.1&.1.3.6.1.2.1.25.1.7.0:public@raspi13
Title[raspi-temp_1]: raspi13 - Temperature 1
PageTop[raspi-temp_1]: <H1>raspi13 - Temperature 1</H1>
Include: raspi-I2C-temp_1.inc
#---------------------------------------------------------------
# Raspberry Pi - Temperature 2
#---------------------------------------------------------------
Target[raspi-temp_2]: .1.3.6.1.2.1.25.1.40.3&.1.3.6.1.2.1.25.1.7.0:public@raspi13
Title[raspi-temp_2]: raspi13 - Temperature 2
PageTop[raspi-temp_2]: <H1>raspi13 - Temperature 2</H1>
Include: raspi-I2C-temp_2.inc
#---------------------------------------------------------------
# Raspberry Pi - Humidity 1
#---------------------------------------------------------------
Target[raspi-hum_1]: .1.3.6.1.2.1.25.1.41.1&.1.3.6.1.2.1.25.1.7.0:public@raspi13
Title[raspi-hum_1]: raspi13 - Humidity 1
PageTop[raspi-hum_1]: <H1>raspi13 - Humidity 1</H1>
Include: raspi-I2C-hum_1.inc
#---------------------------------------------------------------
# Raspberry Pi - Humidity 2
#---------------------------------------------------------------
Target[raspi-hum_2]: .1.3.6.1.2.1.25.1.41.3&.1.3.6.1.2.1.25.1.7.0:public@raspi13
Title[raspi-hum_2]: raspi13 - Humidity 2
PageTop[raspi-hum_2]: <H1>raspi13 - Humidity 2</H1>
Include: raspi-I2C-hum_2.inc
#---------------------------------------------------------------
# Raspberry Pi - Taupunkt / Absolute Feuchte 1.1
#---------------------------------------------------------------
Target[raspi-taupunkt_1]: .1.3.6.1.2.1.25.1.43.1&.1.3.6.1.2.1.25.1.44.1:public@raspi13
Title[raspi-taupunkt_1]: raspi13 - (Taupunkt / Dew Point) / (Absolute Feuchte / Absolute Humidity) 1.1
PageTop[raspi-taupunkt_1]: <H1>raspi13 - (Taupunkt / Dew Point) / (Absolute Feuchte / Absolute Humidity) 1.1</H1>
Include: raspi-taupunkt_1.inc
#---------------------------------------------------------------
# Raspberry Pi - Taupunkt / Absolute Feuchte 1.2
#---------------------------------------------------------------
Target[raspi-taupunkt_2]: .1.3.6.1.2.1.25.1.43.2&.1.3.6.1.2.1.25.1.44.2:public@raspi13
Title[raspi-taupunkt_2]: raspi13 - (Taupunkt / Dew Point) / (Absolute Feuchte / Absolute Humidity) 1.2
PageTop[raspi-taupunkt_2]: <H1>raspi13 - (Taupunkt / Dew Point) / (Absolute Feuchte / Absolute Humidity) 1.2</H1>
Include: raspi-taupunkt_2.inc
#---------------------------------------------------------------
# Raspberry Pi - Taupunkt / Absolute Feuchte 2.1
#---------------------------------------------------------------
Target[raspi-taupunkt_3]: .1.3.6.1.2.1.25.1.43.3&.1.3.6.1.2.1.25.1.44.3:public@raspi13
Title[raspi-taupunkt_3]: raspi13 - (Taupunkt / Dew Point) / (Absolute Feuchte / Absolute Humidity) 2.1
PageTop[raspi-taupunkt_3]: <H1>raspi13 - (Taupunkt / Dew Point) / (Absolute Feuchte / Absolute Humidity) 2.1</H1>
Include: raspi-taupunkt_3.inc
#---------------------------------------------------------------
# Raspberry Pi - Taupunkt / Absolute Feuchte 2.2
#---------------------------------------------------------------
Target[raspi-taupunkt_4]: .1.3.6.1.2.1.25.1.43.4&.1.3.6.1.2.1.25.1.44.3:public@raspi13
Title[raspi-taupunkt_4]: raspi13 - (Taupunkt / Dew Point) / (Absolute Feuchte / Absolute Humidity) 2.2
PageTop[raspi-taupunkt_4]: <H1>raspi13 - (Taupunkt / Dew Point) / (Absolute Feuchte / Absolute Humidity) 2.2</H1>
Include: raspi-taupunkt_4.inc
Alles anzeigen
Die Include-Dateien
Wer richtig mit gezählt hat, kommt auf 10 Includes, je 2 für Temperatur, Luftfeuchtigkeit und Luftdruck,
und noch 4 Berechnungen für Taupunkt und absoluter Luftfeuchtigkeit.
Minimal reichen 4, hier war es nur, um die Algorithmen zu vergleichen.
Da die Include-Dateien zum Teil fast Idendisch sind, habe ich die Unterschiede in Klammern angegeben.
Man entscheide sich für 1 Möglichkeit, ohne die Klammern.
- Luftdruck
Code
Alles anzeigenAbsMax[raspi-press_(1,2)]: 11000 MaxBytes1[raspi-press_(1,2)]: 10500 MaxBytes2[raspi-press_(1,2)]: 8500 Options[raspi-press_(1,2)]: expscale, gauge, absolute, nopercent, unknaszero, noo, growright, pngdate, nobanner YLegend[raspi-press_(1,2)]: Pressure (hPa) Unscaled[raspi-press_(1,2)]: n ShortLegend[raspi-press_(1,2)]: hPa kMG[raspi-press_(1,2)]: Factor[raspi-press_(1,2)]: 0.1 YTicsFactor[raspi-press_(1,2)]: 0.1 LegendI[raspi-press_(1,2)]: Pressure (hPa) : LegendO[raspi-press_(1,2)]: Pressure (hPa) : Legend1[raspi-press_(1,2)]: Pressure (hPa) Legend2[raspi-press_(1,2)]: Pressure (hPa) Legend3[raspi-press_(1,2)]: Max. Pressure (hPa) Legend4[raspi-press_(1,2)]: Max. Pressure (hPa)
Hier ist unter Options zu beachten das der Graph mit "expscale" nicht linear ist,
sondern im unteren Bereich gestaucht und im oberen Bereich gedehnt wurde.
Hier ist nur der Bereich von ca. 850hPa bis ca. 1100hPa interessant.
Es ist nur ein Notbehelf, so schön wie es David Taylor hinbekommen hat,
ist es mir noch nicht gelungen. Maxbytes2 zeichnet eine Linie bei 850hPa und MaxBytes1 eine bei 1050hPa. - Temperatur
Code
Alles anzeigenAbsMax[raspi-temp_(1,2)]: 60000 MaxBytes1[raspi-temp_(1,2)]: 30000 MaxBytes2[raspi-temp_(1,2)]: 20000 Options[raspi-temp_(1,2)]: expscale, gauge, nopercent, unknaszero, noo, pngdate, growright, nobanner YLegend[raspi-temp_(1,2)]: Temperature C ShortLegend[raspi-temp_(1,2)]: °C kMG[raspi-temp_(1,2)]: , Factor[raspi-temp_(1,2)]: 0.001 YTicsFactor[raspi-temp_(1,2)]: 0.001 LegendI[raspi-temp_(1,2)]: Temperature °C: LegendO[raspi-temp_(1,2)]: Temperature °C: Legend1[raspi-temp_(1,2)]: Temperature °C: Legend2[raspi-temp_(1,2)]: Temperature °C: Legend3[raspi-temp_(1,2)]: Max. Temperature °C: Legend4[raspi-temp_(1,2)]: Max. Temperature °C:
Auch hier habe ich expscale gewählt, weil die Temperaturschwankungen stärker ins Auge fallen.<br />
Anmerkung: Das funktioniert bis jetzt nur bei Plusgraden. - Luftfeuchtigkeit
Code
Alles anzeigenAbsMax[raspi-hum_(1,2)]: 100000 MaxBytes1[raspi-hum_(1,2)]: 25000 MaxBytes2[raspi-hum_(1,2)]: 50000 Options[raspi-hum_(1,2)]: expscale, gauge, nopercent, unknaszero, noo, pngdate, growright, nobanner YLegend[raspi-hum_(1,2)]: Humidity ShortLegend[raspi-hum_(1,2)]: % kMG[raspi-hum_(1,2)]: , Factor[raspi-hum_(1,2)]: 0.001 YTicsFactor[raspi-hum_(1,2)]: 0.001 LegendI[raspi-hum_(1,2)]: Humidity %: LegendO[raspi-hum_(1,2)]: Humidity %: Legend1[raspi-hum_(1,2)]: Humidity %: Legend2[raspi-hum_(1,2)]: Humidity %: Legend3[raspi-hum_(1,2)]: Max. Humidity %: Legend4[raspi-hum_(1,2)]: Max. Humidity %:
Auch hier sieht es mit "expscale" wesentlich dramatischer aus. - Taupunkt und absolute Luftfeuchtigkeit
Code
Alles anzeigenAbsMax[raspi-taupunkt_(1,2,3,4)]: 100000 MaxBytes1[raspi-taupunkt_(1,2,3,4)]: 2500 MaxBytes2[raspi-taupunkt_(1,2,3,4)]: 5000 Options[raspi-taupunkt_(1,2,3,4)]: gauge, nopercent, growright, unknaszero, pngdate, nobanner YLegend[raspi-taupunkt_(1,2,3,4)]: AF g/m^3 \\ Tp C ShortLegend[raspi-taupunkt_(1,2,3,4)]: m kMG[raspi-taupunkt_(1,2,3,4)]: , Factor[raspi-taupunkt_(1,2,3,4)]: 0.001 YTicsFactor[raspi-taupunkt_(1,2,3,4)]: 0.001 LegendI[raspi-taupunkt_(1,2,3,4)]: Absolute Feuchte g/m^3: LegendO[raspi-taupunkt_(1,2,3,4)]: Taupunkt °C: Legend1[raspi-taupunkt_(1,2,3,4)]: Absolute Feuchte g/m^3 Legend2[raspi-taupunkt_(1,2,3,4)]: Taupunkt °C Legend3[raspi-taupunkt_(1,2,3,4)]: Max. Absolute Feuchte g/m^3 Legend4[raspi-taupunkt_(1,2,3,4)]: Max. Taupunkt °C
Hier werden 2 Diagramme zusammengefasst, das sich die Graphen (zumindestens bei mir) fast immer nah beieinander befinden.
Es sieht auch ohne "expscale" dramatisch genug aus.
Es sind zwar ein paar mehr Include-Dateien, aber als Trost sei angemerkt, das man sie receyceln kann.
Finale
Fehlt nur noch:
Also ein neues Index-File, spätestens nach 5 min. sollte sich leere Diagramme zeigen, das sich weitere 5 min. später langsam mit Inhalten füllen.
Edit: Fiptehler korrigiert
Edit2: Link überarbeitet