Pi Zero 2 with e-Paper display - error when trying to make the display sleep

433 views Asked by At

I'm in the process of making a little stock tracker using a Pi Zero 2 and an e-Paper display. At the moment I've just got 1 button that when pressed cycles to the next stock, then also updates the display with that stocks information.
This all works, but as these displays aren't meant to be left with power for long periods I need to add in a sleep call after each display refresh. I added a button using gpiozero, added a sleep function at the end of my pressed() function and it all worked... once. The first time I press the button all goes smoothly, but the 2nd time it spits out an error. After some trial and error I discovered it's the sleep call that causes the issues.
My code is as follows:

#!/usr/bin/python
# -*- coding:utf-8 -*-
import sys
import os
picdir = 'pic'
libdir = os.path.join(os.path.dirname(os.path.dirname(os.path.realpath(__file__))), 'lib')
if os.path.exists(libdir):
    sys.path.append(libdir)

import logging
from waveshare_epd import epd2in13_V3
import time
from PIL import Image,ImageDraw,ImageFont
import traceback
import yfinance as yf
from gpiozero import Button
import keyboard

logging.basicConfig(level=logging.DEBUG)

button = Button(2)
pageNum = 0
pageMax = 2

def pressed():
    print("Pressed")
    global pageNum, pageMax
    
    if pageNum < pageMax:
        pageNum += 1
    elif pageNum >= pageMax:
        pageNum = 0
        
    amc = yf.Ticker("AMC")
    gme = yf.Ticker("GME")
    msft = yf.Ticker("MSFT")
        
    if pageNum == 0:
        print("GME selected")
        print(pageNum)
        stock = "GME"
        buy = gme.info['ask']
        sell = gme.info['bid']
        high = gme.info['dayHigh']
        low = gme.info['dayLow']
        opening = gme.info['open']
        current = gme.info['currentPrice']
    elif pageNum == 1:
        print("MSFT selected")
        print(pageNum)
        stock = "MSFT"
        buy = msft.info['ask']
        sell = msft.info['bid']
        high = msft.info['dayHigh']
        low = msft.info['dayLow']
        opening = msft.info['open']
        current = msft.info['currentPrice']
    elif pageNum == 2:
        print("AMC selected")
        print(pageNum)
        stock = "AMC"
        buy = amc.info['ask']
        sell = amc.info['bid']
        high = amc.info['dayHigh']
        low = amc.info['dayLow']
        opening = amc.info['open']
        current = amc.info['currentPrice']
        
    buyR = round(buy, 2)
    sellR = round(sell, 2) 
    highR = round(high, 2) 
    lowR = round(low, 2) 
    openingR = round(opening, 2) 
    currentR = round(current, 2) 

# Blank out rectangles
    draw.rectangle((2, 2, 125, 33), fill = 255)
    draw.rectangle((28, 37, 123, 90), fill = 255)
    draw.rectangle((151, 37, 247, 90), fill = 255)
    draw.rectangle((142, 94, 247, 119), fill = 255)
    
    draw.text((4, 0), str(stock), font = fnt_large, fill = 0)
    draw.text((28, 40), str(highR), font = fnt_small, fill = 0)
    draw.text((28, 66), str(lowR), font = fnt_small, fill = 0)
    draw.text((151, 40), str(buyR), font = fnt_small, fill = 0)
    draw.text((151, 66), str(sellR), font = fnt_small, fill = 0)
    draw.text((142, 93), str(currentR), font = fnt_med, fill = 0)
    
    epd.displayPartial(epd.getbuffer(image)) # Refresh the prices
    logging.info("Sleep from pressed()")
    epd.sleep()

button.when_pressed = pressed

try:
    logging.info("init and Clear")
    epd = epd2in13_V3.EPD()
    epd.init()
