2

I have purchases a Raspberry Pi Pico W and have wired it to the Waveshare 1.54 inch e-Paper display module V2 I have used the code available at the github page, specifically the epd1in54b.py and the epconfig.py,

The specific errors that I have got are some missing libraries, including logging, spidev, ctypes, subprocess. I have tried to work around this as best as I can by replacing these modules with modules supported by Micropython & the Raspberry Pi Pico W.

This is the modified version of epd1in54b_V2.py file

import epdconfig

Display resolution

EPD_WIDTH = 200 EPD_HEIGHT = 200

class EPD: def init(self, cs, dc, rst, busy): self.reset_pin = rst self.dc_pin = dc self.busy_pin = busy self.cs_pin = cs self.width = EPD_WIDTH self.height = EPD_HEIGHT

# Hardware reset
def reset(self):
    epdconfig.digital_write(self.reset_pin, 1)
    epdconfig.delay_ms(200)
    epdconfig.digital_write(self.reset_pin, 0)  # module reset
    epdconfig.delay_ms(5)
    epdconfig.digital_write(self.reset_pin, 1)
    epdconfig.delay_ms(200)

def send_command(self, command):
    epdconfig.digital_write(self.dc_pin, 0)
    epdconfig.digital_write(self.cs_pin, 0)
    epdconfig.spi_writebyte([command])  # Ensure this sends a list
    epdconfig.digital_write(self.cs_pin, 1)

def send_data(self, data):
    epdconfig.digital_write(self.dc_pin, 1)
    epdconfig.digital_write(self.cs_pin, 0)
    epdconfig.spi_writebyte([data])  # Ensure this sends a list
    epdconfig.digital_write(self.cs_pin, 1)

# Send a lot of data
def send_data2(self, data):
    epdconfig.digital_write(self.dc_pin, 1)
    epdconfig.digital_write(self.cs_pin, 0)
    epdconfig.spi_writebyte2(data)  # Pass the data array directly
    epdconfig.digital_write(self.cs_pin, 1)

def ReadBusy(self):
    print("e-Paper busy")
    while epdconfig.digital_read(self.busy_pin) == 1:
        epdconfig.delay_ms(100)
    print("e-Paper busy release")

def init(self):
    if epdconfig.module_init() != 0:
        return -1
    # EPD hardware init start
    self.reset()

    self.ReadBusy()
    self.send_command(0x12)  # SWRESET
    self.ReadBusy()

    self.send_command(0x01)  # Driver output control
    self.send_data(0xC7)
    self.send_data(0x00)
    self.send_data(0x01)

    self.send_command(0x11)  # Data entry mode
    self.send_data(0x01)

    self.send_command(0x44)  # Set RAM-X address start/end position
    self.send_data(0x00)
    self.send_data(0x18)  # 0x18 --> (24+1)*8=200

    self.send_command(0x45)  # Set RAM-Y address start/end position
    self.send_data(0xC7)  # 0xC7 --> (199+1)=200
    self.send_data(0x00)
    self.send_data(0x00)
    self.send_data(0x00)

    self.send_command(0x3C)  # BorderWaveform
    self.send_data(0x05)

    self.send_command(0x18)  # Read built-in temperature sensor
    self.send_data(0x80)

    self.send_command(0x4E)  # Set RAM x address count to 0
    self.send_data(0x00)
    self.send_command(0x4F)  # Set RAM y address count to 0X199
    self.send_data(0xC7)
    self.send_data(0x00)
    self.ReadBusy()
    return 0

def getbuffer(self, image):
    buf = [0xFF] * int(self.width * self.height / 8)
    image_monocolor = image.convert('1')
    imwidth, imheight = image_monocolor.size
    if imwidth != self.width or imheight != self.height:
        raise ValueError('Image must be same dimensions as display ({0}x{1}).'.format(self.width, self.height))

    pixels = image_monocolor.load()
    for y in range(self.height):
        for x in range(self.width):
            if pixels[x, y] == 0:
                buf[int((x + y * self.width) / 8)] &= ~(0x80 >> (x % 8))
    return buf

def display(self, blackimage, redimage):
    if self.width % 8 == 0:
        linewidth = int(self.width / 8)
    else:
        linewidth = int(self.width / 8) + 1

    buf = [0x00] * self.height * linewidth

    # Send black data
    if blackimage is not None:
        self.send_command(0x24)  # DATA_START_TRANSMISSION_1
        self.send_data2(blackimage)

    # Send red data
    if redimage is not None:
        self.send_command(0x26)  # DATA_START_TRANSMISSION_2
        for i in range(int(self.width * self.height / 8)):
            buf[i] = ~redimage[i]
        self.send_data2(buf)

    self.send_command(0x22)  # DISPLAY_REFRESH
    self.send_data(0xF7)
    self.send_command(0x20)  # DISPLAY_REFRESH
    self.ReadBusy()

