BMP280 / BME280 uPython

RP2040 based microcontroller boards running MicroPython.
Target audience: MicroPython users with an RP2040 boards.
This does not include conventional Linux-based Raspberry Pi boards.
Rissy
Posts: 116
Joined: Sun Aug 14, 2022 8:15 am

Re: BMP280 / BME280 uPython

Post by Rissy » Thu Sep 01, 2022 5:47 pm

danjperron wrote:
Thu Sep 01, 2022 5:14 pm
How can I do this if in the driver file, there appears to be a fixed address and its set only to 0x76?! I didn't understand even though it clearly works as I have it....?!
OH! this is a python behavior

if you check the driver you got

Code: Select all

# BME280 default address.
BME280_I2CADDR = 0x76

class BME280:

    def __init__(self,
                 mode=BME280_OSAMPLE_1,
                 address=BME280_I2CADDR,
                 i2c=None,
                 **kwargs):
this mean that if you don't declare address when you create the object it will use BME280_I2CADDR which is 0x76 in the library.
But if you specify address=X it will use X.
Ah yes, I see that now.

Rissy
Posts: 116
Joined: Sun Aug 14, 2022 8:15 am

Re: BMP280 / BME280 uPython

Post by Rissy » Fri Sep 02, 2022 6:46 am

Any help on my other questions gentle-peoples?

Rissy
Posts: 116
Joined: Sun Aug 14, 2022 8:15 am

Re: BMP280 / BME280 uPython

Post by Rissy » Fri Sep 02, 2022 7:07 am

I've got two separate MQTT receive files working. One looks at one broker, and the other looks at another broker.

I attempted to combine these files to give me just one, but i'm not sure if this is allowed or not. The code partially works in that it receives from broker1, but right now it completely ignores broker2.

Maybe a genius out there can advise me where i'm going wrong here, or advise me if I'm trying to do something impossible or not?

Code: Select all

#!/usr/bin/env python
#!/bin/bash
#MQTT_PW2_Vars_Combined.py

import time
import paho.mqtt.client as mqtt

loop=0

#initial screen message with delay attached before running program
print("---------------------------------------------------------")
print("-Pico W1+2 MQTT Receive Program is loading, please wait...-")
print("---------------------------------------------------------")
time.sleep(2)

PicoTempFile = '/home/chrispi/Chris_Py_Progs/Program_Increment_Files/PicoW1/PicoTempFile.txt'
PicoHumFile = '/home/chrispi/Chris_Py_Progs/Program_Increment_Files/PicoW1/PicoHumFile.txt'
CPUFile = '/home/chrispi/Chris_Py_Progs/Program_Increment_Files/PicoW1/PicoFile.txt'

bme0TFile = '/home/chrispi/Chris_Py_Progs/Program_Increment_Files/PicoW2/bme0TFile.txt'
bme0PFile = '/home/chrispi/Chris_Py_Progs/Program_Increment_Files/PicoW2/bme0PFile.txt'
bme0HFile = '/home/chrispi/Chris_Py_Progs/Program_Increment_Files/PicoW2/bme0HFile.txt'
bme1TFile = '/home/chrispi/Chris_Py_Progs/Program_Increment_Files/PicoW2/bme1TFile.txt'
bme1PFile = '/home/chrispi/Chris_Py_Progs/Program_Increment_Files/PicoW2/bme1PFile.txt'
bme1HFile = '/home/chrispi/Chris_Py_Progs/Program_Increment_Files/PicoW2/bme1HFile.txt'
Pico2TempFile = '/home/chrispi/Chris_Py_Progs/Program_Increment_Files/PicoW2/Pico2TempFile.txt'

broker1 = '192.168.0.51'
broker2 = '192.168.0.54'
port = 1883
mqttclient = "PiLogger2"
client = mqtt.Client(mqttclient)

topic01 = 'OS_Temp'
topic02 = 'OS_Hum'
topic03 = 'Pico_Temp'

