How can I display small black and white images on a e-paper spi display with a Raspberry Pi Pico W?

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.

New contributor

user26708930 is a new contributor to this site. Take care in asking for clarification, commenting, and answering.
Check out our Code of Conduct.

Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa Dịch vụ tổ chức sự kiện 5 sao Thông tin về chúng tôi Dịch vụ sinh nhật bé trai Dịch vụ sinh nhật bé gái Sự kiện trọn gói Các tiết mục giải trí Dịch vụ bổ trợ Tiệc cưới sang trọng Dịch vụ khai trương Tư vấn tổ chức sự kiện Hình ảnh sự kiện Cập nhật tin tức Liên hệ ngay Thuê chú hề chuyên nghiệp Tiệc tất niên cho công ty Trang trí tiệc cuối năm Tiệc tất niên độc đáo Sinh nhật bé Hải Đăng Sinh nhật đáng yêu bé Khánh Vân Sinh nhật sang trọng Bích Ngân Tiệc sinh nhật bé Thanh Trang Dịch vụ ông già Noel Xiếc thú vui nhộn Biểu diễn xiếc quay đĩa Dịch vụ tổ chức tiệc uy tín Khám phá dịch vụ của chúng tôi Tiệc sinh nhật cho bé trai Trang trí tiệc cho bé gái Gói sự kiện chuyên nghiệp Chương trình giải trí hấp dẫn Dịch vụ hỗ trợ sự kiện Trang trí tiệc cưới đẹp Khởi đầu thành công với khai trương Chuyên gia tư vấn sự kiện Xem ảnh các sự kiện đẹp Tin mới về sự kiện Kết nối với đội ngũ chuyên gia Chú hề vui nhộn cho tiệc sinh nhật Ý tưởng tiệc cuối năm Tất niên độc đáo Trang trí tiệc hiện đại Tổ chức sinh nhật cho Hải Đăng Sinh nhật độc quyền Khánh Vân Phong cách tiệc Bích Ngân Trang trí tiệc bé Thanh Trang Thuê dịch vụ ông già Noel chuyên nghiệp Xem xiếc khỉ đặc sắc Xiếc quay đĩa thú vị
Trang chủ Giới thiệu Sinh nhật bé trai Sinh nhật bé gái Tổ chức sự kiện Biểu diễn giải trí Dịch vụ khác Trang trí tiệc cưới Tổ chức khai trương Tư vấn dịch vụ Thư viện ảnh Tin tức - sự kiện Liên hệ Chú hề sinh nhật Trang trí YEAR END PARTY công ty Trang trí tất niên cuối năm Trang trí tất niên xu hướng mới nhất Trang trí sinh nhật bé trai Hải Đăng Trang trí sinh nhật bé Khánh Vân Trang trí sinh nhật Bích Ngân Trang trí sinh nhật bé Thanh Trang Thuê ông già Noel phát quà Biểu diễn xiếc khỉ Xiếc quay đĩa
Thiết kế website Thiết kế website Thiết kế website Cách kháng tài khoản quảng cáo Mua bán Fanpage Facebook Dịch vụ SEO Tổ chức sinh nhật