MICs6814, SGP30 and pico W micropython

Hi I have set up a Pico w with the pico 3 slot breakout garden. The MICS6814 gas sensor and the SGP30 are in the i2c slots. I am kind of lost in all the different github pages. I flashed the pico with the appropriate micropython version and I can run python scripts on the pico W in Thonny On github I can see this page : GitHub - pimoroni/breakout-garden: Documentation, software, and examples for the Breakout Garden ecosystem. which has several examples but none for the MICS6814. Regardless, I ran the “wget” command and subsequent process. The command “sudo ./install” terminates with the message “sorry I couldn’t find any breakouts”. Anyway in the breakout-garden-master folder there are no sub-folders for the above 2 breakouts. Do I need to get the software modules from somewhere else ? Any ideas to get me moving forward ? thanks and regards

If the breakout has Micro Python support, the libraries will all be in the custom Pimoroni uf2 file.
For the Micro Python example files, you go here,
pimoroni-pico/micropython/examples at main ¡ pimoroni/pimoroni-pico (github.com)
For the MICS6814
pimoroni-pico/micropython/examples/breakout_mics6814 at main ¡ pimoroni/pimoroni-pico (github.com)
and the SGP30 here,
pimoroni-pico/micropython/examples/breakout_sgp30 at main ¡ pimoroni/pimoroni-pico (github.com)

Pay attention to what i2c pins are used in the demo, you may have to edit / change the file to make it work.

Hi Thanks for your reply which got me restarted nicely. I have an assembly consisting of 1 PICO W, 1 PICO breakout garden, 1 MICS6814 breakout in I2C slot 1 and 1 SGP30 breakout in I2C slot 2. I combined the python scripts for the individual demos into one script and all seems to run fine. I get outputs in Thonny from both sensors. (As the readout logic for both sensors is in the same “while true” loop, the readouts are interlaced on each cycle) What surprises me is that there is no place in the micropython script to encode the I2C addresses. This seems to be happening automatically. Additional surprise - both sensors are running OK using the same pins. Is this normal ? Additionally can you point me to a source describing the interpretation of the sensor readouts ? Regards

You can have multiple devices on the i2c bus, as long as no two devices have the same address. The address of the device is preset, usually listed on the back side of the breakout. Some will let you change it via a jumper.
The pins used by the Pico are set in the following code.

PINS_BREAKOUT_GARDEN = {"sda": 4, "scl": 5}
PINS_PICO_EXPLORER = {"sda": 20, "scl": 21}

i2c = PimoroniI2C(**PINS_BREAKOUT_GARDEN)

The above uses sda 4 and scl 5. You’ll likely have to Google the right term to get some info on what the readings mean.
Or have a look in the Learn section for tutorials.
Getting Started with Enviro+ (pimoroni.com)

Hi Again thanks for the response and the info. I have the 2 sensors working nicely in the pico garden base on a pico w communicating with an mqtt broker (Mosquitto) over wifi. An issue persists however; perhaps others on the forum can help. The setup : 1- both the SGP30 and the MICS6814 are inserted into the Pico garden base, 2- the micropython script combines the logic to read these sensors a single “while true” loop. The implication is that in each loop of the script it reads the SGP30, publishes the results to mqtt, then reads the MICS6814 and publishes the results to mqtt. The issue : the script terminates with mqtt error 3 after a variable time period ranging from a few minutes to several hours. Suspecting the issue could be an overload on the mqtt broker I have introduced substantial time delays between the mqtt “client.publish” commands for the respective sensors. But no luck, However running one sensor only in this setup seems to be fine - not terminating after more than 36 hours. (this setup is using umqtt.simple2.py) Thanks and regards

Are you able to share your code that you’re using, the forum maybe able to help further.

Use the “prefomatted text” button so that is indents correctly. 😀

Hi Here is the code sample. Includes the connection to wifi and to the mqtt broker. Also includes the functions to manipulate the led on the MICS6814 though not stricly necessary. The client.publish commands are in the ‘line protocol’ format used by telegraf for imports into an influxdb timer series database.

