BME280 optimal mit MicroPython ansteuern

Drüben bei Strom sparen beim Einsatz der MicroPython-Firmware im Batteriebetrieb ging es auch um die optimal stromsparende Ansteuerung der BME280 Sensoren.

Einen Teil der Diskussion haben wir hierher verlagert.

BME280 forced mode mit MicroPython

Inventur

Für die erste Implementierung sind wir damals bei dieser Bibliothek gelandet, die ursprünglich für den ESP8266 vorgesehen ist. Die lag wohl damals zufällig im Regal.

Analyse

1. Implementierte Modi

2. Sanity checks

3. Anwendung auf die sleep time

Gedanken

Die Referenz auf BME280_ULTRALOWPOWER ist nett, wird aber scheinbar nirgendwo direkt implementiert oder ich sehs nicht. Werdet Ihr daraus schlau, @weef oder @roh?

Wie gehts weiter?

Es wird auf jeden Fall noch einmal nach alternativen MicroPython-Bibliotheken für den BME280 Ausschau gehalten.

… hätten wir ja auch aus erster Hand haben können. Meiomei.

1 Like

BME280 Bibliothek für MicroPython von robert-hh (Robert Hammelrath) · GitHub

Einleitung

Bewertung

Die Bibliotheken sind vom gleichen Ursprung, die von robert-hh (Robert Hammelrath) · GitHub ist jedoch aktueller und implementiert folgende Features.

Verbesserungen bei “Wait for conversion to complete”

nun jenes verwendet

Weitere Funktionen

Neu hinzugekommen sind sealevel(), altitude() und dew_point(), siehe

– Seitenblicke.

Adafruit CircuitPython BME280

About

Modi: NORMAL vs. FORCED

Definition

Implementierung

Re. forced mode.

STANDBY

Daneben gibt es noch STANDBY Geschichten.

Definition

Implementierung

BMP280 und BME280: die untersten beiden bits im Register 0xF4 “ctrl_meas” setzen diese modi: wenn Du da eine 1 oder eine 2 reinschreibst, startest Du einen cycle per forced mode.

Auf den Seiten 28 und 29 des BME280 – Data sheet finden sich:

1 Like

Danke. Die untersten beiden – also die niederwertigsten (LSB) Bits – ja?

Pycom MicroPython

By robert-hh (Robert Hammelrath) · GitHub.

Berechnung und Setter

Adafruit CircuitPython

By jraber (Jeff Raber) · GitHub.

Berechnung

https://github.com/adafruit/Adafruit_CircuitPython_BME280/blob/master/adafruit_bme280.py#L291-L297

Setter

https://github.com/adafruit/Adafruit_CircuitPython_BME280/blob/master/adafruit_bme280.py#L161-L168

Bei der aktuellen, für Pycom ausgelegten Bibliothek haben wird als Standardmodus BME280_OSAMPLE_1 = 1 verwendet. Das ergibt folgendes Bitfeld für das Register 0xF4 “ctrl_meas”.

>>> mode = 1
>>> bin(mode << 5 | mode << 2 | 1)
'0b100101'

Formatted differently:

>>> format(mode << 5 | mode << 2 | 1, '#010b')
'0b00100101'

Da stelle ich mir immer die Frage: Ist hier jetzt das LSB auf der linken Seite? Deshalb gibt es hier Strauchelpotenzial.

1 Like

Gut, das ist meiner Meinung nach in dieser Bibliothek einfach nicht konfigurierbar sondern steht fix auf 1 – hier wird also immer im forced mode gearbeitet.

Dass self.mode auch zur Berechnung der anderen beiden Bereiche im Bitfeld herangezogen wird, ist aus meinen Augen Quatsch und hatte mich bei der Durchsicht entsprechend verwirrt. Diese beiden regeln den/die/das Overscan [1] – und zwar individuell pro Temperature/Pressure.

Siehe die Adafruit-Implementierung im direkten Vergleich:
https://github.com/adafruit/Adafruit_CircuitPython_BME280/blob/master/adafruit_bme280.py#L80-L86
https://github.com/adafruit/Adafruit_CircuitPython_BME280/blob/master/adafruit_bme280.py#L91-L94
https://github.com/adafruit/Adafruit_CircuitPython_BME280/blob/master/adafruit_bme280.py#L126-L127
https://github.com/adafruit/Adafruit_CircuitPython_BME280/blob/master/adafruit_bme280.py#L291-L297


  1. Not a hardware… ↩︎

2 Likes

Aber…

… auch hier könnte das Timing in die Suppe spucken, siehe Untersuchung und Verbesserung des Timings bei der Ansteuerung der DS18B20 Sensoren unter MicroPython. Daher verwenden wir auf jeden Fall besser die aktualisierte Variante der Bibliothek.