topic1 = 'PicoW2/bme0T'
topic2 = 'PicoW2/bme0P'
topic3 = 'PicoW2/bme0H'
topic4 = 'PicoW2/bme1T'
topic5 = 'PicoW2/bme1P'
topic6 = 'PicoW2/bme1H'
topic7 = 'PicoW2/PicoTemp'

def on_connect1(client, userdata, flags, rc):
    if rc == 0:
        print(f"Connected to MQTT Broker with result: {rc}")
    else:
        print("Failed to connect to Broker, return code = ", rc)

def on_disconnect1(client, userdata, rc):
    if rc != 0:
        print("Unexpected disconnection!")

def on_connect2(client, userdata, flags, rc):
    if rc == 0:
        print(f"Connected to MQTT Broker with result: {rc}")
    else:
        print("Failed to connect to Broker, return code = ", rc)

def on_disconnect2(client, userdata, rc):
    if rc != 0:
        print("Unexpected disconnection!")

def on_message1(client, userdata, message):
    #topics = message.topic.split('/') # topics is now a list containing the topic segments
    #topics = message.topic.split() # topics is now a list containing the topic segments
    topics = message.topic
    #print(topic[1])
    payload = message.payload.decode("utf-8")
    #print(payload)
    if topics == topic01:
        global OS_Temp
        print(f"Received: {(message.payload.decode('utf-8'))} from Topic: {message.topic}")
        GVAR = payload
        OS_Temp = GVAR
        PWTfile = open(PicoTempFile, 'w')
        PWTfile.write(OS_Temp)
        PWTfile.close()

    if topics == topic02:
        global OS_Hum
        print(f"Received: {(message.payload.decode('utf-8'))} from Topic: {message.topic}")
        GVAR = payload
        OS_Hum = GVAR
        PWHfile = open(PicoHumFile, 'w')
        PWHfile.write(OS_Hum)
        PWHfile.close()

    if topics == topic03:
        global Pico_Temp
        print(f"Received: {(message.payload.decode('utf-8'))} from Topic: {message.topic}")
        GVAR = payload
        Pico_Temp = GVAR
        PicoFile = open(CPUFile, 'w')
        PicoFile.write(Pico_Temp)
        #PicoFile.write("\n")
        PicoFile.close()

def on_message2(client, userdata, message):
    topics = message.topic
    payload = message.payload.decode("utf-8")
    if topics == topic1:
        print(f"Received: {(message.payload.decode('utf-8'))} from Topic: {message.topic}")
        GVAR = payload
        bme0T = GVAR
        PWT0file = open(bme0TFile, 'w')
        PWT0file.write(bme0T)
        PWT0file.close()
                
    if topics == topic2:
        print(f"Received: {(message.payload.decode('utf-8'))} from Topic: {message.topic}")
        GVAR = payload
        bme0P = GVAR
        PWP0file = open(bme0PFile, 'w')
        PWP0file.write(bme0P)
        PWP0file.close()
        
    if topics == topic3:
        print(f"Received: {(message.payload.decode('utf-8'))} from Topic: {message.topic}")
        GVAR = payload
        bme0H = GVAR
        PWH0file = open(bme0HFile, 'w')
        PWH0file.write(bme0H)
        PWH0file.close()

    if topics == topic4:
        print(f"Received: {(message.payload.decode('utf-8'))} from Topic: {message.topic}")
        GVAR = payload
        bme1T = GVAR
        PWT1file = open(bme1TFile, 'w')
        PWT1file.write(bme1T)
        PWT1file.close()

    if topics == topic5:
        print(f"Received: {(message.payload.decode('utf-8'))} from Topic: {message.topic}")
        GVAR = payload
        bme1P = GVAR
        PWP1file = open(bme1PFile, 'w')
        PWP1file.write(bme1P)
        PWP1file.close()

    if topics == topic6:
        print(f"Received: {(message.payload.decode('utf-8'))} from Topic: {message.topic}")
        GVAR = payload
        bme1H = GVAR
        PWH1file = open(bme1HFile, 'w')
        PWH1file.write(bme1H)
        PWH1file.close()

    if topics == topic7:
        print(f"Received: {(message.payload.decode('utf-8'))} from Topic: {message.topic}")
        GVAR = payload
        Pico2Temp = GVAR
        Pico2File = open(Pico2TempFile, 'w')
        Pico2File.write(Pico2Temp)
        Pico2File.close()

