pimoroni / EnviroPlus-FeatherWing

CircuitPython library for the Enviro+ FeatherWing
https://shop.pimoroni.com/products/enviro-plus-featherwing
MIT License
10 stars 11 forks source link

Enviro+ tests #17

Open Bogdan50 opened 3 years ago

Bogdan50 commented 3 years ago

Hi, I have recently aquired the Enviro+ board and a feather M4 express from Adafruit. I have istalled the latest CircuitPython 6 and the latest circuit python library. After a few days, these are the results: -the bme280 works, the bme280_simple.py works as expected -the simple screen.py works as expected -the plotter example don't work but the label is added on the screen -the test_all.py will not complete unless I comment out the light/prox sensor code. the error reported is failure in I2C init -if comment out the code this is the result: 2020_11_22_05_16_23_PuTTY_inactive_

bme280 and sound detector work because they use the adafruit library and analog input i assume. I need some help going forward.

dglaude commented 3 years ago

Normally, the PMS5003 should work, but I must admit I have concentrate in the Adafruit library for that sensor: https://github.com/adafruit/Adafruit_CircuitPython_PM25 so you may want to give that a try. I am partially responsible for making this code more robust, and ported some of Pimoroni enhancement to it, so I am interested if something goes wrong with that code.

For the gas sensor, I have not used it in a while, but if I had to spend time on that part, I would give a try to @Gadgetoid new library: https://github.com/pimoroni/Pimoroni_CircuitPython_MICS6814

From memory, the gas sensor is just enabling the sensor, reading from three analogue input and doing some math. None of this is supposed to break in 6.0.0. I tested with 5.3 and early version of 6.0, but not since a long time.

Could you give one or both of those a try?

I have exactly the same hardware as you, so if time permit I can give it a new, but the future is in those new libraries and this repo should try to do the switch and provide new instruction.

Bogdan50 commented 3 years ago

I'm not sure how to install those. Running the setup.py install? I've uncommented the lines that enable the light sensor for more details of the failure source. 2020_11_24_03_30_19_COM9_PuTTY

dglaude commented 3 years ago

PM25 demo code in the Adafruit library likely default to their I2C sensor, but the one used in FeatherWing Enviro+ is UART.

So you have to look into code.py and modify. Typically Adafruit simpletest demo code do comment out alternative configuration (using other pin or other variation of the hardware, like SPI vs I2C).

dglaude commented 3 years ago

I made a "quick" with the stable 6.0.0 and latest libraries. To make it more or less reproducable, here is a log of the useful command I used. I focused on gas as that is easy to reproduce, and it works for me.

When you say that plotter only show the label, the default refresh time is to fill the screen in 24H so it is normal to only see the first pixel, but you can edit those exemple to refresh faster.

I'll try a few other exemple, but so far, so good for me.

unzip adafruit-circuitpython-bundle-6.x-mpy-20201124.zip 
cp -r adafruit-circuitpython-bundle-6.x-mpy-20201124/lib/adafruit_bus_device /media/dglaude/CIRCUITPY/lib/
cp -r adafruit-circuitpython-bundle-6.x-mpy-20201124/lib/adafruit_bme680.mpy /media/dglaude/CIRCUITPY/lib/
cp -r adafruit-circuitpython-bundle-6.x-mpy-20201124/lib/adafruit_st7735r.mpy /media/dglaude/CIRCUITPY/lib/
cp -r adafruit-circuitpython-bundle-6.x-mpy-20201124/lib/adafruit_display_text /media/dglaude/CIRCUITPY/lib/
unzip EnviroPlus-FeatherWing-1.0.zip 
cd lib/
cp -r . /media/dglaude/CIRCUITPY/lib/
cd ..
cp EnviroPlus-FeatherWing/examples/gas_sensor.py /media/dglaude/CIRCUITPY/
echo "import gas_sensor" > /media/dglaude/CIRCUITPY/code.py 

code.py output: Oxidising: 12840.577 Ohms Reducing: 165415.440 Ohms NH3: 43903.642 Ohms

cp EnviroPlus-FeatherWing/examples/plotter_gas.py /media/dglaude/CIRCUITPY/
echo "import plotter_gas" > /media/dglaude/CIRCUITPY/code.py

