How to connect a BME680?


#1

How do I connect my BME680 sensor via Cayenne? It does not appear to be supported by default, will this change in a future update?


#2

which device (pi / arduino) have you connected your BME680?


#3

Hi shramiksalgaonkar,

I am using a Raspberry Pi and have successfully connected the module to my Pi and ran the test script supplied with the module.

Hooking the data being captured into Cayenne is the goal I wish to achieve.


#4

you can the sensor data from the test script to cayenne using https://github.com/myDevicesIoT/Cayenne-MQTT-Python


#5

Thanks!

So something like this project?:

This Github project seems to have solved connecting bme680 using MQTT but to another service.


#6

you have do something similar but using https://github.com/pimoroni/bme680-python and https://github.com/myDevicesIoT/Cayenne-MQTT-Python


#7

Following on from the Pimoroni topic of your (I’m guessing) https://forums.pimoroni.com/t/bme680-to-web-service/8407

I suggest doing this on the Pi desktop or on a Mac/Windows Desktop and copying it across as it’s horrible to do on Android.
On your dashboard, https://cayenne.mydevices.com/cayenne/dashboard/add
Use Add New… - Device/Widget (green bit top left)
Select ‘Bring Your Own Thing’ (from the list, it’s at the bottom).
then stop there.

Use this (it should work, but it’s an untested cut down version of my program with more sensors and I cannot test it, edit as needed and check nothing is included that is also not needed.)
Fill it in with the MQTT info from that page

#!/usr/bin/python3
import sys
import time
import cayenne.client
import bme680

# Cayenne authentication info. This should be obtained from the Cayenne Dashboard.
MQTT_USERNAME  = "mqqt_user_from_page"
MQTT_PASSWORD  = "mqqt_pass_from_page"
MQTT_CLIENT_ID = "mqqt_id_from_page"

#general
timestamp = 0
loop_delay = 15 #seconds
reading_delay = 60

def on_message(message):
        print("message received: " + str(message))

def bme_start():
    print("""Estimate indoor air quality

    Runs the sensor for a burn-in period, then uses a
    combination of relative humidity and gas resistance
    to estimate indoor air quality as a percentage.

    Press Ctrl+C to exit

    """)

    sensor = bme680.BME680()

    # These oversampling settings can be tweaked to
    # change the balance between accuracy and noise in
    # the data.

    sensor.set_humidity_oversample(bme680.OS_2X)
    sensor.set_pressure_oversample(bme680.OS_4X)
    sensor.set_temperature_oversample(bme680.OS_8X)
    sensor.set_filter(bme680.FILTER_SIZE_3)
    sensor.set_gas_status(bme680.ENABLE_GAS_MEAS)

    sensor.set_gas_heater_temperature(320)
    sensor.set_gas_heater_duration(150)
    sensor.select_gas_heater_profile(0)

    # start_time and curr_time ensure that the
    # burn_in_time (in seconds) is kept track of.

    start_time = time.time()
    curr_time = time.time()
    burn_in_time = 300

    burn_in_data = []

    try:
        # Collect gas resistance burn-in values, then use the average
        # of the last 50 values to set the upper limit for calculating
        # gas_baseline.
        print("Collecting gas resistance burn-in data for 5 mins\n")
        while curr_time - start_time < burn_in_time:
            curr_time = time.time()
            if sensor.get_sensor_data() and sensor.data.heat_stable:
                gas = sensor.data.gas_resistance
                burn_in_data.append(gas)
                print("Gas: {0} Ohms".format(gas))
                time.sleep(1)

        gas_baseline = sum(burn_in_data[-50:]) / 50.0

        # Set the humidity baseline to 40%, an optimal indoor humidity.
        hum_baseline = 40.0

        # This sets the balance between humidity and gas reading in the
        # calculation of air_quality_score (25:75, humidity:gas)
        hum_weighting = 0.25

        print("Gas baseline: {0} Ohms, humidity baseline: {1:.2f} %RH\n".format(gas_baseline, hum_baseline))

    except KeyboardInterrupt:
        pass

    return gas_baseline, hum_baseline, hum_weighting

#-----Main
#cayenne mqqt setup
client = cayenne.client.CayenneMQTTClient()
client.on_message = on_message
client.begin(MQTT_USERNAME, MQTT_PASSWORD, MQTT_CLIENT_ID)

print("BME680 Starting")
bme_sensor = bme680.BME680()
gas_baseline, hum_baseline, hum_weighting = bme_start()


try:
    while True:
        client.loop()

        if (time.time() > timestamp + reading_delay):

            if bme_sensor.get_sensor_data():
                #send data direct to Cayenne
                client.celsiusWrite(    1, bme_sensor.data.temperature)
                client.hectoPascalWrite(2, bme_sensor.data.pressure)
                client.virtualWrite(    3, bme_sensor.data.humidity,"rel_hum","p")


            time.sleep(5)   #needs a delay otherwise gas sensor doesn't (i.e. doesn't trigger true), alter as needed.

            if bme_sensor.get_sensor_data() and bme_sensor.data.heat_stable:
                gas = bme_sensor.data.gas_resistance
                gas_offset = gas_baseline - gas

                hum = bme_sensor.data.humidity
                hum_offset = hum - hum_baseline

                # Calculate hum_score as the distance from the hum_baseline.
                if hum_offset > 0:
                    hum_score = (100 - hum_baseline - hum_offset) / (100 - hum_baseline) * (hum_weighting * 100)

                else:
                    hum_score = (hum_baseline + hum_offset) / hum_baseline * (hum_weighting * 100)

                # Calculate gas_score as the distance from the gas_baseline.
                if gas_offset > 0:
                    gas_score = (gas / gas_baseline) * (100 - (hum_weighting * 100))

                else:
                    gas_score = 100 - (hum_weighting * 100)

                # Calculate air_quality_score.
                air_quality_score = hum_score + gas_score

                #Send to calculated Pimoroni formula IAQ to Cayenne, this isn't the true Bosch IAQ
                client.virtualWrite(4, gas, "co","ohms")
                client.virtualWrite(5, air_quality_score, "IAQ","null")
                #print("Gas: {0:.2f} Ohms,humidity: {1:.2f} %RH,air quality: {2:.2f}".format(gas, hum, air_quality_score))

            timestamp = time.time()
        time.sleep(loop_delay-5)

except KeyboardInterrupt:
    pass

then run it on the Pi with that page still open and wait till it works, which shouldn’t be long


#8

Superb @bensimmo. Thanks for sharing this. It will be helpful to many users.


#9

Thank you @bensimmo.

Excitedly working my way through the steps you shared now :slight_smile:

This will be a good resource to point other people to @shramiksalgaonkar - thanks to you too.


#11

I now use Bosch BSEC blob (their bit of C software code you must use as though it says IAQ readings are direct from the device, they are not. They are indirect and go via a bit of C software (BSEC) that does the calculations.

But that’s just switching out all the BME680 code for some code on GitHub.
I’m still testing it though ASI have nothing to compare the actual IAQ too.