if loop == 0:        
    client.connect(broker1, port)
    client.on_connect = on_connect1
    client.on_disconnect = on_disconnect1
    time.sleep(3)
    client.subscribe(topic01)
    client.subscribe(topic02)
    client.subscribe(topic03)
    client.on_message = on_message1
    time.sleep(5)
    loop=1
    client.loop_forever()  #i've tried with this line indented and not indented.  same result is produced

if loop == 1:
    client.connect(broker2, port)
    client.on_connect = on_connect2
    client.on_disconnect = on_disconnect2
    time.sleep(3)
    client.subscribe(topic1)
    client.subscribe(topic2)
    client.subscribe(topic3)
    client.subscribe(topic4)
    client.subscribe(topic5)
    client.subscribe(topic6)
    client.subscribe(topic7)
    client.on_message = on_message2
    time.sleep(5)
    loop=0
    client.loop_forever()  #i've tried with this line indented and not indented.  same result is produced

beetle
Posts: 51
Joined: Sat Oct 16, 2021 11:35 am

Re: BMP280 / BME280 uPython

Post by beetle » Fri Sep 02, 2022 5:07 pm

Rissy, you seek a genius but why are you trying to use 2 mqtt brokers when just one broker can service 1000's of clients?

Mqtt client programs connected to just one broker (even one running on your little rpi) can send messages on whatever topic is desired and receive messages on whatever topics they subscribe to and these Mqtt client programs can run on PC's, mac's, rpi's, rpi Pico's etc.
One broker to rule them all,
many clients is fine when,
one broker will get them all,
and in its bosom bind them.

:lol: (not a genius, and definitely not a poet)

Rissy
Posts: 116
Joined: Sun Aug 14, 2022 8:15 am

Re: BMP280 / BME280 uPython

Post by Rissy » Fri Sep 02, 2022 6:47 pm

beetle wrote:
Fri Sep 02, 2022 5:07 pm
Rissy, you seek a genius but why are you trying to use 2 mqtt brokers when just one broker can service 1000's of clients?

Mqtt client programs connected to just one broker (even one running on your little rpi) can send messages on whatever topic is desired and receive messages on whatever topics they subscribe to and these Mqtt client programs can run on PC's, mac's, rpi's, rpi Pico's etc.
One broker to rule them all,
many clients is fine when,
one broker will get them all,
and in its bosom bind them.

:lol: (not a genius, and definitely not a poet)
Hi beetle! At least I can still count on you helping me out with my requests for help eh. :D

I appreciate what you're saying about MQTT brokers, and eventually, I'll just have the one, but right now whilst i'm prototyping my next "evolution", it would be easier for me to have two for the purposes I was trying to get working. I was more interested in whether it could be done or not, rather than if I should. To be honest.

If nobody knows how to do it, or if it can even be done like i'm trying to do, then i'm more interested in my query regarding the oversampling rates adjustment question when using a Pico W rather than a RP...
As stated, I had to make adjustments to the __init__.py file in my RP4B setup to make the BME280s reliably accurate for the sort of environment my loft is. I've been very happy with the readings i've been getting from that setup. However, now that i'm looking for pulling the RP out of the loft and put this second Pico W up there in its place; what I didn't want was a noticeable jump in the reading performance I've been getting as a consequence of swapping out the hardware taking in those readings. I wanted to duplicate the exact same setup in software using the Pico W as I have with the RP4B. Can it be done?

I may have to put this Pico W up by the RP4B and put the sensors in the same positions, except keep both systems going in parallel for a while just to see how differently they may or may not read. I went through major headaches trying to get the readings accurate by using the cheap-mans method of putting in offsets in the Python software against the readings from my first set of BME280s, but of course if the error(s) are non-linear, then this is the wrong approach. I found the only properly accurate way was to adjust the oversampling rates in the driver file according to the recommendations made by Bosch themselves. This is what I want to do again in the uPython code. Any help?