Die wirft erst einmal:

 1397.5486 [terkin.datalogger        ] INFO   : Reading sensor port "BME280Sensor"
 1397.6333 [terkin.datalogger        ] ERROR  : Reading sensor "BME280Sensor" failed
Traceback (most recent call last):
  File "datalogger.py", line 310, in read_sensors
  File "util.py", line 193, in __exit__
  File "datalogger.py", line 310, in read_sensors
  File "sensor_bme280.py", line 59, in read
ValueError: unknown format code 'd' for object of type 'float'

war das die lib, bei der es float- sowie int-Versionen gab?

ja! 8)

Ja. Ich sehe auch grade: Der Fehler liegt in unserer Routine beim Postprocessing:

t, p, h = self.driver.read_compensated_data()

# Prepare readings.
values = {}
if t:
    values["temperature"] = t / 100

if p:
    p = p // 256
    pi = p // 100
    pd = p - pi * 100
    values["pressure"] = float("{}.{:02d}".format(pi, pd))

if h:
    hi = h // 1024
    hd = h * 100 // 1024 - hi * 100
    values["humidity"] = float("{}.{:02d}".format(hi, hd))

So sehen die Werte aus der Routine read_compensated_data() aus:

>>> datalogger.sensor_manager.sensors
[<SystemMemoryFree object at 3f9a4ae0>, <SystemTemperature object at 3f9a4af0>, <SystemBatteryLevel object at 3f9a4b00>, <SystemUptime object at 3f9a5360>, <SystemWiFiMetrics object at 3f9a5370>, <HX711Sensor object at 3f9a6400>, <DS18X20Sensor object at 3f9a90e0>, <BME280Sensor object at 3f9a9db0>]

>>> bme280 = datalogger.sensor_manager.sensors[-1]

>>> bme280.driver.read_compensated_data()
array('f', [25.95522, 100929.1, 61.13297])

So sehen die Werte aus read_raw_data() aus.

>>> from array import array
>>> result = array("i", [0, 0, 0])
>>> bme280.driver.read_raw_data(result)
>>> result
array('i', [532502, 343152, 35142])

Terkin-Datenlogger interaktiv

Wir sollten die Werte wohl nun einfach “as is” übernehmen und nicht mehr gegen das Scaling arbeiten, wie es die int-Variante lieferte.

Ist pascal in Ordnung oder sollen wir nach hectopascal umrechnen?

1 Like

War vorher auch so, nicht?

   28.4585 [terkin.datalogger        ] INFO   : Sensor data:

           humidity.0x77.i2c:0                        60.7448    Temperatur und Feuchte außen
           pressure.0x77.i2c:0                        1009.36    Temperatur und Feuchte außen
           temperature.0x77.i2c:0                     25.7686    Temperatur und Feuchte außen
2 Likes

Ich halte die Ausgabe von Feuchte und Temperatur mit 4 Stellen nach dem Komma ( z.B.60.7448 % ) für falsch, denn es gaukelt eine Genauigkeit vor, die es nicht gibt. Schon die Stelle vor dem Komma muss nicht stimmen, so genau ist der BME280 auch nicht.
Für die Darstellung in der BOB-App ist die Ausgabe von 1 Nachkommastelle sinnvoll, damit die Kurven glatter werden.
Bei den üblichen Wetterstationen wird die Temperatur mit 1 und Feuchte und Luftdruck ohne Nachkommastelle ausgegeben.

1 Like

Hi Didi,

wir wollen generell immer möglichst viel roh direkt vom Sensor schicken und Umrechnungen erst später machen. Das Auslesen des HX711 ist hier die Ausnahme, die die Regel bestätigt: Hier rechnen wir ja schon am Knoten auf Kilogramm um, selbst wenn auch hier eine spätere Umrechnung denkbar wäre.

Viele Grüße,
Andreas.

Finde es auch überflüssig die unnötigen Nachkommastellen mitzuschleppen, wenn wir an LoRa oder Zwischenspeichern oder irgendwas mit limitations denken müssen wir eh optimieren. Wenn es eine allgemeine Rountine für Temperatur wäre könnte man ja noch sagen, da kommt mal ein Wissenschaftler der mit anderem Gerät im 1/100 oder 1/1000-Bereich messen möchte, die Routinen sind aber an den BME oder den DS18B20 gekoppelt und der wird nicht mehr genauer.

Ich finde es sinnvoll, die Messwerte sofort auf Plausibilität zu prüfen. Damit wird Ballast bei jeder weiteren Verarbeitung oder Transfer vermieden.
Dazu gehören unnötige Nachkommastellen oder Messwertaussreisser bei DS18B20. Wenn z.B. alle 10 sec 23.6°C gemessen werden und dann taucht einmal der Wert 85.7°C auf, dann ist das ein Fehler, vermutlich ein Treiber-Fehler. Ihn zur BOB-App zu senden und dann wegzumitteln ist einfach falsch.

1 Like