BME280 optimal mit MicroPython ansteuern

– 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

Hi Didi,

ja, Glitches aufgrund von Schluckaufs beim Sensortreiber o.ä. sollten wir auf jeden Fall minimieren und falls doch welche durchkommen, ggf. komplett wegfiltern können. Hierfür könnten wir uns auf industrieübliche(?) [1] Wertebereiche einigen, um festzulegen, was “plausibel” genau für designiert gültige Werte bedeuten soll.

Bzgl. des BME280 schnappte ich neulich auf, dass dort bereits ein IIR-Filter eingebaut sein soll.

Viele Grüße,
Andreas.


  1. Vielleicht gibts dafür ja bereits (halb-)offizielle Vorschläge, was so die üblichen Wertebereiche von °C, %hum, hPa, kg, you-name-it pro Einheit in unserer Anwendungsdomäne (environmental monitoring/sensing) angeht. Ansonsten nehmen wir halt den gesunden Menschenverstand zur Hilfe – der aber natürlich auch manchmal täuschen kann. ↩︎

Zumindest hört sich das für mich selbst sinnvoll an, hierfür kurzerhand einen diskreten Bandpass-artigen Filter zu verwenden. Ich bin da allerdings nicht sattelfest, haut das deswegen gerne vom Tisch, falls das irgendwie nonsense ist.

Hierzu wollte ich noch loswerden, dass der aktuelle Softwarestand im Repository in diesem Bereich noch etwas an den Feinheiten verbessert haben könnte, daher freue ich mich über die nächsten "Langzeit"tests von @MKO und @clemens. Wir hoffen, dass durch die kürzlich erfolgten Änderungen an den entsprechenden Routinen bei den DS18B20-Sensoren [1] und hier beim BME280-Sensor die Situation noch ein wenig verbessert wurde.


  1. Untersuchung und Verbesserung des Timings bei der Ansteuerung der DS18B20 Sensoren unter MicroPython ↩︎

BME280 forced mode recap

Wir haben gerade folgende Spur entdeckt.

Investigation

While the BME280 datasheet outlines on page 15 that

3.3.2 Sleep mode

Sleep mode is entered by default after power on reset.

we recognize the canonical libraries explicitly put the sensor into sleep mode when starting up

before further manipulating the control register in order to enable forced mode.

In contrast to that,

might actually put the sensor into normal mode, eventually ignoring the successive enablement of the forced mode.

By the way, the predecessor(?) driver GitHub - catdog2/mpy_bme280_esp8266: Driver for the Bosch BME280 for use with MicroPython on ESP8266 boards is acting in the same way here.

References

>>> bin(0x3F)
'0b111111'

Outlook

We just created a ticket with the upstream repository in order to hear what @robert-hh thinks about our findings.

2 Likes