commit f714df41bfdab053fa2355a19ae990dc041cb4d4 Author: Kenneth Allen Date: Fri Apr 11 17:55:44 2025 +1000 Refine example code diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a348e50 --- /dev/null +++ b/.gitignore @@ -0,0 +1 @@ +/__pycache__/ diff --git a/7.3inch-1.bmp b/7.3inch-1.bmp new file mode 100644 index 0000000..f02a1bb Binary files /dev/null and b/7.3inch-1.bmp differ diff --git a/7.3inch-2.bmp b/7.3inch-2.bmp new file mode 100644 index 0000000..6520ded Binary files /dev/null and b/7.3inch-2.bmp differ diff --git a/7.3inch-3.bmp b/7.3inch-3.bmp new file mode 100644 index 0000000..268d5d6 Binary files /dev/null and b/7.3inch-3.bmp differ diff --git a/Font.ttc b/Font.ttc new file mode 100644 index 0000000..4cbb7c5 Binary files /dev/null and b/Font.ttc differ diff --git a/__main__.py b/__main__.py new file mode 100644 index 0000000..668e0b4 --- /dev/null +++ b/__main__.py @@ -0,0 +1,66 @@ +#!/usr/bin/python +import sys +import os +picdir = os.path.dirname(os.path.realpath(__file__)) + +import logging +import epd7in3g +import time +from PIL import Image, ImageDraw, ImageFont + +logging.basicConfig(level=logging.DEBUG) + +try: + logging.info("epd7in3g Demo") + + epd = epd7in3g + logging.info("init and Clear") + epd.init() + #epd.clear() + font24 = ImageFont.truetype(os.path.join(picdir, 'Font.ttc'), 24) + font18 = ImageFont.truetype(os.path.join(picdir, 'Font.ttc'), 18) + font40 = ImageFont.truetype(os.path.join(picdir, 'Font.ttc'), 40) + + # Drawing on the image + logging.info("1.Drawing on the image...") + h_image = Image.new('RGB', (epd.width, epd.height), epd.WHITE) # 255: clear the frame + draw = ImageDraw.Draw(h_image) + draw.text((5, 0), 'hello world', font = font18, fill = epd.RED) + draw.text((5, 20), '7.3inch e-Paper', font = font24, fill = epd.YELLOW) + draw.text((5, 45), u'微雪电子', font = font40, fill = epd.BLACK) + draw.text((5, 85), u'微雪电子', font = font40, fill = epd.YELLOW) + draw.text((5, 125), u'微雪电子', font = font40, fill = epd.RED) + + draw.line((5, 170, 80, 245), fill = epd.RED) + draw.line((80, 170, 5, 245), fill = epd.YELLOW) + draw.rectangle((5, 170, 80, 245), outline = epd.BLACK) + draw.rectangle((90, 170, 165, 245), fill = epd.YELLOW) + draw.arc((5, 250, 80, 325), 0, 360, fill = epd.BLACK) + draw.chord((90, 250, 165, 325), 0, 360, fill = epd.RED) + epd.display(epd.get_buffer(h_image)) + time.sleep(3) + + ## read bmp file + #logging.info("2.read bmp file") + #h_image = Image.open(os.path.join(picdir, '7.3inch-1.bmp')) + #epd.display(epd.get_buffer(h_image)) + #time.sleep(3) + + #logging.info("3.read bmp file") + #h_image = Image.open(os.path.join(picdir, '7.3inch-2.bmp')) + #epd.display(epd.get_buffer(h_image)) + #time.sleep(3) + + #logging.info("4.read bmp file") + #h_image = Image.open(os.path.join(picdir, '7.3inch-3.bmp')) + #epd.display(epd.getbuffer(h_image)) + #time.sleep(3) + + logging.info("Clear...") + epd.clear() + + logging.info("Goto Sleep...") + epd.sleep() + +finally: + epd7in3g.epdconfig.module_exit(cleanup=True) diff --git a/epd7in3g.py b/epd7in3g.py new file mode 100644 index 0000000..7840d88 --- /dev/null +++ b/epd7in3g.py @@ -0,0 +1,128 @@ +import logging +import epdconfig + +from PIL import Image + +import time + +# Display resolution +width = 800 +height = 480 + +BLACK = 0x000000 # 00 BGR +WHITE = 0xffffff # 01 +YELLOW = 0x00ffff # 10 +RED = 0x0000ff # 11 + +logger = logging.getLogger(__name__) + +# Hardware reset +def reset(): + epdconfig.GPIO_RST_PIN.on() + time.sleep(200/1000) + epdconfig.GPIO_RST_PIN.off() # module reset + time.sleep(2/1000) + epdconfig.GPIO_RST_PIN.on() + time.sleep(200/1000) + +def send_command(*command): + if command: + epdconfig.GPIO_DC_PIN.off() + epdconfig.spi_writebyte2(command[:1]) + if data := command[1:]: + epdconfig.GPIO_DC_PIN.on() + epdconfig.spi_writebyte2(data) + +def wait_for_busy_hi(): + logger.debug("e-Paper busy H") + while not epdconfig.GPIO_BUSY_PIN.value: # 0: idle, 1: busy + time.sleep(5/1000) + logger.debug("e-Paper busy H release") + +def wait_for_busy_lo(): + logger.debug("e-Paper busy L") + while epdconfig.GPIO_BUSY_PIN.value: # 0: busy, 1: idle + time.sleep(5/1000) + logger.debug("e-Paper busy L release") + +def display_on(): + send_command(0x12, 0x01) # DISPLAY_REFRESH + wait_for_busy_hi() + + send_command(0x02, 0x00) # POWER_OFF + wait_for_busy_hi() + +def init(): + epdconfig.module_init() + + # EPD hardware init start + reset() + wait_for_busy_hi() + time.sleep(30/1000) + + send_command(0xAA, 0x49, 0x55, 0x20, 0x08, 0x09, 0x18) + send_command(0x01, 0x3F) + send_command(0x00, 0x4F, 0x69) + send_command(0x05, 0x40, 0x1F, 0x1F, 0x2C) + send_command(0x08, 0x6F, 0x1F, 0x1F, 0x22) + # =================== + # 20211212 + # First setting + send_command(0x06, 0x6F, 0x1F, 0x14, 0x14) + # =================== + send_command(0x03, 0x00, 0x54, 0x00, 0x44) + send_command(0x60, 0x02, 0x00) + # Please notice that PLL must be set for version 2 IC + send_command(0x30, 0x08) + send_command(0x50, 0x3F) + send_command(0x61, 0x03, 0x20, 0x01, 0xE0) + send_command(0xE3, 0x2F) + send_command(0x84, 0x01) + +def get_buffer(image): + # Create a pallette with the 4 colors supported by the panel + pal_image = Image.new("P", (1,1)) + pal_image.putpalette((0x00,0x00,0x00, 0xff,0xff,0xff, 0xff,0xff,0x00, 0xff,0x00,0x00) + (0x00,0x00,0x00)*252) + + # Check if we need to rotate the image + if image.size == (width, height): + image_temp = image + elif image.size == (height, width): + image_temp = image.rotate(90, expand=True) + else: + raise RuntimeError("Invalid image dimensions: %d x %d, expected %d x %d" % (image.size[0], image.height[1], width, height)) + + # Convert the source image to the 4 colors, dithering if needed + image_4color = image_temp.convert("RGB").quantize(palette=pal_image) + buf_4color = bytearray(image_4color.tobytes('raw')) + + # into a single byte to transfer to the panel + buf = [0x00] * int(width * height / 4) + for idx in range(len(buf_4color) // 4): + buf[idx] = (buf_4color[idx*4] << 6) + (buf_4color[idx*4+1] << 4) + (buf_4color[idx*4+2] << 2) + buf_4color[idx*4+3] + return buf + +def display(image): + assert len(image) == width * height / 4 + + send_command(0x04) + wait_for_busy_hi() + + send_command(*([0x10] + image)) + display_on() + +def clear(color=0x55): + assert not width % 4 + iwidth = width // 4 + + send_command(0x04) + wait_for_busy_hi() + + send_command(*([0x10] + [color]*(height * iwidth))) + display_on() + +def sleep(): + send_command(0x02, 0x00) # POWER_OFF + send_command(0x07, 0xa5) # DEEP_SLEEP + time.sleep(2) + epdconfig.module_exit() diff --git a/epdconfig.py b/epdconfig.py new file mode 100644 index 0000000..86f0682 --- /dev/null +++ b/epdconfig.py @@ -0,0 +1,56 @@ +from ctypes import * +import logging +import os + +logger = logging.getLogger(__name__) + +# Pin definition +RST_PIN = 17 +DC_PIN = 25 +CS_PIN = 8 +BUSY_PIN = 24 +PWR_PIN = 18 +MOSI_PIN = 10 +SCLK_PIN = 11 + +import spidev +SPI = spidev.SpiDev() + +# Create FIFOs in /run +os.environ['LG_WD'] = f'/run/user/{os.getuid()}' +import gpiozero +GPIO_RST_PIN = gpiozero.LED(RST_PIN) +GPIO_DC_PIN = gpiozero.LED(DC_PIN) +# GPIO_CS_PIN = gpiozero.LED(CS_PIN) +GPIO_PWR_PIN = gpiozero.LED(PWR_PIN) +GPIO_BUSY_PIN = gpiozero.Button(BUSY_PIN, pull_up = False) + +def spi_writebyte(data): + SPI.writebytes(data) + +def spi_writebyte2(data): + SPI.writebytes2(data) + +def module_init(): + GPIO_PWR_PIN.on() + + # SPI device, bus = 0, device = 0 + SPI.open(0, 0) + SPI.max_speed_hz = 4000000 + SPI.mode = 0b00 + +def module_exit(cleanup=False): + logger.debug("spi end") + SPI.close() + + GPIO_RST_PIN.off() + GPIO_DC_PIN.off() + GPIO_PWR_PIN.off() + logger.debug("close 5V, Module enters 0 power consumption ...") + + if cleanup: + GPIO_RST_PIN.close() + GPIO_DC_PIN.close() + # GPIO_CS_PIN.close() + GPIO_PWR_PIN.close() + GPIO_BUSY_PIN.close()