import time
from pimoroni_i2c import PimoroniI2C
from breakout_mics6814 import BreakoutMICS6814
from breakout_sgp30 import BreakoutSGP30
import network
from umqtt.simple2 import MQTTClient

SSID = 'redacted'
PWD = 'redacted'
mqtt_server = 'redacted'
client_id = 'redacted'
mqttuser = 'redacted'
mqttpwd = 'redacted'

wlan =  network.WLAN(network.STA_IF)

def connectWifi():
    wlan.active(True)
    wlan.connect(SSID,PWD)
    max_wait = 10
    while max_wait > 0:
        if wlan.status() < 0 or wlan.status() >3:
            break
        max_wait -=1
        print('waiting for connection % secs' %max_wait)
        time.sleep(1)
    if wlan.status() != 3:    
        print('network connection has failed')
    else:
        print('connected after % secs' %max_wait)
        status =  wlan.ifconfig()
        print ('ip = ' +status[0] )

def mqtt_connect():
    client = MQTTClient(client_id, mqtt_server, user= mqttuser, password = mqttpwd, keepalive=3600)
    client.connect()
    print('Connected to %s MQTT Broker'%(mqtt_server))
    return client

def reconnect():
    print('Failed to connect to the MQTT Broker. Reconnecting...')
    time.sleep(5)
    machine.reset()

connectWifi()

try:
    client = mqtt_connect()
except OSError as e:
    reconnect()

OUTPUT_FREQUENCY = 0.5

# initialize MICS
PINS_BREAKOUT_GARDEN = {"sda": 4, "scl": 5}
PINS_PICO_EXPLORER = {"sda": 20, "scl": 21}

i2cmics = PimoroniI2C(**PINS_BREAKOUT_GARDEN)
gas = BreakoutMICS6814(i2cmics)
gas.set_brightness(1.0)

# Initialise SGP30

PINS_BREAKOUT_GARDEN = {"sda": 4, "scl": 5}  # i2c pins 4, 5 for Breakout Garden
PINS_PICO_EXPLORER = {"sda": 20, "scl": 21}  # Default i2c pins for Pico Explorer

i2csgp = PimoroniI2C(**PINS_BREAKOUT_GARDEN)
sgp30 = BreakoutSGP30(i2csgp)
print("SGP30 initialised - about to start measuring without waiting")
sgp30.start_measurement(False)
id = sgp30.get_unique_id()
print("Started measuring for id 0x", '{:04x}'.format(id[0]), '{:04x}'.format(id[1]), '{:04x}'.format(id[2]), sep="")

# From CPython Lib/colorsys.py
def hsv_to_rgb(h, s, v):
    if s == 0.0:
        return v, v, v
    i = int(h * 6.0)
    f = (h * 6.0) - i
    p = v * (1.0 - s)
    q = v * (1.0 - s * f)
    t = v * (1.0 - s * (1.0 - f))
    i = i % 6
    if i == 0:
        return v, t, p
    if i == 1:
        return q, v, p
    if i == 2:
        return p, v, t
    if i == 3:
        return p, q, v
    if i == 4:
        return t, p, v
    if i == 5:
        return v, p, q

h = 0 # for MICS6814
j = 0 # for sgp30
last_output = time.time()

while True:
    #  for MICs6814

    oxd = gas.read_oxidising()
    #print ("type for oxd : " ,type(oxd))
    red = gas.read_reducing()
    nh3 = gas.read_nh3()
    readings = gas.read_all()
    r, g, b = [int(255 * c) for c in hsv_to_rgb(h / 360.0, 1.0, 1.0)]  # rainbow magic

    if time.time() - last_output > OUTPUT_FREQUENCY:
        print("MICS readings : OX: {} Red: {} NH3: {}  All: {} ".format(oxd, red, nh3, readings))
        tgraf_OX = "home,tag1=MICS6814,tag2=OX ox="  +str(oxd) 
        client.publish('MICS6814/OX', tgraf_OX)
        tgraf_RED = "home,tag1=MICS6814,tag2=RED red="  +str(red)
        client.publish('MICS6814/RED', tgraf_RED)
        tgraf_NH3 = "home,tag1=MICS6814,tag2=NH3 nh3="  +str(nh3)
        client.publish('MICS6814/NH3', tgraf_NH3)
        last_output = time.time()

    gas.set_led(r, g, b)

    h += 1
    time.sleep(1.0)