Draw label and the first value in the graph.

Bogdan50 commented 3 years ago

I did edit the polling interval from filling the whole screen to 1 second. But going back to the two libraries mentioned previously, could the culprit be the Python version 3.9 that I am using? Are you using 3.8 or 3.9?

dglaude commented 3 years ago

Ok, so with test_all.py I have a problem with I2C for ltr559. And this could be some change in CP 5 or 6 relative to I2C that is incompatible with the way I2C is done by Pimoroni...

cp -r adafruit-circuitpython-bundle-6.x-mpy-20201124/lib/adafruit_bme280.mpy /media/dglaude/CIRCUITPY/lib/
cp EnviroPlus-FeatherWing/examples/test_all.py /media/dglaude/CIRCUITPY/
echo "import test_all" > /media/dglaude/CIRCUITPY/code.py       

code.py output: Screen successfully set up! I2C Initialised! BME280 Tests Passed! Gas Sensor Tests Passed! Traceback (most recent call last): File "code.py", line 1, in File "test_all.py", line 80, in File "lib/pimoroni_ltr559/init.py", line 218, in init File "lib/i2cdevice/init.py", line 230, in get File "lib/i2cdevice/init.py", line 183, in read_register File "lib/i2cdevice/init.py", line 288, in _i2c_read File "lib/pimoroni_circuitpython_adapter/init.py", line 46, in read_i2c_block_data File "lib/pimoroni_circuitpython_adapter/init.py", line 40, in read_i2c_block_data TypeError: extra keyword arguments given

My best bet will be to get away from the old ltr559 and try the new library https://github.com/pimoroni/Pimoroni_CircuitPython_LTR559/

dglaude commented 3 years ago

Ok, so I went for test_all.py and removed the ltr part, and I have similar result as you (except that my PM25 is not making error).

PMS5003 Tests Passed! These tests failed: Oxidising gases reading out of expected range Reducing gases reading out of expected range NH3 gases reading out of expected range

I don't know what is the range of value to expect from that library, but the following assertion are the trigger for those error message.

softassert.softassert(lambda: 0 <= gas.read_all().oxidising <= 5, "Oxidising gases reading out of expected range")
softassert.softassert(lambda: 0 <= gas.read_all().reducing <= 5, "Reducing gases reading out of expected range")
softassert.softassert(lambda: 0 <= gas.read_all().nh3 <= 5, "NH3 gases reading out of expected range")
dglaude commented 3 years ago

The new LRT559 works great for me with ltr559_simpletest.py

git clone https://github.com/pimoroni/Pimoroni_CircuitPython_LTR559.git
cd Pimoroni_CircuitPython_LTR559/
cp Pimoroni_CircuitPython_LTR559/pimoroni_circuitpython_ltr559.py /media/dglaude/CIRCUITPY/lib/
cp Pimoroni_CircuitPython_LTR559/examples/ltr559_simpletest.py /media/dglaude/CIRCUITPY/
cp -r adafruit-circuitpython-bundle-6.x-mpy-20201124/lib/adafruit_register/media/dglaude/CIRCUITPY/lib/
echo "import ltr559_simpletest" > /media/dglaude/CIRCUITPY/code.py

What need to be done in this repo is to:

  1. Verify that the new API is more or less similar to the old one
  2. Stop using the lrt559 from EnviroPlus-FeatherWing
  3. Adapt example to use the new library
  4. Adapt the documentation, readme, ...
Bogdan50 commented 3 years ago

Yes, now both the prox and gas sensors work. I've switched the code to UART and the test reports it finds the sensor but no data: pm25_PuTTY

gas_PuTTY

lux PuTTY

I am very grateful for your patience, thank you.

dglaude commented 3 years ago

For your PM25, it could be a bad serial connection: the cable, the connector, the sensor. Maybe you should contact Pimoroni support, I am just a customer like you.

dglaude commented 3 years ago

But going back to the two libraries mentioned previously, could the culprit be the Python version 3.9 that I am using? Are you using 3.8 or 3.9?

Sorry, I am confused... you are using a "Feather M4 Express" so that would be running CircuitPython 6.0.0. Python, or CPython, this would run on your computer... it should not matter what version you use.

