Adding a bigger display to Enviro+

Hello,

I would like to add a bigger display to an Enviro+ hat. I see that there are GPIO holes for a header on the hat itself. Any idea if this could be done ? Anyone else tried it and could maybe point me to more info ?

Thanks for your time.

I don’t own that hat, but I am running modified versions of that code on multi display setups. A second display could be added, it will be a bit of work though. Those holes for a header aren’t for a display, not an SPI display anyway.

Enviro Plus at Raspberry Pi GPIO Pinout

Thank you for your reply and pointing out that the holes are not for what I thought they could be.
Would you have time to expand a bit more on what kind of work needs to be done ?

You’re going to need to get access to the GPIO pins needed to wire up another display.
One way to do it is as follows.
Adafruit Perma Proto Bonnet Mini Kit - Pimoroni
2x20 pin Female GPIO Header for Raspberry Pi - Pimoroni
As a bonus, it will add some distance between the Pi and Enviro, reducing heat transfer from the Pi.
Then wire up you display to the SPI pins on the Pi. If you use SPI0 CE0 code modification is minimal.

Thank you.I already have on order the proto board and I also have the header. They were intended for a different project but I’ll try them. The display I have is based on the ST7789 driver. Do you think it will work ? Do I have to call the ST7789 library for it ?

Should work. Yes, you will have to call up the ST7789 library for it.
Is it a Pimoroni Display? A link to it would help?

Sorry,life got it the way. It is not a Pimoroni display,rather a cheap chinese one I had around based on the ST7789 driver. Or so I thought. My colors were inverted so I had to do some digging into the Adafruit’s library but I got it.
I am not entirely satisfied because my display doesn’t get initialized after a reboot. If I have the a copy of the script running at reboot then I can call another version that will display the data on the bigger display. For now it’ll have to stay like that for a while. I will eventually get a good Pimoroni display but I’ve looked and the only one that is around 2" is the hat with buttons. I don’t mind that,but maybe a bit too complicated for what I want.
Thanks again for your help, if I make any good progress I’ll post.

2 Likes

What sensors are you using on the Enviro+? The other way to go is just a BME280 and a display.
You can ignore the Buttons and LED on the Display Hat. You don’t have to use them, or even wire them up. I have two Pico Display Packs wired up like that.

I’m using all but the PMS5003. Interesting thought about the display hat,I was thinking that too. I’ll get one soon.
I didn’t know about the pico packs,now I see it. I should browse the site more I guess.
How would I go about splitting the info on the screens?

Awesome setup. Love it. Thank you for the detailed explanation and pictures,much appreciated. The code is very welcomed. I am better at hardware than software,so it will help me a lot. I do have pHat stacks and a black hck3r stack as well which I use right now for my temporary setup.
I like a bit bigger displays so I am thinking to use your idea with something a bit larger. I am interested on displaying the temp/humidity/gases data instead of weather. I’ll have to figure out how to modify the scripts provided by Pimoroni.
I have some code to study now :)

A lot of my code is modified Pimoroni examples. It’s where I unusually start.
That project evolved into a Pi Pico setup with two Pico Display Pack V2’s.
Pi Pico based Weather Station Project - Discussion / Projects - Pimoroni Buccaneers

The same could be done with two Pi Display Hat Mini’s. And as near as I can tell, you could use a Pico Display Pack with a Pi and vis versa. They both use 3V logic and the same driver chips.

I have plans to wire up a Pico Display Pack to a Pi, just have to find my round 2it. ;)
I have one of the original 240 x 135 Display Packs sitting there doing nothing. It’s my replacement for the Enviro’s 160 x 80 LCD. It’s close to the same width versus height ratio.
I’ll likely use something like this to mate the two.
Adafruit Perma-Proto 40-Pin Raspberry Pi Breadboard PCB Kit - with 2x2 - Pimoroni
It’s what I did here, it’s running Enviro+ code. It’s 3 displays instead of just one.


I thought I had a thread on this but can’t find it?

Found it. =)
Three display weather graphing setup - Discussion / Projects - Pimoroni Buccaneers

EDIT: That build is actually sitting in front of me on my computer desk. The barometric pressure is the one I watch the most. I live on the seacoast so it’s a big deal if it drops fast. A 2 mb drop in a 2 hour period is considered as dropping rapidly. That third display graphs a 2 hour period.

That is the post the sparked my idea of adding a bigger display. So,you’re that person :). Kudos on a great enhancement. I like the enviro hat as an idea of exploring the sensors and their capabilities. Even if the gas sensor is not the greatest a lot can be learned and the Pimoroni coding examples are a very good starting point.
Originally I wanted to do this exactly same setup but wanted a bit bigger displays. I do not have a zero but I do have a Pi 3b. If I run Bullseye can I use some of the code you are using here for these 3 ? I am inclined of trying the Pico display packs you mentioned.

Bullseye should be fine, I’m pretty sure that code is Python 3.