# for SGP30 
    j += 1
    air_quality = sgp30.get_air_quality()
    eCO2 = air_quality[BreakoutSGP30.ECO2]
    seCO2 = str(eCO2)
    TVOC = air_quality[BreakoutSGP30.TVOC]
    sTVOC = str (TVOC)
    #print  ("type for eCO2 : " , type(eCO2))
    #print  ("type for seCO2 : " , type(seCO2))
    air_quality_raw = sgp30.get_air_quality_raw()
    H2 = air_quality_raw[BreakoutSGP30.H2]
    ETHANOL = air_quality_raw[BreakoutSGP30.ETHANOL]
    
    print("SGP30 readings : ", j, " : CO2 ", eCO2, " TVOC ", TVOC, ", raw ", H2, " ", ETHANOL, sep="")
    tgraf_CO2 = "home,tag1=SGP30,tag2=CO2 co2=" +seCO2       #publish lux to mqtt.
    client.publish('SGP30/CO2', tgraf_CO2)
    tgraf_TVOC = "home,tag1=SGP30,tag2=TVOC tvoc=" +sTVOC
    client.publish('SGP30/TVOC', tgraf_TVOC)
    tgraf_H2 = "home,tag1=SGP30,tag2=H2 h2="  +str(H2)
    client.publish('SGP30/H2', tgraf_H2)
    tgraf_ETH = "home,tag1=SGP30,tag2=ETH eth="  +str(ETHANOL)
    client.publish('SGP30/ETH', tgraf_ETH)
    if j == 30:
        print("Resetting device")
        sgp30.soft_reset()
        time.sleep(0.5)
        print("Restarting measurement, waiting 15 secs before returning")
        sgp30.start_measurement(True)
        print("Measurement restarted, now read every second")

    time.sleep(1.0)
    


Thanks for sharing the code. I’m no expert, lets get that clear straight off the bat. I’ve had a similar set up in the past using the PicoW breakout garden with those (and other breakouts) Though, the broker was homeassistant managed, as was also influxDB. There’s no guarantee any of my suggestions will definitively solve your issue.

In the mqtt_connect() def the keep alive is set to 3600 seconds. To my mind at least, that is possibly too high. Around 30 seconds should be enough. As client.publish() will connect each time it needs to, AFAIK.

Looking at a description of mqtt error codes an error code of 3 is listed as: Connection Refused: Server Unavailable. Suggesting that the issue may be on the other end. Is there any value in checking the logs of the mqtt broker or influxdb?

There could also be some value in using static timings as opposed to time.time() statements. They work sure. Simply put without an IDE or a RTC available the picow doesn’t really know the concept of time. Have you tried using fixed time.sleep(value in seconds) to see if it resolves the issue?

Thanks for the observations. I’ll follow up specifically on the keep-alive parameter and the mqtt logs. However, I seem to have discovered the source of the problem somewhat by accident.
In the script which crashed the following statement was present :

        client.publish('SGP30/ETH', str(ETHANOL).encode())

This is not a correct format for the influxdb line protocol. When I uploaded the script in the previous message, I noticed this issue and changed it in both the script in the forum message and the script running on the pico. So readers of the previous message could not have seen this issue. The replacement lines follow.

        tgraf_ETH = "home,tag1=SGP30,tag2=ETH eth="  +str(ETHANOL)
        client.publish('SGP30/ETH', tgraf_ETH)

Since making this change, the script has run without crashing for about 24 hours. I apologize for asking for help on a problem already fixed (even though unknown at the time).

1 Like

No need to apologise at all, we’re all learners. Happy accidents are the best kind. Excellent that you have it working. 👍

1 Like