def Clear(self):
    if self.width % 8 == 0:
        linewidth = int(self.width / 8)
    else:
        linewidth = int(self.width / 8) + 1

    self.send_command(0x24)  # DATA_START_TRANSMISSION_1
    self.send_data2([0xff] * int(self.height * linewidth))

    self.send_command(0x26)  # DATA_START_TRANSMISSION_2
    self.send_data2([0x00] * int(self.height * linewidth))

    self.send_command(0x22)  # DISPLAY_REFRESH
    self.send_data(0xF7)
    self.send_command(0x20)  # DISPLAY_REFRESH
    self.ReadBusy()

def sleep(self):
    self.send_command(0x10)  # Enter deep sleep
    self.send_data(0x01)

    epdconfig.delay_ms(2000)
    epdconfig.module_exit()

The modified epdconfig.py file is here:

import os
import sys
import time

logger = logging.getLogger(name)

import machine import time

class RaspberryPi: # Pin definition RST_PIN = 17 DC_PIN = 25 CS_PIN = 8 BUSY_PIN = 24 PWR_PIN = 18

def __init__(self):
    self.spi = machine.SPI(0, baudrate=4000000, polarity=0, phase=0, sck=machine.Pin(18), mosi=machine.Pin(19))
    self.rst = machine.Pin(self.RST_PIN, machine.Pin.OUT)
    self.dc = machine.Pin(self.DC_PIN, machine.Pin.OUT)
    self.cs = machine.Pin(self.CS_PIN, machine.Pin.OUT)
    self.busy = machine.Pin(self.BUSY_PIN, machine.Pin.IN)
    self.pwr = machine.Pin(self.PWR_PIN, machine.Pin.OUT)

    self.cs(1)  # Disable the chip select

def digital_write(self, pin, value):
    pin_obj = getattr(self, pin.lower())
    pin_obj.value(value)

def digital_read(self, pin):
    pin_obj = getattr(self, pin.lower())
    return pin_obj.value()

def delay_ms(self, delaytime):
    time.sleep_ms(delaytime)

def spi_writebyte(self, data):
    self.cs(0)  # Enable chip select
    self.spi.write(bytearray(data))
    self.cs(1)  # Disable chip select

def module_init(self):
    self.pwr.on()
    return 0

def module_exit(self):
    self.spi.deinit()
    self.rst.off()
    self.dc.off()
    self.pwr.off()
    print("SPI end, Module enters 0 power consumption ...")

Assuming we are using the RaspberryPi configuration for the Pico

implementation = RaspberryPi()

Export functions to the module level

for func in [x for x in dir(implementation) if not x.startswith('_')]: setattr(sys.modules[name], func, getattr(implementation, func))

class JetsonNano: # Pin definition RST_PIN = 17 DC_PIN = 25 CS_PIN = 8 BUSY_PIN = 24 PWR_PIN = 18

def __init__(self):
    import Jetson.GPIO
    self.GPIO = Jetson.GPIO

def digital_write(self, pin, value):
    self.GPIO.output(pin, value)

def digital_read(self, pin):
    return self.GPIO.input(self.BUSY_PIN)

def delay_ms(self, delaytime):
    time.sleep(delaytime / 1000.0)

def spi_writebyte(self, data):
    self.SPI.SYSFS_software_spi_transfer(data[0])

def spi_writebyte2(self, data):
    for i in range(len(data)):
        self.SPI.SYSFS_software_spi_transfer(data[i])

def module_init(self):
    self.GPIO.setmode(self.GPIO.BCM)
    self.GPIO.setwarnings(False)
    self.GPIO.setup(self.RST_PIN, self.GPIO.OUT)
    self.GPIO.setup(self.DC_PIN, self.GPIO.OUT)
    self.GPIO.setup(self.CS_PIN, self.GPIO.OUT)
    self.GPIO.setup(self.PWR_PIN, self.GPIO.OUT)
    self.GPIO.setup(self.BUSY_PIN, self.GPIO.IN)
    self.GPIO.output(self.PWR_PIN, 1)
    self.SPI.SYSFS_software_spi_begin()
    return 0