Hello aphanumeric,
I hope all is well. I was wondering if you have any idea on this issue. I’ve bought 3 mini Hats from Pimoroni to replicate your setup.
I have the Enviro+ HAT and when I connected 2 displays everything works,sort off,but I can sort it out.
When I try to conect to 3rd one I need to use port=1 on SPI to get 3 devices but that is where the ST7789 throws errors. Looks like port 1 somehow is not part of the driver ?
I am using the driver that Pimoroni has on their mini HAT page.
I’ve tried modifying the init.py from self spi mode = 0 to 1 but still no joy.

Here’s the error I get when trying to run the script :

File “/home/bursucel/Desktop/7735_7789_Eugen_combined.py”, line 38, in
disp0 = ST7789.ST7789(
File “/usr/local/lib/python3.9/dist-packages/ST7789/init.py”, line 123, in init
self._spi = spidev.SpiDev(port, cs)
FileNotFoundError: [Errno 2] No such file or directory

Looks to me that line 123 is calling for something not present ?

How did you solve this problem on your setup ?

Thanks. Not a rush at all,whenever you have time.

port=0 means your using SPI0
port=1 means your using SPI1
I went SPI1 because it supports 3 displays out of the box dtoverlay=spi1-3cs.
Your display has to be wired to the SPI bus your using in your code.
You can’t change how the Enviro+ Hat display is wired, not easily anyway.
I haven’t tried it, but “I think” you can use SPI0 “and” SPI1.

SPI0
GPIO 7, Pin 26, CE1
GPIO 8, Pin 24, CE0
GPIO 9, Pin 21, MISO
GPIO 10, Pin 19, MOSI
GPIO 11, Pin 23, SCLK

SPI1
GPIO 16, Pin 36, CE2
GPIO 17, Pin 11, CE1
GPIO 18, Pin 12, CE0
GPIO 19, Pin 35, MISO
GPIO 20, Pin 38, MOSI
GPIO 21, Pin 40, SCLK

/boot/config.txt

dtparam=spi=on

dtoverlay=spi1-1cs #1 chip select
dtoverlay=spi1-2cs #2 chip select
dtoverlay=spi1-3cs #3 chip select

SCLK - Serial ClocK
CE - Chip Enable (often called Chip Select)
MOSI - Master Out Slave In
MISO - Master In Slave Out
MOMI - Master Out Master In

Wall of code to follow:

#!/usr/bin/env python3

import os
import sys
import time
import colorsys
import logging
import ST7735
import RPi.GPIO as GPIO

from sys import exit
from PIL import Image
from PIL import ImageDraw
from PIL import ImageFont
from subprocess import PIPE, Popen
from fonts.ttf import RobotoMedium as UserFont
try:
    from smbus2 import SMBus
except ImportError:
    from smbus import SMBus
from bme280 import BME280

def Shutdown(channel):  
    os.system("sudo shutdown now -P")
    time.sleep(30)

GPIO.setmode(GPIO.BCM)  
GPIO.setwarnings(False)
GPIO.setup(24, GPIO.IN, pull_up_down = GPIO.PUD_UP)
GPIO.add_event_detect(24, GPIO.FALLING, callback = Shutdown, bouncetime = 2000)

logging.basicConfig(
    format='%(asctime)s.%(msecs)03d %(levelname)-8s %(message)s',
    level=logging.INFO,
    datefmt='%Y-%m-%d %H:%M:%S')

logging.info("""Displays readings from BME280 sensor
Press Ctrl+C to exit!
""")

bme280 = BME280()

disp0 = ST7735.ST7735(
    port=1,
    cs=0, 
    dc=19,
#    backlight=5, 
    rotation=90,
    spi_speed_hz=10000000
)

disp0.begin()

disp1 = ST7735.ST7735(
    port=1,
    cs=1, 
    dc=19,
 #   backlight=6, 
    rotation=90,
    spi_speed_hz=10000000
)

disp1.begin()

disp2 = ST7735.ST7735(
    port=1,
    cs=2, 
    dc=19,
  #  backlight=13, 
    rotation=90,
    spi_speed_hz=10000000
)

disp2.begin()

WIDTH = 160
HEIGHT = 80

img = Image.new('RGB', (WIDTH, HEIGHT), color=(0, 0, 0))
draw = ImageDraw.Draw(img)
path = os.path.dirname(os.path.realpath(__file__))
font_size = 20
font = ImageFont.truetype(UserFont, font_size)

message = ""

top_pos = 25

def display_text0(variable, data, unit):
    values[variable] = values[variable][1:] + [data]
    vmin = min(values[variable])
    vmax = max(values[variable])
    colours = [(v - vmin + 1) / (vmax - vmin + 1) for v in values[variable]]
    message = "{}:{:.0f}{}".format(variable[:11],data,unit)
    logging.info(message)
    draw.rectangle((0, 0, WIDTH, HEIGHT), (255, 255, 255))
    for i in range(len(colours)):
        colour = (1.0 - colours[i]) * 0.6
        r, g, b = [int(x * 255.0) for x in colorsys.hsv_to_rgb(colour, 1.0, 1.0)]
        draw.rectangle((i, top_pos, i + 1, HEIGHT), (r, g, b))
        line_y = HEIGHT - (top_pos + (colours[i] * (HEIGHT - top_pos))) + top_pos
        draw.rectangle((i, line_y, i + 1, line_y + 1), (0, 0, 0))

    draw.text((0, 0), message, font=font, fill=(0, 0, 0))
    disp0.display(img)

def display_text1(variable, data, unit):
    values[variable] = values[variable][1:] + [data]
    vmin = min(values[variable])
    vmax = max(values[variable])
    colours = [(v - vmin + 1) / (vmax - vmin + 1) for v in values[variable]]
    message = "{}:{:.0f}{}".format(variable[:11],data,unit)
    logging.info(message)
    draw.rectangle((0, 0, WIDTH, HEIGHT), (255, 255, 255))
    for i in range(len(colours)):
        colour = (1.0 - colours[i]) * 0.6
        g, r, b = [int(x * 255.0) for x in colorsys.hsv_to_rgb(colour, 1.0, 1.0)]
        draw.rectangle((i, top_pos, i + 1, HEIGHT), (r, g, b))
        line_y = HEIGHT - (top_pos + (colours[i] * (HEIGHT - top_pos))) + top_pos
        draw.rectangle((i, line_y, i + 1, line_y + 1), (0, 0, 0))

    draw.text((0, 0), message, font=font, fill=(0, 0, 0))
    disp1.display(img)

def display_text2(variable, data, unit):
    values[variable] = values[variable][1:] + [data]
    vmin = min(values[variable])
    vmax = max(values[variable])
    colours = [(v - vmin + 1) / (vmax - vmin + 1) for v in values[variable]]
    message = "{}:{:.0f}{}".format(variable[:11],data,unit)
    logging.info(message)
    draw.rectangle((0, 0, WIDTH, HEIGHT), (255, 255, 255))
    for i in range(len(colours)):
        colour = (1.0 - colours[i]) * 0.6
        g, r, b = [int(x * 255.0) for x in colorsys.hsv_to_rgb(colour, 1.0, 1.0)]
        draw.rectangle((i, top_pos, i + 1, HEIGHT), (r, g, b))
        line_y = HEIGHT - (top_pos + (colours[i] * (HEIGHT - top_pos))) + top_pos
        draw.rectangle((i, line_y, i + 1, line_y + 1), (0, 0, 0))

    draw.text((0, 0), message, font=font, fill=(0, 0, 0))
    disp2.display(img)    

last_page = 0

variables = ["Temperature",
             "Humidity",
             "Pressure"]

values = {}

for v in variables:
    values[v] = [1] * WIDTH

mode = 0
F = 0
D = 0

while True:

    
    if F < 161:
        F = F + 1 
    elif F >= 161:
        time.sleep(5)
        D = D + 1 
            
    if mode == 0:
        mode %= len(variables)
        last_page = time.time()
        unit = "C"
        data = bme280.get_temperature()
        display_text0(variables[mode], data, unit)
        mode = 1

    if mode == 1:
        mode %= len(variables)
        last_page = time.time()
        unit = "%"
        data = bme280.get_humidity()
        display_text1(variables[mode], data, unit)
        
    if D == 0:        
        mode = 2
    elif D > 0 and D < 9:
        mode = 0
    elif D == 9:
        mode = 2
        D = 0
    
    if mode == 2:
        mode %= len(variables)
        last_page = time.time()
        unit = "mb"
        data = bme280.get_pressure()
        display_text2(variables[mode], data, unit)
        mode = 0
   
# Last edited on Marct 4th 2021
# sudo pip3 install rv3028
# sudo pip3 install pimoroni-bme280 smbus
# curl https://get.pimoroni.com/st7735 | bash
# sudo pip3 install fonts
# sudo pip3 install font-roboto
# sudo nano /boot/config.txt
# add
# dtoverlay=spi1-3cs
# run crontab -e
# add
# @reboot python3 /home/pi/3LCD_THP.py &  

Thank you for your reply. With your help I think I figured it out. I had everything wired correctly but the installation of Enviro+ adds a line to config.txt that disables SPI1. Took me a few hours to work out that bug :) .Once I disabled that line,SPI1 started working properly.
The error I was getting was because it was disabled.
In my case the ST7789 init.py had to be modified as well because it was calling for 240 width and my displays are 320. That took another hour to figure out.
I do have a working model now. Next step, I would like to figure out how to drive the 3 screens on SPI1 and the included Enviro small screen on SPI0 and just put a message on that small one. I know there is a display script example from Pimoroni,it was too late yesterday to try everything.
Thanks again for your help, much appreciated.

This “might” help with the displaying text part.
My Pi 400 CPU info display - Discussion / Projects - Pimoroni Buccaneers

Thanks,I’ll have a look.