Basically, the uPython version of these lines (original versus my adjusted version according to Bosch recommendations):

Code: Select all

#def setup(self, mode='normal', temperature_oversampling=16, pressure_oversampling=16, humidity_oversampling=16, temperature_standby=500):
def setup(self, mode='normal', temperature_oversampling=2, pressure_oversampling=16, humidity_oversampling=1, temperature_standby=500):

beetle
Posts: 51
Joined: Sat Oct 16, 2021 11:35 am

Re: BMP280 / BME280 uPython

Post by beetle » Fri Sep 02, 2022 7:34 pm

Rissy, regarding the oversampling that your micropython library allows it is done differently than the way you describe for you rpi library. In the micropython library snippet you show (as below) that there are 5 oversampling modes shown. As you can see when you create a class object to use the BME280 class the default oversample mode is 1 which appears to mean 1 times oversampled.

Code: Select all

# Operating Modes
BME280_OSAMPLE_1 = 1
BME280_OSAMPLE_2 = 2
BME280_OSAMPLE_4 = 3
BME280_OSAMPLE_8 = 4
BME280_OSAMPLE_16 = 5

BME280_REGISTER_CONTROL_HUM = 0xF2
BME280_REGISTER_CONTROL = 0xF4

class BME280:
    def __init__(self,
                 mode=BME280_OSAMPLE_1,
                 address=BME280_I2CADDR,
                 i2c=None,
                 **kwargs):
        # 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
        self.address = address
And, like the i2c address, which you now understand can be overridden, you can likewise override the default oversample by passing the desired when you create your class object. So for 8x oversampling something like:
my_bme280 = BME280(address = 0x77, mode = BME280_OSAMPLE_8)

As you will also see from your code snippet, if you put in something other than one of the defined sample modes the class will complain (raise an error) and show the available modes to use.

I note that in your example setting for your rpi you appear to be able to set oversampling for the temperature and humidity differently. The micropython library you are using just has the one setting for both.

Rissy
Posts: 116
Joined: Sun Aug 14, 2022 8:15 am

Re: BMP280 / BME280 uPython

Post by Rissy » Sat Sep 03, 2022 8:11 am

Ah right. I did see the reference to oversampling in bme280.py, but I’m having problems understanding how to change these for each of the parameters to match the credentials I’ve given in my RP. Are you able to give me the answer for this and maybe then I’ll understand?

Also, if you’re saying they’ve tied the temperature and humidity oversampling potential together in this driver file, is there an alternative one which will allow full potential changes as per my RP4B equivalent?

Rissy
Posts: 116
Joined: Sun Aug 14, 2022 8:15 am

Re: BMP280 / BME280 uPython

Post by Rissy » Mon Sep 05, 2022 5:41 pm

No help from anyone then? Should I post for help in other forums?

User avatar
Roberthh
Posts: 3667
Joined: Sat May 09, 2015 4:13 pm
Location: Rhineland, Europe

Re: BMP280 / BME280 uPython

Post by Roberthh » Mon Sep 05, 2022 7:48 pm

The driver can easily be modified. If you change the API to supply a tuple of 3 values for oversampling instead of a singe value, these values can be sent to the chip. There seems to be only a single place where that happens.

Rissy
Posts: 116
Joined: Sun Aug 14, 2022 8:15 am

Re: BMP280 / BME280 uPython

Post by Rissy » Mon Sep 05, 2022 8:24 pm

Roberthh wrote:
Mon Sep 05, 2022 7:48 pm
The driver can easily be modified. If you change the API to supply a tuple of 3 values for oversampling instead of a singe value, these values can be sent to the chip. There seems to be only a single place where that happens.
Ha! That’s great Roberthh!

Unfortunately you describe that to me as if I know how to do that. :lol:

I don’t.

Can you do this for me and explain how I can then use it to set the oversample values I want to use?

Post Reply