def module_exit(self):
    print("spi end")
    self.SPI.SYSFS_software_spi_end()
    print("close 5V, Module enters 0 power consumption ...")
    self.GPIO.output(self.RST_PIN, 0)
    self.GPIO.output(self.DC_PIN, 0)
    self.GPIO.output(self.PWR_PIN, 0)
    self.GPIO.cleanup([self.RST_PIN, self.DC_PIN, self.CS_PIN, self.BUSY_PIN, self.PWR_PIN])

class SunriseX3: # Pin definition RST_PIN = 17 DC_PIN = 25 CS_PIN = 8 BUSY_PIN = 24 PWR_PIN = 18 Flag = 0

def __init__(self):
    import spidev
    import Hobot.GPIO
    self.GPIO = Hobot.GPIO
    self.SPI = spidev.SpiDev()

def digital_write(self, pin, value):
    self.GPIO.output(pin, value)

def digital_read(self, pin):
    return self.GPIO.input(pin)

def delay_ms(self, delaytime):
    time.sleep(delaytime / 1000.0)

def spi_writebyte(self, data):
    self.SPI.writebytes(data)

def spi_writebyte2(self, data):
    self.SPI.xfer3(data)

def module_init(self):
    if self.Flag == 0:
        self.Flag = 1
        self.GPIO.setmode(self.GPIO.BCM)
        self.GPIO.setwarnings(False)
        self.GPIO.setup(self.RST_PIN, self.GPIO.OUT)
        self.GPIO.setup(self.DC_PIN, self.GPIO.OUT)
        self.GPIO.setup(self.CS_PIN, self.GPIO.OUT)
        self.GPIO.setup(self.PWR_PIN, self.GPIO.OUT)
        self.GPIO.setup(self.BUSY_PIN, self.GPIO.IN)
        self.GPIO.output(self.PWR_PIN, 1)
        self.SPI.open(2, 0)
        self.SPI.max_speed_hz = 4000000
        self.SPI.mode = 0b00
        return 0
    else:
        return 0

def module_exit(self):
    print("spi end")
    self.SPI.close()
    print("close 5V, Module enters 0 power consumption ...")
    self.Flag = 0
    self.GPIO.output(self.RST_PIN, 0)
    self.GPIO.output(self.DC_PIN, 0)
    self.GPIO.output(self.PWR_PIN, 0)
    self.GPIO.cleanup([self.RST_PIN, self.DC_PIN, self.CS_PIN, self.BUSY_PIN], self.PWR_PIN)

output = "Raspberry Pi Pico"

if "Raspberry" in output: implementation = RaspberryPi() elif os.path.exists('/sys/bus/platform/drivers/gpio-x3'): implementation = SunriseX3() else: implementation = JetsonNano()

for func in [x for x in dir(implementation) if not x.startswith('_')]: setattr(sys.modules[name], func, getattr(implementation, func))

END OF FILE

The code I am using to generate the image is here:

import framebuf
import utime
from machine import Pin, SPI
import epd1in54b_V2

Initialize the SPI communication

spi = SPI(1, baudrate=2000000, polarity=0, phase=0, sck=Pin(10), mosi=Pin(11), miso=Pin(12))

Initialize the e-paper display

epd = epd1in54b_V2.EPD(spi, cs=Pin(13), dc=Pin(14), rst=Pin(15), busy=Pin(16))

Clear the display

epd.init() epd.clear_frame_memory(0xFF) epd.display_frame()

Create a black and white image (10x10 pixels)

image_width = 10 image_height = 10 image = bytearray(image_width * image_height // 8) framebuf_image = framebuf.FrameBuffer(image, image_width, image_height, framebuf.MONO_HLSB)

Draw a 10x10 pixel black square

for y in range(image_height): for x in range(image_width): framebuf_image.pixel(x, y, 0) # 0 means black in MONO_HLSB mode

Calculate the position to place the image in the center of the display

display_width = epd.width display_height = epd.height x_pos = (display_width - image_width) // 2 y_pos = (display_height - image_height) // 2

Display the image

epd.set_frame_memory(image, x_pos, y_pos, image_width, image_height) epd.display_frame()

Put the display to sleep

epd.sleep()

Can someone please advise me on how to do this.

EDIT:

I am using Thonny to connect to my Raspberry Pi Pico W, on my macbook, through an usb-c to usb-a adapter, to a usb-a to micro b adapter, to the Raspberry Pi Pico W. I have tested the connection using leds, buttons & buzzers, and it works fine. I still do not know how to display images on the display though.

odo59
  • 21
  • 2

0 Answers0