#    epd.Clear(0xFF)
    
    fnt_small = ImageFont.truetype(os.path.join(picdir, 'DejaVuSans-Bold.ttf'), 20)
    fnt_med = ImageFont.truetype(os.path.join(picdir, 'DejaVuSans-Bold.ttf'), 24)
    fnt_large = ImageFont.truetype(os.path.join(picdir, 'DejaVuSans-Bold.ttf'), 32)
        
    logging.info("New image")
    image = Image.new('1', (epd.height, epd.width), 255)  # 255 = w BG, 0 = black BG
    draw = ImageDraw.Draw(image)    
    epd.displayPartBaseImage(epd.getbuffer(image)) # Refresh the display
    
    # Draw the table
    draw.line([(0,0),(249,0)], fill = 0,width = 1)
    draw.line([(249,0),(249,121)], fill = 0,width = 1)
    draw.line([(0,121),(249,121)], fill = 0,width = 1)
    draw.line([(0,0),(0,121)], fill = 0,width = 1)
    
    draw.line([(0,35),(250,35)], fill = 0,width = 1)
    draw.line([(0,92),(250,92)], fill = 0,width = 1)
    draw.line([(125,35),(125,92)], fill = 0,width = 1)
    
    draw.text((4, 40), 'H:', font = fnt_small, fill = 0)
    draw.text((4, 66), 'L:', font = fnt_small, fill = 0)
    draw.text((129, 40), 'B:', font = fnt_small, fill = 0)
    draw.text((129, 66), 'S:', font = fnt_small, fill = 0)
    draw.text((6, 93), 'CURRENT:', font = fnt_med, fill = 0)
    
    epd.display(epd.getbuffer(image))
    
    while True:
        keyboard.wait('q')
        keyboard.send('ctrl+6')    
    
    logging.info("Sleep mode")
    epd.sleep()

except IOError as e:
    logging.info(e)

except KeyboardInterrupt:
    logging.info("ctrl + c:")
    epd2in13_V3.epdconfig.module_exit()
    exit

And the error code that is generated when the button is pressed for a 2nd time is:

Traceback (most recent call last):
  File "/usr/lib/python3/dist-packages/gpiozero/pins/rpigpio.py", line 223, in _call_when_changed
    super(RPiGPIOPin, self)._call_when_changed()
  File "/usr/lib/python3/dist-packages/gpiozero/pins/local.py", line 130, in _call_when_changed
    self.state if state is None else state)
  File "/usr/lib/python3/dist-packages/gpiozero/pins/pi.py", line 298, in _call_when_changed
    method(ticks, state)
  File "/usr/lib/python3/dist-packages/gpiozero/input_devices.py", line 182, in _pin_changed
    self._fire_events(ticks, bool(self._state_to_value(state)))
  File "/usr/lib/python3/dist-packages/gpiozero/mixins.py", line 401, in _fire_events
    self._fire_activated()
  File "/usr/lib/python3/dist-packages/gpiozero/mixins.py", line 447, in _fire_activated
    super(HoldMixin, self)._fire_activated()
  File "/usr/lib/python3/dist-packages/gpiozero/mixins.py", line 364, in _fire_activated
    self.when_activated()
  File "1.py", line 89, in pressed
    epd.displayPartial(epd.getbuffer(image)) # Refresh the prices
  File "/home/berry/e-Paper/RaspberryPi_JetsonNano/python/lib/waveshare_epd/epd2in13_V3.py", line 311, in displayPa                                                       rtial
    epdconfig.digital_write(self.reset_pin, 0)
  File "/home/berry/e-Paper/RaspberryPi_JetsonNano/python/lib/waveshare_epd/epdconfig.py", line 53, in digital_writ                                                       e
    self.GPIO.output(pin, value)
RuntimeError: The GPIO channel has not been set up as an OUTPUT

I've tried a few different approaches to try and get this working but am all out of ideas, it seems no matter where I put it, the sleep line always goes wrong the 2nd time it's called.

0

There are 0 answers