Bogdan50 commented 3 years ago

Regarding Python version, you are correct and I was confused, sorry. Also I am wrong about the PM25. I thought the sensor is on the board when one has to get it separately. https://shop.pimoroni.com/products/pms5003-particulate-matter-sensor-with-cable I don't have it but plan on getting it..

Bogdan50 commented 3 years ago

I've left the board running for a day or so and noticed that the temperature graph is not changing much. It looks like the board (maybe the screen) is generating heat and keeps the BME280 at a constant temperature. I took a pic of the startup period and it very clear that the temp is rising and then stabilizing around 34 degrees c. 20201129_220219 I know there is not much that can be done about this now. Or maybe lowering the screen intensity?

kevinjwalters commented 3 years ago

BTW, I got the standard combined plotter code running using Version 1.0 libraries on CircuitPython 6.0.0 on a Feather nRF52840 Express (without a PM sensor) earlier by using the change in https://github.com/pimoroni/circuitpython_adapter/commit/f062036d10c43af6946df5ab08a12c142017b0ba - that hasn't yet made its way into a release for this repository but I've started that discussion...

All of these devices with temperature sensors suffer from some degree of self-heating and from heating from components nearby. Many have noticed this with Adafruit boards (Adafruit Forums: Offering calibrated temperature property). It's interesting to note the micro:bit DAL has a temperature adjustment feature to allow for very basic compensation.

