Pico enviro+ buttons not playing ball

Hi all, total code noob here.

I am trying to create a script for my pico enviro+. I am using a combination of 2 of the example scripts, enviro_all.py and particle.py. These scripts both work fine in their original state.

I have my script displaying the information that I need but the buttons are not working correctly.

I have changed the enviro script to call the information from the particulate sensor when the button is pressed, in place of the equaliser script in the original example.

Here is what is happening:
When I start the enviro+ it loads the first screen which shows Temp, Humidity, pressure & Dewpoint.
When on that screen I can press buttons A & B to toggle the display on and off. I have X & Y set to switch between Particulates and Sensors (respectively).
When I press X, the display switches to particulates, as expected. However once on the particulates screen the buttons no longer work. I cannot toggle the screen on or off (A & B), nor can I switch back to the sensors screen. (Y)

Any help with this would be much appreciated.

Heres my code;

import time
import machine
from picographics import PicoGraphics, DISPLAY_ENVIRO_PLUS
from pimoroni import RGBLED, Button
from breakout_bme68x import BreakoutBME68X, STATUS_HEATER_STABLE
from pimoroni_i2c import PimoroniI2C
from breakout_ltr559 import BreakoutLTR559
from pms5003 import PMS5003

"""
This example reads from all the sensors on Enviro+.
(plus the optional particulate sensor)
Displays the results on screen.
Press A and B to turn the backlight on and off
Press X and Y to switch between particulate mode and sensor mode!
"""

# change this to adjust temperature compensation
TEMPERATURE_OFFSET = 3

BRIGHTNESS = 0.8

# light the LED red if the gas reading is less than 50%
GAS_ALERT = 0.5

def describe_pressure(pressure_hpa):
    """Convert pressure into barometer-type description."""
    if pressure_hpa < 970:
        description = "storm"
    elif 970 <= pressure_hpa < 990:
        description = "rain"
    elif 990 <= pressure_hpa < 1010:
        description = "change"
    elif 1010 <= pressure_hpa < 1030:
        description = "fair"
    elif pressure_hpa >= 1030:
        description = "dry"
    else:
        description = ""
    return description


def describe_humidity(corrected_humidity):
    """Convert relative humidity into good/bad description."""
    if 40 < corrected_humidity < 60:
        description = "good"
    else:
        description = "bad"
    return description

# set up the display
display = PicoGraphics(display=DISPLAY_ENVIRO_PLUS)

# set up the LED
led = RGBLED(6, 7, 10, invert=True)

# set up the buttons
button_a = Button(12, invert=True)
button_b = Button(13, invert=True)
button_x = Button(14, invert=True)
button_y = Button(15, invert=True)

# set up the Pico W's I2C
PINS_BREAKOUT_GARDEN = {"sda": 4, "scl": 5}
i2c = PimoroniI2C(**PINS_BREAKOUT_GARDEN)

# set up BME688 and LTR559 sensors
bme = BreakoutBME68X(i2c, address=0x77)
ltr = BreakoutLTR559(i2c)

# configure the PMS5003 for Enviro+
pms5003 = PMS5003(
    uart=machine.UART(1, tx=machine.Pin(8), rx=machine.Pin(9), baudrate=9600),
    pin_enable=machine.Pin(3),
    pin_reset=machine.Pin(2),
    mode="active"
)

# some constants we'll use for drawing
WHITE = display.create_pen(255, 255, 255)
BLACK = display.create_pen(0, 0, 0)
RED = display.create_pen(255, 0, 0)
GREEN = display.create_pen(0, 255, 0)
CYAN = display.create_pen(0, 255, 255)
MAGENTA = display.create_pen(200, 0, 200)
YELLOW = display.create_pen(255, 255, 0)
BLUE = display.create_pen(0, 0, 200)
GREY = display.create_pen(75, 75, 75)

WIDTH, HEIGHT = display.get_bounds()
display.set_font("bitmap8")

# some other variables we'll use to keep track of stuff

mode = "sensors"  # start off in sensor mode

# these values will get updated later on
min_temperature = 100.0
max_temperature = 0.0
min_gas = 100000.0
max_gas = 0.0

# array for storing particulate readings
results = []

# setup
led.set_rgb(255, 0, 0)
display.set_backlight(BRIGHTNESS)
display.set_pen(RED)
display.text("waiting for sensors", 0, 0, WIDTH, scale=3)
display.update()

# the gas sensor gives a few weird readings to start, lets discard them
temperature, pressure, humidity, gas, status, _, _ = bme.read()
time.sleep(0.5)
temperature, pressure, humidity, gas, status, _, _ = bme.read()
time.sleep(0.5)

