kopia lustrzana https://github.com/pimoroni/pimoroni-pico
Pico Enviro+: More examples.
rodzic
4ffb94e1ad
commit
31fc56816e
|
@ -0,0 +1,85 @@
|
||||||
|
# Pico Enviro+ MicroPython Examples <!-- omit in toc -->
|
||||||
|
|
||||||
|
- [PicoGraphics](#picographics)
|
||||||
|
- [BME688](#bme688)
|
||||||
|
- [PMS5003 Particulate Sensor](#pms5003-particulate-sensor)
|
||||||
|
- [Non-Wireless Examples](#non-wireless-examples)
|
||||||
|
- [BME688 sensor](#bme688-sensor)
|
||||||
|
- [Button Test](#button-test)
|
||||||
|
- [Enviro All](#enviro-all)
|
||||||
|
- [Enviro All (Basic)](#enviro-all-basic)
|
||||||
|
- [LCD](#lcd)
|
||||||
|
- [Light](#light)
|
||||||
|
- [Mic](#mic)
|
||||||
|
- [Particle](#particle)
|
||||||
|
- [Wireless Examples](#wireless-examples)
|
||||||
|
- [Enviro All (MQTT)](#enviro-all-mqtt)
|
||||||
|
|
||||||
|
## PicoGraphics
|
||||||
|
|
||||||
|
You can draw on Pico Enviro+'s display using our tiny PicoGraphics display library.
|
||||||
|
- [PicoGraphics MicroPython function reference](../../modules/picographics)
|
||||||
|
|
||||||
|
## BME688
|
||||||
|
|
||||||
|
The 4-in-1 BME688 environmental sensor on Pico Enviro+ measures temperature, humidity, pressure and gas.
|
||||||
|
- [BME68X MicroPython function reference](../breakout_bme68x)
|
||||||
|
|
||||||
|
## PMS5003 Particulate Sensor
|
||||||
|
|
||||||
|
The examples that use the [optional particulate sensor](https://shop.pimoroni.com/products/pms5003-particulate-matter-sensor-with-cable) require separate drivers - you can install them from PyPi by searching for 'pms5003-micropython' in Thonny's 'Tools > Manage Packages'
|
||||||
|
|
||||||
|
- [PMS5003 MicroPython library](https://github.com/pimoroni/pms5003-micropython)
|
||||||
|
|
||||||
|
## Non-Wireless Examples
|
||||||
|
|
||||||
|
### BME688 sensor
|
||||||
|
[bme688_sensor.py](bme688_sensor.py)
|
||||||
|
|
||||||
|
Reads from the BME688 environmental sensor and shows temperature, humidity and pressure on the display.
|
||||||
|
|
||||||
|
### Button Test
|
||||||
|
[button_test.py](button_test.py)
|
||||||
|
|
||||||
|
This example shows you a simple, non-interrupt way of reading Pico Enviro+'s buttons with a loop that checks to see if buttons are pressed.
|
||||||
|
|
||||||
|
### Enviro All
|
||||||
|
[enviro_all.py](enviro_all.py)
|
||||||
|
|
||||||
|
An advanced example that reads from all the sensors on Pico Enviro+ (including the particulate sensor) and displays the results on screen. Press A and B to turn the backlight on and off, and press X and Y to switch between sensor mode and graphic equaliser mode!
|
||||||
|
|
||||||
|
### Enviro All (Basic)
|
||||||
|
[enviro_all_basic.py](enviro_all_basic.py)
|
||||||
|
|
||||||
|
This basic example shows how to read from all the sensors on Pico Enviro+ (plus the optional particulate sensor). Prints results to the REPL only.
|
||||||
|
|
||||||
|
### LCD
|
||||||
|
[lcd.py](lcd.py)
|
||||||
|
|
||||||
|
LCD demo with bouncy balls.
|
||||||
|
|
||||||
|
### Light
|
||||||
|
[light.py](light.py)
|
||||||
|
|
||||||
|
Reads the light/proximity sensors and displays the results on screen.
|
||||||
|
|
||||||
|
### Mic
|
||||||
|
[mic.py](mic.py)
|
||||||
|
|
||||||
|
Reads the microphone and displays a waveform on screen.
|
||||||
|
|
||||||
|
### Particle
|
||||||
|
[particle.py](particle.py)
|
||||||
|
|
||||||
|
Reads from the (optional) particulate sensor and displays the results on screen.
|
||||||
|
|
||||||
|
## Wireless Examples
|
||||||
|
|
||||||
|
The wireless examples need `network_manager.py` and `WIFI_CONFIG.py` from the `common` directory to be saved to your Pico W. Open up `WIFI_CONFIG.py` in Thonny to add your wifi details (and save it when you're done).
|
||||||
|
|
||||||
|
For MQTT, you'll need to install `micropython-mqtt.simple` using Thonny's 'Tools' > 'Manage Packages'.
|
||||||
|
|
||||||
|
### Enviro All (MQTT)
|
||||||
|
[enviro_all_mqtt.py](enviro_all_mqtt.py)
|
||||||
|
|
||||||
|
This example reads from all the sensors on Pico Enviro+ (plus the optional particulate sensor) and posts the results into an MQTT broker.
|
|
@ -0,0 +1,288 @@
|
||||||
|
import time
|
||||||
|
from machine import Pin, UART
|
||||||
|
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 adcfft import ADCFFT
|
||||||
|
# comment out the next line if no particulate sensor
|
||||||
|
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 sensor mode and graphic equaliser 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 graphic_equaliser():
|
||||||
|
m_arr = [0 for _ in range(16)]
|
||||||
|
i = 0
|
||||||
|
|
||||||
|
adcfft.update()
|
||||||
|
m = 0
|
||||||
|
for x in range(5, 240):
|
||||||
|
v = adcfft.get_scaled(x, 144)
|
||||||
|
m = max(m, v)
|
||||||
|
v = min(239, v)
|
||||||
|
v = 239 - v
|
||||||
|
display.line(x - 5, v, x - 5, 239)
|
||||||
|
m_arr[i] = min(255, m)
|
||||||
|
i += 1
|
||||||
|
if i >= len(m_arr):
|
||||||
|
i = 0
|
||||||
|
ms = int(sum(m_arr) / len(m_arr))
|
||||||
|
led.set_rgb(0, ms, 0)
|
||||||
|
|
||||||
|
|
||||||
|
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
|
||||||
|
|
||||||
|
|
||||||
|
def describe_light(lux):
|
||||||
|
"""Convert light level in lux to descriptive value."""
|
||||||
|
if lux < 50:
|
||||||
|
description = "dark"
|
||||||
|
elif 50 <= lux < 100:
|
||||||
|
description = "dim"
|
||||||
|
elif 100 <= lux < 500:
|
||||||
|
description = "light"
|
||||||
|
elif lux >= 500:
|
||||||
|
description = "bright"
|
||||||
|
return description
|
||||||
|
|
||||||
|
|
||||||
|
def draw_hist(results_array):
|
||||||
|
result_index = 0
|
||||||
|
for result in results_array:
|
||||||
|
display.set_pen(YELLOW)
|
||||||
|
display.rectangle(2 * result_index, 240 - result.pm_ug_per_m3(10), 2, 240)
|
||||||
|
display.set_pen(MAGENTA)
|
||||||
|
display.rectangle(2 * result_index, 240 - result.pm_ug_per_m3(2.5), 2, 240)
|
||||||
|
display.set_pen(BLUE)
|
||||||
|
display.rectangle(2 * result_index, 240 - result.pm_ug_per_m3(1.0), 2, 240)
|
||||||
|
result_index += 1
|
||||||
|
|
||||||
|
|
||||||
|
# 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)
|
||||||
|
|
||||||
|
# set up ADCFFT library to read mic with fast fourier transform
|
||||||
|
adcfft = ADCFFT()
|
||||||
|
|
||||||
|
# configure the PMS5003 for Enviro+
|
||||||
|
# comment out this section if no particulate sensor
|
||||||
|
pms5003 = PMS5003(
|
||||||
|
uart=UART(1, tx=Pin(8), rx=Pin(9), baudrate=9600),
|
||||||
|
pin_enable=Pin(3),
|
||||||
|
pin_reset=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(200, 200, 0)
|
||||||
|
BLUE = display.create_pen(0, 0, 200)
|
||||||
|
FFT_COLOUR = display.create_pen(255, 0, 255)
|
||||||
|
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 equaliser 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 = "sensors"
|
||||||
|
display.set_backlight(BRIGHTNESS)
|
||||||
|
time.sleep(0.2)
|
||||||
|
elif button_y.is_pressed:
|
||||||
|
mode = "equaliser"
|
||||||
|
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
|
||||||
|
|
||||||
|
# read LTR559
|
||||||
|
ltr_reading = ltr.get_reading()
|
||||||
|
lux = ltr_reading[BreakoutLTR559.LUX]
|
||||||
|
prox = ltr_reading[BreakoutLTR559.PROXIMITY]
|
||||||
|
|
||||||
|
# read particulate sensor and put the results into the array
|
||||||
|
# comment out if no PM sensor
|
||||||
|
data = pms5003.read()
|
||||||
|
results.append(data)
|
||||||
|
if (len(results) > 120): # Scroll the result list by removing the first value
|
||||||
|
results.pop(0)
|
||||||
|
|
||||||
|
if heater == "Stable" and ltr_reading is not None:
|
||||||
|
led.set_rgb(0, 0, 0)
|
||||||
|
|
||||||
|
# draw some stuff on the screen
|
||||||
|
display.set_pen(BLACK)
|
||||||
|
display.clear()
|
||||||
|
|
||||||
|
# draw particulate graph on screen, comment out if no PM sensor
|
||||||
|
draw_hist(results)
|
||||||
|
|
||||||
|
# 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"rh {corrected_humidity:.0f}%", 0, 75, WIDTH, scale=3)
|
||||||
|
display.text(f"{pressure_hpa:.0f}hPa", 0, 125, WIDTH, scale=3)
|
||||||
|
display.text(f"{lux} lux", 0, 175, WIDTH, scale=3)
|
||||||
|
|
||||||
|
# draw the second column of text
|
||||||
|
display.text(f"{describe_humidity(corrected_humidity)}", 125, 75, WIDTH, scale=3)
|
||||||
|
display.text(f"{describe_pressure(pressure_hpa)}", 125, 125, WIDTH, scale=3)
|
||||||
|
display.text(f"{describe_light(lux)}", 125, 175, 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 == "equaliser":
|
||||||
|
display.set_pen(BLACK)
|
||||||
|
display.clear()
|
||||||
|
display.set_pen(FFT_COLOUR)
|
||||||
|
display.text("mic", 0, 0, WIDTH, scale=3)
|
||||||
|
graphic_equaliser()
|
||||||
|
display.update()
|
|
@ -0,0 +1,80 @@
|
||||||
|
import time
|
||||||
|
from machine import Pin, ADC, UART
|
||||||
|
from pimoroni import RGBLED
|
||||||
|
from breakout_bme68x import BreakoutBME68X, STATUS_HEATER_STABLE
|
||||||
|
from pimoroni_i2c import PimoroniI2C
|
||||||
|
from breakout_ltr559 import BreakoutLTR559
|
||||||
|
from pms5003 import PMS5003
|
||||||
|
|
||||||
|
"""
|
||||||
|
This basic example shows how to read from all the sensors on Enviro+.
|
||||||
|
(plus the optional particulate sensor)
|
||||||
|
Prints results to the REPL.
|
||||||
|
"""
|
||||||
|
|
||||||
|
# change this to adjust temperature compensation
|
||||||
|
TEMPERATURE_OFFSET = 3
|
||||||
|
|
||||||
|
# set up the LED
|
||||||
|
led = RGBLED(6, 7, 10, invert=True)
|
||||||
|
led.set_rgb(255, 0, 0)
|
||||||
|
|
||||||
|
# set up the Pico'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)
|
||||||
|
|
||||||
|
# setup analog channel for microphone
|
||||||
|
MIC_PIN = 26
|
||||||
|
mic = ADC(Pin(26))
|
||||||
|
|
||||||
|
# configure the PMS5003 for Enviro+
|
||||||
|
pms5003 = PMS5003(
|
||||||
|
uart=UART(1, tx=Pin(8), rx=Pin(9), baudrate=9600),
|
||||||
|
pin_enable=Pin(3),
|
||||||
|
pin_reset=Pin(2),
|
||||||
|
mode="active"
|
||||||
|
)
|
||||||
|
|
||||||
|
while True:
|
||||||
|
# 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))
|
||||||
|
|
||||||
|
# read LTR559
|
||||||
|
ltr_reading = ltr.get_reading()
|
||||||
|
lux = ltr_reading[BreakoutLTR559.LUX]
|
||||||
|
prox = ltr_reading[BreakoutLTR559.PROXIMITY]
|
||||||
|
|
||||||
|
# read mic
|
||||||
|
mic_reading = mic.read_u16()
|
||||||
|
|
||||||
|
# read particle sensor
|
||||||
|
particulate_reading = pms5003.read()
|
||||||
|
|
||||||
|
if heater == "Stable" and ltr_reading is not None:
|
||||||
|
led.set_rgb(0, 0, 0)
|
||||||
|
print(f"""
|
||||||
|
Temperature = {corrected_temperature} °C
|
||||||
|
Humidity = {corrected_humidity} %
|
||||||
|
Pressure = {pressure/100} hPa
|
||||||
|
Gas = {gas}
|
||||||
|
Lux = {lux}
|
||||||
|
Mic = {mic_reading}
|
||||||
|
Particulates (1.0) = {particulate_reading.pm_ug_per_m3(1.0)} ug/m3
|
||||||
|
Particulates (2.5) = {particulate_reading.pm_ug_per_m3(2.5)} ug/m3
|
||||||
|
Particulates (10) = {particulate_reading.pm_ug_per_m3(10)} ug/m3
|
||||||
|
""")
|
||||||
|
else:
|
||||||
|
# light up the LED red if there's a problem with the BME688 or LTR559 sensor readings
|
||||||
|
led.set_rgb(255, 0, 0)
|
||||||
|
|
||||||
|
time.sleep(1.0)
|
|
@ -0,0 +1,177 @@
|
||||||
|
import time
|
||||||
|
from machine import Pin, ADC, UART
|
||||||
|
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
|
||||||
|
import umqtt.simple
|
||||||
|
import WIFI_CONFIG
|
||||||
|
from network_manager import NetworkManager
|
||||||
|
import uasyncio
|
||||||
|
|
||||||
|
"""
|
||||||
|
This example reads from all the sensors on Enviro+.
|
||||||
|
(plus the optional particulate sensor)
|
||||||
|
Posts results via MQTT.
|
||||||
|
"""
|
||||||
|
|
||||||
|
# change this to adjust temperature compensation
|
||||||
|
TEMPERATURE_OFFSET = 3
|
||||||
|
|
||||||
|
# MQTT broker settings
|
||||||
|
CLIENT_ID = "EnviroPlus"
|
||||||
|
SERVER_ADDRESS = "broker_IP_goes_here"
|
||||||
|
MQTT_USERNAME = "broker_username_goes_here"
|
||||||
|
MQTT_PASSWORD = "broker_password_goes_here"
|
||||||
|
UPDATE_INTERVAL = 60 # how often to post MQTT data, in seconds
|
||||||
|
|
||||||
|
|
||||||
|
def status_handler(mode, status, ip):
|
||||||
|
display.set_pen(BLACK)
|
||||||
|
display.clear()
|
||||||
|
display.set_pen(WHITE)
|
||||||
|
display.text("Network: {}".format(WIFI_CONFIG.SSID), 10, 10, scale=2)
|
||||||
|
status_text = "Connecting..."
|
||||||
|
if status is not None:
|
||||||
|
if status:
|
||||||
|
status_text = "Connection successful!"
|
||||||
|
else:
|
||||||
|
status_text = "Connection failed!"
|
||||||
|
|
||||||
|
display.text(status_text, 10, 30, scale=2)
|
||||||
|
display.text("IP: {}".format(ip), 10, 60, scale=2)
|
||||||
|
display.update()
|
||||||
|
|
||||||
|
|
||||||
|
# set up wifi
|
||||||
|
network_manager = NetworkManager(WIFI_CONFIG.COUNTRY, status_handler=status_handler)
|
||||||
|
|
||||||
|
# set up the display
|
||||||
|
display = PicoGraphics(display=DISPLAY_ENVIRO_PLUS)
|
||||||
|
display.set_backlight(1.0)
|
||||||
|
|
||||||
|
# set up the LED
|
||||||
|
led = RGBLED(6, 7, 10, invert=True)
|
||||||
|
led.set_rgb(255, 0, 0)
|
||||||
|
|
||||||
|
# set up the buttons
|
||||||
|
button_a = Button(12, invert=True)
|
||||||
|
button_b = Button(13, 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)
|
||||||
|
|
||||||
|
# set up analog channel for microphone
|
||||||
|
mic = ADC(Pin(26))
|
||||||
|
|
||||||
|
# configure the PMS5003 for Enviro+
|
||||||
|
pms5003 = PMS5003(
|
||||||
|
uart=UART(1, tx=Pin(8), rx=Pin(9), baudrate=9600),
|
||||||
|
pin_enable=Pin(3),
|
||||||
|
pin_reset=Pin(2),
|
||||||
|
mode="active"
|
||||||
|
)
|
||||||
|
|
||||||
|
# sets up MQTT
|
||||||
|
mqtt_client = umqtt.simple.MQTTClient(client_id=CLIENT_ID, server=SERVER_ADDRESS, user=MQTT_USERNAME, password=MQTT_PASSWORD)
|
||||||
|
|
||||||
|
# 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)
|
||||||
|
|
||||||
|
WIDTH, HEIGHT = display.get_bounds()
|
||||||
|
display.set_font("bitmap8")
|
||||||
|
|
||||||
|
# some other variables we'll use to keep track of stuff
|
||||||
|
current_time = 0
|
||||||
|
mqtt_time = 0
|
||||||
|
mqtt_success = False
|
||||||
|
e = "Wait a minute"
|
||||||
|
|
||||||
|
while True:
|
||||||
|
# connect to wifi
|
||||||
|
uasyncio.get_event_loop().run_until_complete(network_manager.client(WIFI_CONFIG.SSID, WIFI_CONFIG.PSK))
|
||||||
|
|
||||||
|
# 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))
|
||||||
|
|
||||||
|
# read LTR559
|
||||||
|
ltr_reading = ltr.get_reading()
|
||||||
|
lux = ltr_reading[BreakoutLTR559.LUX]
|
||||||
|
prox = ltr_reading[BreakoutLTR559.PROXIMITY]
|
||||||
|
|
||||||
|
# read mic
|
||||||
|
mic_reading = mic.read_u16()
|
||||||
|
|
||||||
|
# read particle sensor
|
||||||
|
particulate_reading = pms5003.read()
|
||||||
|
|
||||||
|
if heater == "Stable" and ltr_reading is not None:
|
||||||
|
led.set_rgb(0, 0, 0)
|
||||||
|
current_time = time.ticks_ms()
|
||||||
|
if (current_time - mqtt_time) / 1000 >= UPDATE_INTERVAL:
|
||||||
|
# then do an MQTT
|
||||||
|
try:
|
||||||
|
mqtt_client.connect()
|
||||||
|
mqtt_client.publish(topic="EnviroTemperature", msg=str(corrected_temperature))
|
||||||
|
mqtt_client.publish(topic="EnviroHumidity", msg=str(corrected_humidity))
|
||||||
|
mqtt_client.publish(topic="EnviroPressure", msg=str(pressure / 100))
|
||||||
|
mqtt_client.publish(topic="EnviroGas", msg=str(gas))
|
||||||
|
mqtt_client.publish(topic="EnviroLux", msg=str(lux))
|
||||||
|
mqtt_client.publish(topic="EnviroMic", msg=str(mic_reading))
|
||||||
|
mqtt_client.publish(topic="EnviroParticulates1_0", msg=str(particulate_reading.pm_ug_per_m3(1.0)))
|
||||||
|
mqtt_client.publish(topic="EnviroParticulates2_5", msg=str(particulate_reading.pm_ug_per_m3(2.5)))
|
||||||
|
mqtt_client.publish(topic="EnviroParticulates10", msg=str(particulate_reading.pm_ug_per_m3(10)))
|
||||||
|
mqtt_client.disconnect()
|
||||||
|
mqtt_success = True
|
||||||
|
mqtt_time = time.ticks_ms()
|
||||||
|
led.set_rgb(0, 50, 0)
|
||||||
|
except Exception as e:
|
||||||
|
print(e)
|
||||||
|
mqtt_success = False
|
||||||
|
led.set_rgb(255, 0, 0)
|
||||||
|
else:
|
||||||
|
# light up the LED red if there's a problem with MQTT or sensor readings
|
||||||
|
led.set_rgb(255, 0, 0)
|
||||||
|
|
||||||
|
# turn off the backlight with A and turn it back on with B
|
||||||
|
# things run a bit hotter when screen is on, so we're applying a different temperature offset
|
||||||
|
if button_a.is_pressed:
|
||||||
|
display.set_backlight(1.0)
|
||||||
|
TEMPERATURE_OFFSET = 5
|
||||||
|
time.sleep(0.5)
|
||||||
|
elif button_b.is_pressed:
|
||||||
|
display.set_backlight(0)
|
||||||
|
TEMPERATURE_OFFSET = 3
|
||||||
|
time.sleep(0.5)
|
||||||
|
|
||||||
|
# draw some stuff on the screen
|
||||||
|
display.set_pen(BLACK)
|
||||||
|
display.clear()
|
||||||
|
display.set_pen(WHITE)
|
||||||
|
display.text("Posting Enviro+ sensor data to Home Assistant via MQTT", 10, 10, WIDTH, scale=3)
|
||||||
|
if mqtt_success is True:
|
||||||
|
current_time = time.ticks_ms()
|
||||||
|
display.set_pen(GREEN)
|
||||||
|
display.text(f"Last MQTTed {(current_time - mqtt_time) / 1000:.0f} seconds ago", 10, 130, WIDTH, scale=3)
|
||||||
|
else:
|
||||||
|
display.set_pen(RED)
|
||||||
|
display.text(e, 10, 130, WIDTH, scale=3)
|
||||||
|
display.update()
|
||||||
|
|
||||||
|
time.sleep(1.0)
|
Ładowanie…
Reference in New Issue