This project started due to the smoke haze that enveloped our area during the 2019 and 2020 bushfires. I wanted something to check the air quality of my home and maybe find areas where it needed better sealing. In addition, the BMP280 sensor was on special, so it was built into the project as well. Given how easy it has become to use a Pi Zero, I've developed this as a quick and easy tool to be able to determine whether there's any haze or contaminants which are present in the area this is located in remotely, which can then be forwarded anywhere in the world.
Environment Monitor – Version Two
Bill of Materials
- Raspberry Pi Zero WH
- Enviro Sensor
- Air Quality Sensor and Breadboard Adapter
- BMP280
- Polycarbonate Enclosure - From Jaycar
Version One - Portable
The first version of this project used a PMS5003 and a BMP280 sensor connected to a Raspberry Pi Zero. The Pi was set up as a WiFi hotspot, which a phone or tablet could connect to read the sensor data. This meant the sensor could be used anywhere regardless of internet access or phone network.
Version Two – Fixed Installation
The second version came about due to a post on the Core Electronics Forum about the Pimoroni Enviro Board. The board looked impressive with a large number of different sensor types. It also had a direct connection to the PMS5003 particle sensor. This project will be described here.
In researching the Enviro board, a post on the Pimoroni Forum linked to a GitHub web page. EnviroPlusWeb. This changed the direction of the project because the EnviroPlusWeb page provided the Python code and HTML to access all the sensors on the Enviro board. All the software hard work had been done.
Placing the BME280 sensor on the Enviro board means it measures the temperature around the Raspberry Pi Zero and not the ambient room temperature. Hence, external BMP280 was added in an attempt to resolve this issue.
Note: In my experience, Pimoroni produces excellent products that work well with a high quality of manufacture. BUT, schematics are non-existent and the tutorials and software help is often lacking. They seem to rely on the maker community to provide this information. Other companies like Adafruit and Sparkfun provide a huge amount of help in using their products; so, for me, they are the preferred manufacturers.
The plan was to install the device on a wall in the garage, hence the style of case chosen. This also meant it would have easy access to the home WiFi network.
Design
The enclosure was chosen so the display could be easily read and could be mounted on a wall. Placing a finger (or other objects) over the light sensor activates the proximity detector and the program then steps through the sensor readings on the display. This allows a quick check of the readings and shows the device is working.
The addition of the BMP280 was in an attempt to measure the ambient room temperature rather than the Pi Zero processor. The Enviro BME280 is too close to the Pi for accurate room temperature readings. (the Pi gives off a lot of heat) The BMP280 was placed as far from the Pi board as possible with a small hole to allow outside air to the sensor. Yet it still indicates 2 degrees higher than the actual room temperature; even after allowing for the known heating issue. A future improvement might be a fan to remove air from the enclosure; possibly this would make the temperature readings reflect reality.
A hole was cut in the bottom of the enclosure to allow unimpeded airflow to the PMS5003. But it does compromise the weatherproofing of the case.
The power cable is a Micro USB to USB-A cable. It connects from the Pi USB power port to a 1A USB plug pack.
Construction
The electrical connections were very simple:
- USB cable connects to the Micro USB power port on the Pi
- Enviro 40 pin socket plugs into the Pi 40 pin header
- PMS5003 8 pin cable plugs into the Enviro PM socket
- BMP280 connects to the Enviro breakout header by a short cable (pins 3V3, SDA, SCL, GND)
The physical installation was a little more challenging. A small case was considered but it proved impossible to fit all the components and only by a small margin. The Pi was just a little too wide to fit nicely. (a 3D printer would be nice, to make the case fit the parts) The hole for the PMS5003 was cut in the lower part of the case. The case would still be waterproof on the top and the sides. Power cable entry is via the lower part of the case. The Enviro Board needs to be as close to the cover as possible so the proximity detector activates correctly. The USB cable connection to the Pi needs to clear the PMS5003 box. Hence, tall standoffs were used to position the Pi & Enviro as high in the case as possible. A right-angle header was soldered to the Enviro breakout for connection of the BMP280. (the only soldering required) ADDR 1 link on the BMP280 is cut so it has address 0x77. The BME280 address 0x76.
Note: With all of my projects I aim for something that can be assembled and disassembled as easily as possible. Allowing replacement of components if they fail or are damaged during testing.
Software
I began to write up the complete process I used to get the device working, but realized there was too much information that would not enhance the document. So the following is a shortened version with hopefully the relevant steps. Getting a Raspberry Pi to boot correctly from an SD card can be a challenge if you have never done it before. Setting up the Pi and installing the libraries; are detailed in many other places on the internet and won't be replicated here. I use PuTTY to SSH to the Pi and FileZilla to transfer files. Sublime Text is an excellent editor for programming languages. My development platform is Windows 10.
- SD card initial setup:
- The current version of Raspbian loaded on an SD card to be run headless.
- A static IP address was assigned for the Pi.
- raspi-config used to set password, hostname, enable interfaces, etc
- Install libraries:
- Enviro
- PMS5003
- BMP280 (the Adafruit Library works best in my opinion)
- Load / Develop Software:
- The software uses the Python programming language
- Python Flask Web Server delivers two HTML files to web browsers
- Main Files (In .zip below):
- enviro2.py - python program
- index.html - main web page
- readings.html - called to display the data in chart format
- Ancillary Files:
- Roboto-Regular.ttf - LCD font
- style.css – HTML styles used by index.html
- Start on boot
- Add the following lines to the end of /etc/rc.local before exit 0 to start the program upon Pi power up or reboot.
sudo i2cdetect -y 1 cd /home/pi python3 enviro2.py
EnviroPlusWeb by Nophead on GitHub was the starting point for software development. This software worked perfectly the first time, giving a nice display on the OLED and an excellent web page chart. I highly recommend the EnviroPlusWeb software to anyone using an Enviro Board as a starting point. It is well written and produces a reasonable display with little effort.
The OLED display was nice but in my opinion, there was too much displayed on one screen and the font size was too small. Also, the Python code did not do what I wanted.
The Python code was changed significantly adding routines I had already developed for other projects and version 1 of this project.
The HTML code was changed only slightly, I am still figuring out how it all works. The chart displays all sensors at the same time but I would like the ability to select which sensor I want to display.
The Python code introduced threading; a concept I had not used in Python at the time. I changed the code to spawn three processes rather than the single one the original code did.
The last part of the code starts with the Python Flask web server. I learned from this also. Specifying 0.0.0.0 as the IP address means the server will use the IP assigned to Pi by the router. Previously I had hardcoded the IP address.
Processes Running on the Pi
- Sensor thread – reads sensors every second, averages over 5 minutes then saves to file. A new file is started for a new day.
- LCD thread – detects proximity activation and displays current sensor data. Each screen will display for 0.5 seconds then cycle to the next as long as the proximity is active or it will display the current screen for 30 seconds then turn the screen off.
- Terminal thread – provides sensor data in text format to a terminal connected to the Pi.
- Flask Web Server – provides a web page chart to any device that connects to the server.
Testing
Initial testing was simple Python routines to read the Enviro sensors and display the data. Confidence testing so to speak. The Pimoroni library was used to do this.
Once the Python code and Html were working as desired the device was placed in the garage and left to run for over a month. It worked as expected, the chart showed varying conditions in the garage over time.
A KWS-V20 USB monitor showed the device draws between 140 and 170mA when running and over 240mA when the WiFi is active. Power used for 40h 34m was 6502mAh giving an average current of 160mA. Battery operation is not really an option when running the Pi Zero full time.
A nice utility to check I2C devices present.
sudo i2cdetect -y 1 0 1 2 3 4 5 6 7 8 9 a b c d e f 00: -- -- -- -- -- -- -- -- -- -- -- -- -- 10: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 20: -- -- -- 23 -- -- -- -- -- -- -- -- -- -- -- -- 30: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 40: -- -- -- -- -- -- -- -- -- 49 -- -- -- -- -- -- 50: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 60: -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- -- 70: -- -- -- -- -- -- 76 77
0x23 = Light / Proximity detector
0x49 = Gas Sensor, ADC
0x76 = BME280
0x77 = BMP280
Notes:
The PMS5003 samples particle concentration every 2.3 seconds but the data is sent every second to the serial port. Readings upon start-up can be inaccurate for the first 30 seconds or so.
The gas sensor can take up to 10 minutes or more to stabilize. The readings from this are resistance values and in a home environment, it is impossible to calibrate the sensor. It is only an indication of a change in levels not parts per million of the 3 gas types measured.
Suggested formulae for calculating parts per million:
red_in_ppm = math.pow(10, -1.25 * math.log10(red_rs/red_r0) 0.64) oxi_in_ppm = math.pow(10, math.log10(oxi_rs/oxi_r0) - 0.8129) nh3_in_ppm = math.pow(10, -1.8 * math.log10(nh3_rs/nh3_r0) - 0.163)
where:
red_rs, oxi_rs, nh3_rs are the current sensor values.
red_r0, oxi_r0, nh3_r0 are the sensor values at controlled ambient conditions.
The sensor data is averaged and saved to a file every 5 seconds, a new file is created for a new day. These files are about 75KBytes in size and are continuously added to the SD card in /home/pi/data. The file name contains the year and number of the day in the year. (ie 2020_359) Given enough time the available space on the SD card would run out. With the 16GB SD cards I use, it would take over 300 years, not really a problem.
Conclusion
In my opinion, the Enviro would make an excellent STEM teaching tool. Students could learn how various sensors work and how to make use of the data they provide.
As a device for accurately measuring environmental conditions, it fails in a number of areas. The most accurate part is the PMS5003 and that is a separate device. Temperature and Humidity are greatly affected by the proximity of the Pi. The gas sensor returns only resistance values. Parts per million would have to be calculated in software and compensation applied considering how these sensors drift with time and other environmental conditions. Accurate calibration is not possible in a home environment. The color OLED display is a nice addition but contributes significantly to the overall cost of the device.
If you want to learn about measuring environmental conditions and are willing to pay the cost; this device is a good starting point. But as an accurate measuring device it falls short.
I have learned much by getting the two versions of this project working and am happy with the way the device performs in general. It will sit in the garage recording environmental conditions which can be accessed via a web page. If a situation like the fires of 2019/2020 occurs again it may be moved to measure conditions in other parts of the house.
I hope that you've found this project informative!
Resources and Repositories
https://learn.pimoroni.com/tutorial/sandyj/getting-started-with-enviro-plus
https://learn.pimoroni.com/tutorial/sandyj/enviro-plus-and-luftdaten-air-quality-station
https://forums.pimoroni.com/t/enviroplus-assistance/11595
https://github.com/pimoroni/enviroplus-python/tree/master/examples
https://github.com/nophead/EnviroPlusWeb