while True:
    # turn off the backlight with A and turn it back on with B
    # switch between sensor and particulate mode with X and Y
    if button_a.is_pressed:
        display.set_backlight(BRIGHTNESS)
        time.sleep(0.2)
    elif button_b.is_pressed:
        display.set_backlight(0)
        time.sleep(0.2)
    elif button_x.is_pressed:
        mode = "part"
        display.set_backlight(BRIGHTNESS)
        time.sleep(0.2)
    elif button_y.is_pressed:
        mode = "sensors"
        display.set_backlight(BRIGHTNESS)
        time.sleep(0.2)

    if mode == "sensors":
        # read BME688
        temperature, pressure, humidity, gas, status, _, _ = bme.read()
        heater = "Stable" if status & STATUS_HEATER_STABLE else "Unstable"

        # correct temperature and humidity using an offset
        corrected_temperature = temperature - TEMPERATURE_OFFSET
        dewpoint = temperature - ((100 - humidity) / 5)
        corrected_humidity = 100 - (5 * (corrected_temperature - dewpoint))

        # record min and max temperatures
        if corrected_temperature >= max_temperature:
            max_temperature = corrected_temperature
        if corrected_temperature <= min_temperature:
            min_temperature = corrected_temperature

        # record min and max gas readings
        if gas > max_gas:
            max_gas = gas
        if gas < min_gas:
            min_gas = gas

        # convert pressure into hpa
        pressure_hpa = pressure / 100

        if heater == "Stable":
            led.set_rgb(0, 50, 0)

            # draw some stuff on the screen
            display.set_pen(BLACK)
            display.clear()

            # draw the top box
            display.set_pen(GREY)
            display.rectangle(0, 0, WIDTH, 60)

            # pick a pen colour based on the temperature
            display.set_pen(GREEN)
            if corrected_temperature > 30:
                display.set_pen(RED)
            if corrected_temperature < 10:
                display.set_pen(CYAN)
            display.text(f"{corrected_temperature:.1f}°c", 5, 15, WIDTH, scale=4)

            # draw temp max and min
            display.set_pen(CYAN)
            display.text(f"min {min_temperature:.1f}", 125, 5, WIDTH, scale=3)
            display.set_pen(RED)
            display.text(f"max {max_temperature:.1f}", 125, 30, WIDTH, scale=3)

            # draw the first column of text
            display.set_pen(WHITE)
            display.text(f"Humidity {corrected_humidity:.0f}", 0, 75, WIDTH, scale=3)
            display.text(f"{pressure_hpa:.0f} hPa", 0, 125, WIDTH, scale=3)
            display.text(f"Dewpoint {dewpoint:.2f}°c", 0, 175, WIDTH, scale=3)

            # draw the second column of text
            display.text(f"{describe_humidity(corrected_humidity)}", 170, 75, WIDTH, scale=3)
            display.text(f"{describe_pressure(pressure_hpa)}", 130, 125, WIDTH, scale=3)

            # draw bar for gas
            if min_gas != max_gas:
                # light the LED and set pen to red if the gas / air quality reading is less than 50%
                if (gas - min_gas) / (max_gas - min_gas) < GAS_ALERT:
                    led.set_rgb(255, 0, 0)
                    display.set_pen(RED)
                else:
                    display.set_pen(GREEN)

                display.rectangle(236, HEIGHT - round((gas - min_gas) / (max_gas - min_gas) * HEIGHT), 4, round((gas - min_gas) / (max_gas - min_gas) * HEIGHT))
                display.text("gas", 185, 210, WIDTH, scale=3)

            display.update()
            time.sleep(0.5)

    elif mode == "part":

        display = PicoGraphics(display=DISPLAY_ENVIRO_PLUS)
        display.set_backlight(1.0)

        # Set RGB Led
        led.set_rgb(50, 0, 50)

        # Drawing routines
        def draw_background():
            display.set_pen(BLACK)
            display.clear()
            display.set_pen(WHITE)
            display.text("PARTICULATES", 20, 10, scale=3)


        def draw_txt_overlay(sensor_data):
            display.set_pen(RED)
            display.text("PM1.0: {0}".format(sensor_data.pm_ug_per_m3(1.0)), 5, 60, scale=4)
            display.set_pen(YELLOW)
            display.text("PM2.5: {0}".format(sensor_data.pm_ug_per_m3(2.5)), 5, 100, scale=4)
            display.set_pen(GREEN)
            display.text("PM10: {0}".format(sensor_data.pm_ug_per_m3(10)), 5, 140, scale=4)


        while True:

            draw_background()
            data = pms5003.read()
            print(data)
            results.append(data)

            if (len(results) > 120):  # Scroll the result list by removing the first value
                results.pop(0)

            draw_txt_overlay(data)
            display.update()
            time.sleep(0.5)

I’m no expert but I’m thinking the while True loop inside a while True loop might be an issue? Maybe its getting stuck in the second while True loop?

2 Likes

Thank you so much. you were right about the second while true loop. I have removed that and shifted the remainder of the code about (removed no longer necessary indents) it is now working perfectly.

While true, it was required in its original code, it wasn’t needed here. :D

What is above the while True: gets run once. What is below it runs in a loop.
That code is still in the loop, now it’s just the one loop.

1 Like