I've never looked through the Bosch datasheets but there's a very interesting comment on a YouTube video (TheHWcave: Review of Pimoroni's Enviro+ board - Part1 gas, temp., humidity, pressure and particulate matter) about these particular temperature sensors being designed to monitor the device temperature and not ambient air temperature. That's confimed in the replies in the YouTube comments.

I'm going to have a look at some other options for external temperature sensing. There's plenty of cheap, decent-looking options out there and they can be positioned well away from the board (and its convection currents). Let me know if you beat me to it.

Bogdan50 commented 3 years ago

Hey Kevin, The BME280 sensor in addition to pressure and temp, has also a humidity sensor. That would raise the question then, why would one need to monitor a device’s humidity? I think the board + display generate enough heat to keep the sensor at a constant, higher, temp. My main goal was to get pressure change charts with temp/hydro as bonuses.

dglaude commented 3 years ago

Maybe putting the sensor directly on the board was not such a smart choice. I believe that video is about the pHAT, but a Feather board is even smaller.

Another issue I have with the Feather is that the screen and the sensor are at the same place, so you can only monitor inside. Having the screen and a few button inside, and all the sensor on an external board would make sense.

Having a Stemma connector and a Stemma sensor a bit further could help. I have just order two temperature only Stemma, maybe I can compare the value of the build-in and the external sensor.

Bogdan50 commented 3 years ago

Yes David, I think that would help. I’m thinking maybe a heatsink on the Feather chip would help too.

dglaude commented 3 years ago

Wait, are you stacking the FeatherWing on top of the Feather? This is wrong, they should be "side by side" on a "doubler" or as far as possible on a "tripler" or more.

kevinjwalters commented 3 years ago

I'm stacking. I think any board like this will always have limitations on sensor placement but they are a good platform to start with and experiment. BTW, the gas sensors work best with controlled airflow. There might be some neat ways to using the pms5003 in an enclosure to create that flow.

I think I've worked out the pins and it looks like there's some spare, the names in brackets are Pimoroni's names.

    A0 (pin5) - MiCS6814 ammonia gas sensor
    A1 (pin6) - MiCS8614 reducing gas sensor
    A2 (pin7) - MiCS6814 oxidising gas sensor
    A3 (pin8) - analogue microphone
    A4 (pin9) - MiCS6814 enable
    D5 (pin19) - SPI bus screen command
    D6 (pin20) - SPI bus screen chip select
    D9 (pin21) - backlight (PWM)
    D10 (pin22) - PMS5003 enable
    D11 (pin23) - PMS5003 reset
    D12 (pin24) - LTR-559 interrupt (not supported in CircuitPython library) [added later]
    SCL (pin18) - I2C clock
    SDA (pin17) - I2C data
    SCK (pin11) - SPI bus clock
    MO (pin12) - SPI bus master out slave in
    MI (pin13) - SPI bus master in slave out
    TX (pin15) - PMS5003 receive (transmit from Feather)
    RX (pin14) - PMS5003 transmit (receive by Feather)
Bogdan50 commented 3 years ago

Yes, I have it stacked too, that's how Adafruit shows it on their page. But it is not permanent I can unplug the Enviro and test it on another proto board.

kevinjwalters commented 3 years ago

I plugged in a PMS5003 today and it works but it's pretty flaky. That's with the Version 1.0 download recommended in the docs.

I missed a pin on the previous list:

D12 (pin24) - LTR-559 interrupt (not supported in CircuitPython library)
dglaude commented 3 years ago

My experience with PMS5003 is that the serial connection is difficult to have right. Could be my cable, the sensor, or the FeatherWing. Maybe it is also because I tested a lot and also tested behaviour when connection is flaky and improving the UART code. So doing that I may have made it even more of an issue.

Right now I believe the best way to gather data from PMS5003 is to use the Adafruit Library and this PR: https://github.com/adafruit/Adafruit_CircuitPython_PM25/pull/13

It enable a mode where the PMS5003 will only send values when we send a request and this is a much better way than to try to sync with the constant push of frame of data.

Please give that a try and maybe give your feedback on the code or result. It works for me, but I cannot review the library.

kevinjwalters commented 3 years ago

@dglaude Yes, there is a problem with producer vs consumer rates here. I've attached a logic analyser and for one run I can see for plotters_combined.py the PMS5003 will spit data every 920ms but the program only reads every 1340ms (interval set to 1). My knowledge of CircuitPython's UART is limited at the moment but I think the data simply gets buffered up, then eventually fills the buffer (possbily default size of 64 bytes) and bytes are lost resulting either in partial frames or bad checksums. The checksum is a nice feature of the PMS5003 to reduce chance of using bogus data.

kevinjwalters commented 3 years ago

A bit of a rush job but I've put together Instructables: Using the Pimoroni Enviro+ FeatherWing With the Adafruit Feather NRF52840 Express to describe using the Feather nRF52840 Express with this board. I'm busy mid week but I'll see what I can do to get the PMS5003 comms into tip top shape.

Bogdan50 commented 3 years ago

Thank you Kevin. Regarding the serial data communications with the PMS5003, maybe it can be done asynchronously using RTS signal (if it has it). I've ordered the sensor but still haven't gotten it so I can't say if it only uses RX/TX lines to communicate.

kevinjwalters commented 3 years ago

There's no hardware flow control.

Bogdan50 commented 3 years ago

This is from the Pimoroni github python library for RaspberryPi: https://github.com/pimoroni/pms5003-python/blob/master/library/pms5003/__init__.py

It seems they are sitting in a loop and waiting for a signal from the sensor: line 125 sof = self._serial.read(1)

then read how many bytes where sent line 140 data = bytearray(self._serial.read(2)) # Get frame length packet

Not very efficient but maybe they can get away with it on a multi threaded cpu. Maybe we can use an input pin on the Feather to detect data on the serial bus.

dglaude commented 3 years ago

Thank you for the guide, I wish I could have read that earlier as I did not protect the gas sensor... I wonder if that was recommended by Pimoroni.

For the serial communication with the PMS5003, I believe the proper way is that Pending PR.

Bogdan50 commented 3 years ago

What do you mean by Pending PR David?

According to https://github.com/adafruit/Adafruit_CircuitPython_PM25/blob/master/adafruit_pm25/__init__.py the buffer is 32 bytes and they are waiting for the ASCII BM to identify the start of the buffer.

And, in the example provided, they are doing the same thing, sit in a 1 second loop reading the uart buffer. I wonder if it would miss pms5003 buffers if more time is spent in the loop doing other things like for example reading and displaying the other sensors.

dglaude commented 3 years ago

Black to that temperature issue, even with the Feather on the side, and so the MCU unlikely to hear the bme280, the reported temperature is completely off and too warm. PXL_20201226_012841720 PXL_20201226_071218741~2 This is taking a measurement every minute and comparing the on board BME with a StemmaQT attached much more precise temperature sensor PCT2075. I cannot prove it right now, but I believe it is the backlight that heat the enviro+. But without backlight the screen is unreadable. Notice also on the picture that I use a FeatherS2 powered by an ESP32S2 and that will give me WiFi without the conflict that we saw for the AirLift Feather Wing.

kevinjwalters commented 3 years ago

@dglaude You're ahead of me, I'd spotted that FeatherS2 but I knew I shouldn't buy one until I had time to use it!

I've got something like a humble TMP36 somewhere and I was going to give that a go on the temperature side of things. If you go analogue there's a reasonably-well-known issue with reading from multiple pins with high impedance sources and multiplexed inputs. This is very likely to happen with Enviro+ with analogue external temperature sensor as the Enviro+ board has analogue outputs. It gets a mention at the bottom of https://learn.adafruit.com/tmp36-temperature-sensor and is discussed in https://electronics.stackexchange.com/questions/67171/input-impedance-of-arduino-uno-analog-pins

kevinjwalters commented 3 years ago

For comparison, the CLUE suffers from heating from the backlight but it's not the only source. You have to scroll through the output but you can see a temperature drop from 30.88 to 28.74 in my second post on Adafruit Forums: CLUE temperature off a few degrees?.

I started the discussion Adafruit Forums: CLUE temperature off a few degrees? based off that and others who were disappointed by less-than-useful temperature readings. The BBC micro:bit DAL actually has a simple feature to subtract a value from the temperature to offer very primitive calibration/adjustment.

Bogdan50 commented 3 years ago

The gas sensor has 3 independent heaters. Maybe the heat is dissipating through the ground layer to the temp sensor?

dglaude commented 3 years ago

I confirm it is the heater(s) from the gas sensor that influence the most the temperature measured by the bme280 and the following trick seems to avoid the issue:

# Disable gas sensor.
from digitalio import DigitalInOut, Direction, Pull 
MiCS6814_enable = DigitalInOut(pimoroni_physical_feather_pins.pin9())
MiCS6814_enable.direction = Direction.OUTPUT
MiCS6814_enable=False

I also disabled the backlight (but maybe that was not needed) but here is the code for that trick:

pwm = pulseio.PWMOut(pimoroni_physical_feather_pins.pin21())
pwm.duty_cycle = 0

Now I need to decide what is the most important part of the Enviro+ between the Gas sensor and the temperature+pressure+humidity. But it seems that using both simultaneously is not an option.

But at least now the temperature of both sensor (the bme280 and the external pct2075).

Bogdan50 commented 3 years ago

That gas sensor is far more interesting. In conjunction with the PMS5003 sensor, it is providing much more interesting data. And the temperature is only marginally influencing pressure readings.

I tried the code, it does not work for me. First error was about the missing import pimoroni_physical_feather_pins. I added that to the working code of the 3 plotters. Basically this is what I was trying:

"""
plotter-bme280.py

Logs the temperature, humidity and pressure over 24hrs (by default)
"""

#interval = 540 # full screen of reading spans 24hrs
interval = 384 # uncomment for 1 reading per second
#interval = 60 # uncomment for 1 reading per minute
#interval = 3600 # uncomment for 1 reading per hour

import time
import displayio
import terminalio
import adafruit_bme280, board, busio, digitalio
import pimoroni_physical_feather_pins
from pimoroni_envirowing.screen import plotter

from adafruit_display_text import label

# Disable gas sensor.
MiCS6814_enable = digitalio.DigitalInOut(pimoroni_physical_feather_pins.pin9())
MiCS6814_enable.direction = digitalio.Direction.OUTPUT
MiCS6814_enable=False

# colours for the plotter are defined as rgb values in hex, with 2 bytes for each colour
red = 0xFF0000
green = 0x00FF00
blue = 0x0000FF

# set up the connection with the sensor
i2c = busio.I2C(board.SCL, board.SDA)
bme280 = adafruit_bme280.Adafruit_BME280_I2C(i2c, address=0x76)

# average global sea level pressure, for more accurate readings change this to your local sea level pressure (measured in hPa)
bme280.sea_level_pressure = 1013.25

# the max value is set to 70 as it is the screen height in pixels after the labels (top_space) (this is just to make a calculation later on easier)
splotter = plotter.ScreenPlotter([red, green, blue, red+green+blue], max_value=70, min_value=0, top_space=10)

# add a colour coded text label for each reading
splotter.group.append(label.Label(terminalio.FONT, text="{:0.1f} C".format(bme280.temperature), color=red, x=0, y=5, max_glyphs=15))
splotter.group.append(label.Label(terminalio.FONT, text="{:0.1f} hPa".format(bme280.pressure), color=green, x=50, y=5, max_glyphs=15))
splotter.group.append(label.Label(terminalio.FONT, text="{:0.1f} %".format(bme280.humidity), color=blue, x=120, y=5, max_glyphs=15))
#splotter.group.append(label.Label(terminalio.FONT, text="{:0.2f} m".format(bme280.altitude), color=red+green+blue, x=40, y=20, max_glyphs=15)) # uncomment for altitude estimation

while True:
    # take readings
    temperature = bme280.temperature
    pressure = bme280.pressure
    humidity = bme280.humidity
    #altitude = bme280.altitude # uncomment for altitude estimation

    # update the line graph
    splotter.update(
        # scale to 70 as that's the number of pixels height available
        splotter.remap(temperature, 0, 50, 0, 70),
        splotter.remap(pressure, 975, 1025, 0, 70),
        splotter.remap(humidity, 0, 100, 0, 70),
        #splotter.remap(altitude, 0, 1000, 0, 70) # uncomment for altitude estimation
    )

    # update the labels
    splotter.group[1].text = "{:0.1f} C".format(temperature)
    splotter.group[2].text = "{:0.1f} hPa".format(pressure)
    splotter.group[3].text = "{:0.1f} %".format(humidity)
    #splotter.group[4].text = "{:0.2f} m".format(altitude) # uncomment for altitude estimation
time.sleep(interval)
dglaude commented 3 years ago

Not sure what the problem is, need to try your code.

For physical pin, I made this for FeatherS2: https://github.com/pimoroni/physical_feather_pins/pull/4

My plan is to use the deep sleep function of CircuitPython on ESP32S2 to wake, gather data, upload to adafruit IO, and sleep.

I have to figure out the time to warm the gas sensor, so I could take the temperature before. I don't think I will use the screen as this would require remembering data during the sleep and the splotter code does not work like that.

Bogdan50 commented 3 years ago

I timed the heat up interval. It takes about 7 minutes before it starts to flatten out. The graph in the picture has the measuring interval of 10 seconds. 20201227_152624 1

Bogdan50 commented 3 years ago

The specs don't say how long before the sensor is ready for measurment. 1143_datasheet mics-6814 rev 8_2.pdf

dglaude commented 3 years ago

Ok, I had something strange in my code... and your version has it too. The screen goes black! But behind the scene, it get update, and I can see it because pressing the reset button show what is hidden.

So somehow, by setting this pin to false, it also turn the screen off: A4 (pin9) - MiCS6814 enable

But I was also playing with the backlight in test just before or after D9 (pin21) - backlight (PWM)

Did I confuse pin9 and D9? (remember, I made the pin mapping myself for the ESP32S2).

What Feather are you using for your test? Do we have the schematic of this board??? That could help (not that I can read them)

Bogdan50 commented 3 years ago

Adafruit Feather M4 Express, yes there is a schematic for it, here: https://cdn-learn.adafruit.com/assets/assets/000/057/242/original/arduino_compatibles_schem.png?1531010817

I take it back. A4 is pin 13. I got confused by the breakouts image. And my code is wrong don't use it. Just insert your code as you showed originally.

I can't find a schematic for the Enviro+ plus.

Bogdan50 commented 3 years ago

But I think it may not be possible to disable the heaters. If you look at the spec doc, they supply 5v through 3 resistors straight to 4 pins on the sensors. And looking at the bottom of Enviro+ I think I found those 3 resistors. 20201227_182320 1

kevinjwalters commented 3 years ago

I've probably power cycled the board 50 times now so this is rare but watch out for this one that affects the operation of the PMS5003: Pimoroni Forums: Enviro+ FeatherWing fails to produce 5V until power-cycled.

Bogdan50 commented 3 years ago

It would be nice to have a schematic of the Enviro+. There is a buck converter power supply on the Enviro, looking at the bottom.