Inky_pHAT Weather Station
I here would like to describe a very simple and compact, Raspberry Pi Zero-based weather station, which displays the values measured by a BME280 temperature/pressure/humidity sensor on a Pimoroni Inky pHAT e-paper/e-ink display. To allow the connection of sensors and the pHAT to the GPIO of the Pi I placed a Pimorini Pico HAT hacker with two female headers attached between the GPIO and the display. The device has been used to attach several sensors, so the BME280 version described here is just an example.
Unlike LCD displays, e-ink displays keep the image even if power has been switched off. Therefore they are a very good solution if you want to display information that is updated just from time to time, especially to build low energy devices. The major benefit of the monochrome/black version of the Inky pHAT is that updating the display takes just about one second, instead of ten to fifteen seconds required by the three-color versions. See movie.
Adafruit's Blinka library allows to run Circuit Python code on the Raspberry Pi, and Circuit Python samples for a wide variety of sensors are available from Adafruit. A detailed description how to install Blinka and the Circuit Python codes can be found at the Adafruit website. The libraries I tested so far (BMP280, BME280, TSL2591, TCS34785, VEML7065, ...) were working very well, while there were minor problems in some of the example codes.
BME280 is a sensor to measure temperature, humidity and atmospheric pressure. BMP280 breakouts are available from many vendors, including Adafruit, but I here was using a cheap Chinese version. Please be aware that these are using different i2c addresses (Adafruit: 0x77, others: 0x76).
The breakout is connected to the Pi by i2c, and reading the sensor is very simple using the library and example code.
.
Materials Used
A Raspberry Pi Zero, with a male header attached. But any Raspberry Pi version would do.
A Pimoroni Inky pHAT, black/monochrome version, 25€|22£|20US$, at Pimoroni.
A Pimoroni Pico HAT hacker, 2.50€|2£, with two female headers attached, one of them a booster header with longer pins. I have build two different versions, see description below.
A BME280 breakout, AZ Delivery via Amazon.de @ 7.50 €, with header attached.
Elongation jumper cables
Optional:
A USB power pack, for mobile applications
A housing for the Pi or the device (not shown here)
Assembly
- Solder the female headers to the Pico HAT hacker. Before soldering, check for correct orientation.
I have build two version of this, for different purposes. One with the down facing booster header placed in the front row and a normal, up/facing header in the back row, and a version with the down facing booster header in the back row, and a right-angle female header in the front row. See images.
The first version allows to attach and exchange sensors and cables very easy, while the version with the inward facing header does allow to enclose Pi, sensor and Inky pHAT into a housing.
Alternatively you may solder the cables connecting GPIO and sensor directly to the Pico HAT hacker and/or solder the Pico HAT hacker directly to the GPIO pins. In any case use the minimal amount of solder required. - Solder the header to the sensor, if required.
- Stack the modified Pico HAT hacker unit on the Pi, then add the Inky pHAT. If required, insert some support, e.g. A foam block or stand-offs, for the Inky pHAT.
- Attach the cables and the sensor, using the 3V, GND, SDA and SCL ports.
Not all sensors will survive 5V, so please check before you connect them to 5V ports. - Install the Blinka library, then install the Circuit Python BME280 library from Adafruit.
- Install the Inky pHAT library from Pimoroni.
- Install the example Python code described in a later step and attached to this instructable.
- Run the code.
Using the Device
There are two options to use the device.
The code as shown here shall be started using a screen attached, but then could run without.
With minor modifications to the code you may use crontab to perform measurements at defined time points. This would allow to reduce power consumption even further. Excellent descriptions how to use crontab can be found elsewhere.
In conjunction with a power pack you can build a mobile device and use it to measure the conditions inside or outside, in the fridge, in the sauna, your humidor, the wine cellar, in a plane, ….
Using a Zero W you may not only display the values on the display, but also send them to a server or your website via WLAN, as described elsewhere.
The BME280 Script
As mentioned before, you need to install the Adafruit Blinka and Circuit Python BME280 libraries as well as the Pimoroni Inky pHAT library.
The code first initializes the sensor and Inky pHAT, then reads the temperature, pressure and humidity values from the sensor and displays them on screen and e-ink display. Using the time.sleep() command, measurements are taken every minute. Adjust as required. By setting a language parameter, you may change the language used to display the results.
Using the Inky pHAT e-ink display, you first build the image to be displayed in memory before it finally is transferred to the screen using the inkyphat.show() command. The Inky pHAT library is simplifying the process, offering commands to draw and format text, lines, rectangles, circles or use background images.
In addition to the measured values, the time of measurement is displayed as well.
Please keep in mind that the script as well as the libraries are written in Python 3, so open and run using Py3 IDLE or equivalent.
# A script for the bme280 temperature/pressure/humidity sensor (non-Adafruit version)<br># and the inky pHAT - black version # # version Dec 01 2018, Dr H # # Requires Adafruit Blinka and Circuit Python BME280 libraries # and the Pimoroni Inky pHAT library import time import datetime import board import busio from adafruit_bme280 import Adafruit_BME280 from adafruit_bme280 import Adafruit_BME280_I2C import inkyphat import sys from PIL import ImageFont inkyphat.set_colour('black') # for b/w inky phat inkyphat.set_rotation(180) # turn display 180° font1 = ImageFont.truetype(inkyphat.fonts.FredokaOne, 27) # Select standard font font2 = ImageFont.truetype(inkyphat.fonts.FredokaOne, 19) # Select standard font data # lang ="DE" # set language parameter, default ("") -> english lang ="EN" i2c = busio.I2C(board.SCL, board.SDA) bmp = Adafruit_BME280_I2C(i2c, address=0x76) # default i2c address (for Adafruit BMP280) 0x77 (default), 0x76 for chinese breakout) #set reference pressure # required for altitute calculation, please adjust. Standard value 1013.25 hPa # manual input: #reference_hPa =input ("Enter reference pressure in hPa: ") # or # set pressure at starting time as reference, e.g. for relative height measurements time.sleep (1) # wait a second before 1st measurement j= 0 pres_norm_sum = 0 while j in range (5): # take five measurements to define reference value pres_norm_sum = pres_norm_sum + bmp.pressure j= j+1 time.sleep (1) reference_hPa=(pres_norm_sum/j) # set inital measurement as reference point to enable height measurements bmp.sea_level_pressure = float (reference_hPa) print () while True: #runs forever, modify for crontab-version # measured values t=bmp.temperature p=bmp.pressure h=bmp.humidity a=bmp.altitude # calculated by adafruit library from pressure #timestamp ts = datetime.datetime.now() # timestamp ts0_EN ='{:%Y-%m-%d}'.format(ts) # timestamp - date, EN format ts0_DE ='{:%d.%m.%Y}'.format(ts) # timestamp - date, German format ts1='{:%H:%M:%S}'.format(ts) # timestamp - time tmp = "{0:0.1f}".format(t) pre = "{0:0.1f}".format(p) hyg = "{0:0.1f}".format(h) alt = "{0:0.1f}".format(a) tText = "Temp.: " pText_EN = "Pressure: " pText_DE = "Luftdruck: " hText_EN = "Humidity: " hText_DE = "rel. LF: " aText_EN = "Altitude: " aText_DE = "Höhe üNN: " # exakt: ü. NHN, über Normal Höhen Null if (lang =="DE"): ts0 = ts0_DE aText = aText_DE pText = pText_DE hText = hText_DE else: # default english ts0 = ts0_EN aText = aText_EN pText = pText_EN hText = hText_EN # print values to display print (ts) print (tText, tmp, "°C") print (pText, pre, " hPa") print (hText, hyg, " %") print (aText, alt, " m") print () # print values to Inky pHAT t1 = 5 # tab 1, frist column, simplifies optimization of layout t2 = 110 # tab 2, second column inkyphat.clear() inkyphat.text((t1, 0), ts0, inkyphat.BLACK, font2) # write timestamp date inkyphat.text((t2, 0), ts1, inkyphat.BLACK, font2) # write timestamp time inkyphat.line ((t1,25, 207,25), 1,3) # draw a line inkyphat.text((t1, 30), tText, inkyphat.BLACK, font2) inkyphat.text((t2, 30), (tmp + "°C"), inkyphat.BLACK, font2) inkyphat.text((t1, 55), pText, inkyphat.BLACK, font2) inkyphat.text((t2, 55), (pre + " hPa"), inkyphat.BLACK, font2) inkyphat.text((t1, 80), hText, inkyphat.BLACK, font2) inkyphat.text((t2, 80), (hyg + " %"), inkyphat.BLACK, font2) # alternatively display calculated height # inkyphat.text((t1, 80), aText, inkyphat.BLACK, font2) # inkyphat.text((t2, 80), (alt + " m"), inkyphat.BLACK, font2) inkyphat.show() time.sleep(51) # wait some seconds before next measurements, +19 sec per cycle inkyphat.clear() # empty Inky pHAT display procedure, inkyphat.show() # silence for crontab-version
Downloads
The BMP280 Script
The BMP280 is very similar to the BME280 sensor, but just measures temperature and pressure. The scripts are very similar, but you need different Circuit Python libraries. Here instead of the humidity a calculated height, based on a reference pressure, is displayed.
Attached you find the script.