Touchscreen driver POC

Example documentation
This commit is contained in:
2026-05-07 16:28:08 -07:00
parent c0ad8306a7
commit a125f45b34
201 changed files with 19783 additions and 34 deletions
@@ -0,0 +1,339 @@
# *****************************************************************************
# * | File : epd2in13_V2.py
# * | Author : Waveshare team
# * | Function : Electronic paper driver
# * | Info :
# *----------------
# * | This version: V4.0
# * | Date : 2019-06-20
# # | Info : python demo
# -----------------------------------------------------------------------------
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documnetation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS OR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
#
import logging
from . import epdconfig
import numpy as np
# Display resolution
EPD_WIDTH = 122
EPD_HEIGHT = 250
class EPD_2IN13_V2:
def __init__(self):
self.reset_pin = epdconfig.EPD_RST_PIN
self.dc_pin = epdconfig.EPD_DC_PIN
self.busy_pin = epdconfig.EPD_BUSY_PIN
self.cs_pin = epdconfig.EPD_CS_PIN
self.width = EPD_WIDTH
self.height = EPD_HEIGHT
epdconfig.address = 0x14
FULL_UPDATE = 0
PART_UPDATE = 1
lut_full_update= [
0x80,0x60,0x40,0x00,0x00,0x00,0x00, #LUT0: BB: VS 0 ~7
0x10,0x60,0x20,0x00,0x00,0x00,0x00, #LUT1: BW: VS 0 ~7
0x80,0x60,0x40,0x00,0x00,0x00,0x00, #LUT2: WB: VS 0 ~7
0x10,0x60,0x20,0x00,0x00,0x00,0x00, #LUT3: WW: VS 0 ~7
0x00,0x00,0x00,0x00,0x00,0x00,0x00, #LUT4: VCOM: VS 0 ~7
0x03,0x03,0x00,0x00,0x02, # TP0 A~D RP0
0x09,0x09,0x00,0x00,0x02, # TP1 A~D RP1
0x03,0x03,0x00,0x00,0x02, # TP2 A~D RP2
0x00,0x00,0x00,0x00,0x00, # TP3 A~D RP3
0x00,0x00,0x00,0x00,0x00, # TP4 A~D RP4
0x00,0x00,0x00,0x00,0x00, # TP5 A~D RP5
0x00,0x00,0x00,0x00,0x00, # TP6 A~D RP6
0x15,0x41,0xA8,0x32,0x30,0x0A,
]
lut_partial_update = [ #20 bytes
0x00,0x00,0x00,0x00,0x00,0x00,0x00, #LUT0: BB: VS 0 ~7
0x80,0x00,0x00,0x00,0x00,0x00,0x00, #LUT1: BW: VS 0 ~7
0x40,0x00,0x00,0x00,0x00,0x00,0x00, #LUT2: WB: VS 0 ~7
0x00,0x00,0x00,0x00,0x00,0x00,0x00, #LUT3: WW: VS 0 ~7
0x00,0x00,0x00,0x00,0x00,0x00,0x00, #LUT4: VCOM: VS 0 ~7
0x0A,0x00,0x00,0x00,0x00, # TP0 A~D RP0
0x00,0x00,0x00,0x00,0x00, # TP1 A~D RP1
0x00,0x00,0x00,0x00,0x00, # TP2 A~D RP2
0x00,0x00,0x00,0x00,0x00, # TP3 A~D RP3
0x00,0x00,0x00,0x00,0x00, # TP4 A~D RP4
0x00,0x00,0x00,0x00,0x00, # TP5 A~D RP5
0x00,0x00,0x00,0x00,0x00, # TP6 A~D RP6
0x15,0x41,0xA8,0x32,0x30,0x0A,
]
# Hardware reset
def reset(self):
epdconfig.digital_write(self.reset_pin, 1)
epdconfig.delay_ms(200)
epdconfig.digital_write(self.reset_pin, 0)
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])
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])
epdconfig.digital_write(self.cs_pin, 1)
def send_data2(self, data):
epdconfig.digital_write(self.dc_pin, 1)
epdconfig.digital_write(self.cs_pin, 0)
epdconfig.spi_writebyte(data)
epdconfig.digital_write(self.cs_pin, 1)
def ReadBusy(self):
while(epdconfig.digital_read(self.busy_pin) == 1): # 0: idle, 1: busy
epdconfig.delay_ms(10)
def TurnOnDisplay(self):
self.send_command(0x22)
self.send_data(0xC7)
self.send_command(0x20)
self.ReadBusy()
def TurnOnDisplayPart(self):
self.send_command(0x22)
self.send_data(0x0c)
self.send_command(0x20)
# self.ReadBusy()
def TurnOnDisplayPart_Wait(self):
self.send_command(0x22)
self.send_data(0x0c)
self.send_command(0x20)
self.ReadBusy()
def init(self, update):
if (epdconfig.module_init() != 0):
return -1
# EPD hardware init start
self.reset()
if(update == self.FULL_UPDATE):
self.ReadBusy()
self.send_command(0x12) # soft reset
self.ReadBusy()
self.send_command(0x74) #set analog block control
self.send_data(0x54)
self.send_command(0x7E) #set digital block control
self.send_data(0x3B)
self.send_command(0x01) #Driver output control
self.send_data(0xF9)
self.send_data(0x00)
self.send_data(0x00)
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(0x0F) #0x0C-->(15+1)*8=128
self.send_command(0x45) #set Ram-Y address start/end position
self.send_data(0xF9) #0xF9-->(249+1)=250
self.send_data(0x00)
self.send_data(0x00)
self.send_data(0x00)
self.send_command(0x3C) #BorderWavefrom
self.send_data(0x03)
self.send_command(0x2C) #VCOM Voltage
self.send_data(0x55) #
self.send_command(0x03)
self.send_data(self.lut_full_update[70])
self.send_command(0x04) #
self.send_data(self.lut_full_update[71])
self.send_data(self.lut_full_update[72])
self.send_data(self.lut_full_update[73])
self.send_command(0x3A) #Dummy Line
self.send_data(self.lut_full_update[74])
self.send_command(0x3B) #Gate time
self.send_data(self.lut_full_update[75])
self.send_command(0x32)
for count in range(70):
self.send_data(self.lut_full_update[count])
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 0X127
self.send_data(0xF9)
self.send_data(0x00)
self.ReadBusy()
else:
self.send_command(0x2C) #VCOM Voltage
self.send_data(0x26)
self.ReadBusy()
self.send_command(0x32)
for count in range(70):
self.send_data(self.lut_partial_update[count])
self.send_command(0x37)
self.send_data(0x00)
self.send_data(0x00)
self.send_data(0x00)
self.send_data(0x00)
self.send_data(0x40)
self.send_data(0x00)
self.send_data(0x00)
self.send_command(0x22)
self.send_data(0xC0)
self.send_command(0x20)
self.ReadBusy()
self.send_command(0x3C) #BorderWavefrom
self.send_data(0x01)
return 0
def getbuffer(self, image):
if self.width%8 == 0:
linewidth = int(self.width/8)
else:
linewidth = int(self.width/8) + 1
buf = [0xFF] * (linewidth * self.height)
image_monocolor = image.convert('1')
imwidth, imheight = image_monocolor.size
pixels = image_monocolor.load()
if(imwidth == self.width and imheight == self.height):
# logging.debug("Vertical")
for y in range(imheight):
for x in range(imwidth):
if pixels[x, y] == 0:
x = imwidth - x
buf[int(x / 8) + y * linewidth] &= ~(0x80 >> (x % 8))
elif(imwidth == self.height and imheight == self.width):
# logging.debug("Horizontal")
for y in range(imheight):
for x in range(imwidth):
newx = y
newy = self.height - x - 1
if pixels[x, y] == 0:
newy = imwidth - newy - 1
buf[int(newx / 8) + newy*linewidth] &= ~(0x80 >> (y % 8))
return buf
def display(self, image):
if self.width%8 == 0:
linewidth = int(self.width/8)
else:
linewidth = int(self.width/8) + 1
self.send_command(0x24)
# for j in range(0, self.height):
# for i in range(0, linewidth):
# self.send_data(image[i + j * linewidth])
self.send_data2(image)
self.TurnOnDisplay()
def displayPartial(self, image):
if self.width%8 == 0:
linewidth = int(self.width/8)
else:
linewidth = int(self.width/8) + 1
self.send_command(0x24)
# for j in range(0, self.height):
# for i in range(0, linewidth):
# self.send_data(image[i + j * linewidth])
self.send_data2(image)
self.TurnOnDisplayPart()
def displayPartial_Wait(self, image):
if self.width%8 == 0:
linewidth = int(self.width/8)
else:
linewidth = int(self.width/8) + 1
self.send_command(0x24)
for j in range(0, self.height):
for i in range(0, linewidth):
self.send_data(image[i + j * linewidth])
self.TurnOnDisplayPart_Wait()
def displayPartBaseImage(self, image):
if self.width%8 == 0:
linewidth = int(self.width/8)
else:
linewidth = int(self.width/8) + 1
self.send_command(0x24)
for j in range(0, self.height):
for i in range(0, linewidth):
self.send_data(image[i + j * linewidth])
self.send_command(0x26)
for j in range(0, self.height):
for i in range(0, linewidth):
self.send_data(image[i + j * linewidth])
self.TurnOnDisplay()
def Clear(self, color):
if self.width%8 == 0:
linewidth = int(self.width/8)
else:
linewidth = int(self.width/8) + 1
self.send_command(0x24)
for j in range(0, self.height):
for i in range(0, linewidth):
self.send_data(color)
self.TurnOnDisplay()
def sleep(self):
# self.send_command(0x22) #POWER OFF
# self.send_data(0xC3)
# self.send_command(0x20)
self.send_command(0x10) #enter deep sleep
self.send_data(0x03)
epdconfig.delay_ms(100)
def Dev_exit(self):
epdconfig.module_exit()
### END OF FILE ###
@@ -0,0 +1,436 @@
# *****************************************************************************
# * | File : epd2in13_V3.py
# * | Author : Waveshare team
# * | Function : Electronic paper driver
# * | Info :
# *----------------
# * | This version: V1.1
# * | Date : 2021-10-30
# # | Info : python demo
# -----------------------------------------------------------------------------
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documnetation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS OR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
#
import logging
from . import epdconfig
import numpy as np
# Display resolution
EPD_WIDTH = 122
EPD_HEIGHT = 250
logger = logging.getLogger(__name__)
class EPD:
def __init__(self):
self.reset_pin = epdconfig.EPD_RST_PIN
self.dc_pin = epdconfig.EPD_DC_PIN
self.busy_pin = epdconfig.EPD_BUSY_PIN
self.cs_pin = epdconfig.EPD_CS_PIN
self.width = EPD_WIDTH
self.height = EPD_HEIGHT
epdconfig.address = 0x14
FULL_UPDATE = 0
PART_UPDATE = 1
lut_partial_update= [
0x0,0x40,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x80,0x80,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x40,0x40,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x80,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x10,0x0,0x0,0x0,0x0,0x0,0x0,
0x1,0x0,0x0,0x0,0x0,0x0,0x0,
0x1,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x22,0x22,0x22,0x22,0x22,0x22,0x0,0x0,0x0,
0x22,0x17,0x41,0x00,0x32,0x36,
]
lut_full_update = [
0x80,0x4A,0x40,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x40,0x4A,0x80,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x80,0x4A,0x40,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x40,0x4A,0x80,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0xF,0x0,0x0,0x0,0x0,0x0,0x0,
0xF,0x0,0x0,0xF,0x0,0x0,0x2,
0xF,0x0,0x0,0x0,0x0,0x0,0x0,
0x1,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x22,0x22,0x22,0x22,0x22,0x22,0x0,0x0,0x0,
0x22,0x17,0x41,0x0,0x32,0x36,
]
'''
function :Hardware reset
parameter:
'''
def reset(self):
epdconfig.digital_write(self.reset_pin, 1)
epdconfig.delay_ms(20)
epdconfig.digital_write(self.reset_pin, 0)
epdconfig.delay_ms(2)
epdconfig.digital_write(self.reset_pin, 1)
epdconfig.delay_ms(20)
'''
function :send command
parameter:
command : Command register
'''
def send_command(self, command):
epdconfig.digital_write(self.dc_pin, 0)
epdconfig.digital_write(self.cs_pin, 0)
epdconfig.spi_writebyte([command])
epdconfig.digital_write(self.cs_pin, 1)
'''
function :send data
parameter:
data : Write data
'''
def send_data(self, data):
epdconfig.digital_write(self.dc_pin, 1)
epdconfig.digital_write(self.cs_pin, 0)
epdconfig.spi_writebyte([data])
epdconfig.digital_write(self.cs_pin, 1)
def send_data2(self, data):
epdconfig.digital_write(self.dc_pin, 1)
epdconfig.digital_write(self.cs_pin, 0)
epdconfig.spi_writebyte(data)
epdconfig.digital_write(self.cs_pin, 1)
'''
function :Wait until the busy_pin goes LOW
parameter:
'''
def ReadBusy(self):
logger.debug("e-Paper busy")
while(epdconfig.digital_read(self.busy_pin) == 1): # 0: idle, 1: busy
epdconfig.delay_ms(10)
logger.debug("e-Paper busy release")
'''
function : Turn On Display
parameter:
'''
def TurnOnDisplay(self):
self.send_command(0x22) # Display Update Control
self.send_data(0xC7)
self.send_command(0x20) # Activate Display Update Sequence
self.ReadBusy()
'''
function : Turn On Display Part
parameter:
'''
def TurnOnDisplayPart(self):
self.send_command(0x22) # Display Update Control
self.send_data(0x0c) # fast:0x0c, quality:0x0f, 0xcf
self.send_command(0x20) # Activate Display Update Sequence
# self.ReadBusy()
def TurnOnDisplayPart_Wait(self):
self.send_command(0x22) # Display Update Control
self.send_data(0x0c) # fast:0x0c, quality:0x0f, 0xcf
self.send_command(0x20) # Activate Display Update Sequence
self.ReadBusy()
'''
function : Set lut
parameter:
lut : lut data
'''
def Lut(self, lut):
self.send_command(0x32)
for i in range(0, 153):
self.send_data(lut[i])
self.ReadBusy()
'''
function : Send lut data and configuration
parameter:
lut : lut data
'''
def SetLut(self, lut):
self.Lut(lut)
self.send_command(0x3f)
self.send_data(lut[153])
self.send_command(0x03) # gate voltage
self.send_data(lut[154])
self.send_command(0x04) # source voltage
self.send_data(lut[155]) # VSH
self.send_data(lut[156]) # VSH2
self.send_data(lut[157]) # VSL
self.send_command(0x2c) # VCOM
self.send_data(lut[158])
'''
function : Setting the display window
parameter:
xstart : X-axis starting position
ystart : Y-axis starting position
xend : End position of X-axis
yend : End position of Y-axis
'''
def SetWindow(self, x_start, y_start, x_end, y_end):
self.send_command(0x44) # SET_RAM_X_ADDRESS_START_END_POSITION
# x point must be the multiple of 8 or the last 3 bits will be ignored
self.send_data((x_start>>3) & 0xFF)
self.send_data((x_end>>3) & 0xFF)
self.send_command(0x45) # SET_RAM_Y_ADDRESS_START_END_POSITION
self.send_data(y_start & 0xFF)
self.send_data((y_start >> 8) & 0xFF)
self.send_data(y_end & 0xFF)
self.send_data((y_end >> 8) & 0xFF)
'''
function : Set Cursor
parameter:
x : X-axis starting position
y : Y-axis starting position
'''
def SetCursor(self, x, y):
self.send_command(0x4E) # SET_RAM_X_ADDRESS_COUNTER
# x point must be the multiple of 8 or the last 3 bits will be ignored
self.send_data(x & 0xFF)
self.send_command(0x4F) # SET_RAM_Y_ADDRESS_COUNTER
self.send_data(y & 0xFF)
self.send_data((y >> 8) & 0xFF)
'''
function : Initialize the e-Paper register
parameter:
'''
def init(self, update):
if (epdconfig.module_init() != 0):
return -1
if update == self.FULL_UPDATE:
# 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(0xf9)
self.send_data(0x00)
self.send_data(0x00)
self.send_command(0x11) #data entry mode
self.send_data(0x03)
self.SetWindow(0, 0, self.width-1, self.height-1)
self.SetCursor(0, 0)
self.send_command(0x3c)
self.send_data(0x05)
self.send_command(0x21) # Display update control
self.send_data(0x00)
self.send_data(0x80)
self.send_command(0x18)
self.send_data(0x80)
self.ReadBusy()
self.SetLut(self.lut_full_update)
else:
epdconfig.digital_write(self.reset_pin, 0)
epdconfig.delay_ms(1)
epdconfig.digital_write(self.reset_pin, 1)
self.SetLut(self.lut_partial_update)
self.send_command(0x37)
self.send_data(0x00)
self.send_data(0x00)
self.send_data(0x00)
self.send_data(0x00)
self.send_data(0x00)
self.send_data(0x40)
self.send_data(0x00)
self.send_data(0x00)
self.send_data(0x00)
self.send_data(0x00)
self.send_command(0x3C) #BorderWavefrom
self.send_data(0x80)
self.send_command(0x22)
self.send_data(0xC0)
self.send_command(0x20)
self.ReadBusy()
self.SetWindow(0, 0, self.width - 1, self.height - 1)
self.SetCursor(0, 0)
return 0
'''
function : Display images
parameter:
image : Image data
'''
def getbuffer(self, image):
img = image
imwidth, imheight = img.size
if(imwidth == self.width and imheight == self.height):
img = img.rotate(180, expand=True).convert('1')
elif(imwidth == self.height and imheight == self.width):
# image has correct dimensions, but needs to be rotated
img = img.rotate(270, expand=True).convert('1')
else:
logger.warning("Wrong image dimensions: must be " + str(self.width) + "x" + str(self.height))
# return a blank buffer
return [0x00] * (int(self.width/8) * self.height)
buf = bytearray(img.tobytes('raw'))
return buf
'''
function : Sends the image buffer in RAM to e-Paper and displays
parameter:
image : Image data
'''
def display(self, image):
if self.width%8 == 0:
linewidth = int(self.width/8)
else:
linewidth = int(self.width/8) + 1
self.send_command(0x24)
# for j in range(0, self.height):
# for i in range(0, linewidth):
# self.send_data(image[i + j * linewidth])
self.send_data2(image)
self.TurnOnDisplay()
'''
function : Sends the image buffer in RAM to e-Paper and partial refresh
parameter:
image : Image data
'''
def displayPartial(self, image):
if self.width%8 == 0:
linewidth = int(self.width/8)
else:
linewidth = int(self.width/8) + 1
self.send_command(0x24) # WRITE_RAM
# for j in range(0, self.height):
# for i in range(0, linewidth):
# self.send_data(image[i + j * linewidth])
self.send_data2(image)
self.TurnOnDisplayPart()
def displayPartial_Wait(self, image):
if self.width%8 == 0:
linewidth = int(self.width/8)
else:
linewidth = int(self.width/8) + 1
self.send_command(0x24) # WRITE_RAM
# for j in range(0, self.height):
# for i in range(0, linewidth):
# self.send_data(image[i + j * linewidth])
self.send_data2(image)
self.TurnOnDisplayPart_Wait()
'''
function : Refresh a base image
parameter:
image : Image data
'''
def displayPartBaseImage(self, image):
if self.width%8 == 0:
linewidth = int(self.width/8)
else:
linewidth = int(self.width/8) + 1
self.send_command(0x24)
for j in range(0, self.height):
for i in range(0, linewidth):
self.send_data(image[i + j * linewidth])
self.send_command(0x26)
for j in range(0, self.height):
for i in range(0, linewidth):
self.send_data(image[i + j * linewidth])
self.TurnOnDisplay()
'''
function : Clear screen
parameter:
'''
def Clear(self, color):
if self.width%8 == 0:
linewidth = int(self.width/8)
else:
linewidth = int(self.width/8) + 1
# logger.debug(linewidth)
self.send_command(0x24)
for j in range(0, self.height):
for i in range(0, linewidth):
self.send_data(color)
self.TurnOnDisplay()
'''
function : Enter sleep mode
parameter:
'''
def sleep(self):
self.send_command(0x10) #enter deep sleep
self.send_data(0x01)
epdconfig.delay_ms(2000)
def Dev_exit(self):
epdconfig.module_exit()
### END OF FILE ###
@@ -0,0 +1,370 @@
# *****************************************************************************
# * | File : epd2in13_V4.py
# * | Author : Waveshare team
# * | Function : Electronic paper driver
# * | Info :
# *----------------
# * | This version: V1.0
# * | Date : 2023-08-14
# # | Info : python demo
# -----------------------------------------------------------------------------
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documnetation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS OR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
#
import logging
from . import epdconfig
import numpy as np
# Display resolution
EPD_WIDTH = 122
EPD_HEIGHT = 250
logger = logging.getLogger(__name__)
class EPD:
def __init__(self):
self.reset_pin = epdconfig.EPD_RST_PIN
self.dc_pin = epdconfig.EPD_DC_PIN
self.busy_pin = epdconfig.EPD_BUSY_PIN
self.cs_pin = epdconfig.EPD_CS_PIN
self.width = EPD_WIDTH
self.height = EPD_HEIGHT
epdconfig.address = 0x14
FULL_UPDATE = 0
PART_UPDATE = 1
'''
function :Hardware reset
parameter:
'''
def reset(self):
epdconfig.digital_write(self.reset_pin, 1)
epdconfig.delay_ms(20)
epdconfig.digital_write(self.reset_pin, 0)
epdconfig.delay_ms(2)
epdconfig.digital_write(self.reset_pin, 1)
epdconfig.delay_ms(20)
'''
function :send command
parameter:
command : Command register
'''
def send_command(self, command):
epdconfig.digital_write(self.dc_pin, 0)
epdconfig.digital_write(self.cs_pin, 0)
epdconfig.spi_writebyte([command])
epdconfig.digital_write(self.cs_pin, 1)
'''
function :send data
parameter:
data : Write data
'''
def send_data(self, data):
epdconfig.digital_write(self.dc_pin, 1)
epdconfig.digital_write(self.cs_pin, 0)
epdconfig.spi_writebyte([data])
epdconfig.digital_write(self.cs_pin, 1)
def send_data2(self, data):
epdconfig.digital_write(self.dc_pin, 1)
epdconfig.digital_write(self.cs_pin, 0)
epdconfig.spi_writebyte(data)
epdconfig.digital_write(self.cs_pin, 1)
'''
function :Wait until the busy_pin goes LOW
parameter:
'''
def ReadBusy(self):
logger.debug("e-Paper busy")
while(epdconfig.digital_read(self.busy_pin) == 1): # 0: idle, 1: busy
epdconfig.delay_ms(10)
logger.debug("e-Paper busy release")
'''
function : Turn On Display
parameter:
'''
def TurnOnDisplay(self):
self.send_command(0x22) # Display Update Control
self.send_data(0xF7)
self.send_command(0x20) # Activate Display Update Sequence
self.ReadBusy()
'''
function : Turn On Display Part
parameter:
'''
def TurnOnDisplayPart(self):
self.send_command(0x22) # Display Update Control
self.send_data(0xFF) # fast:0x0c, quality:0x0f, 0xcf
self.send_command(0x20) # Activate Display Update Sequence
# self.ReadBusy()
def TurnOnDisplayPart_Wait(self):
self.send_command(0x22) # Display Update Control
self.send_data(0xFF) # fast:0x0c, quality:0x0f, 0xcf
self.send_command(0x20) # Activate Display Update Sequence
self.ReadBusy()
'''
function : Setting the display window
parameter:
xstart : X-axis starting position
ystart : Y-axis starting position
xend : End position of X-axis
yend : End position of Y-axis
'''
def SetWindow(self, x_start, y_start, x_end, y_end):
self.send_command(0x44) # SET_RAM_X_ADDRESS_START_END_POSITION
# x point must be the multiple of 8 or the last 3 bits will be ignored
self.send_data((x_start>>3) & 0xFF)
self.send_data((x_end>>3) & 0xFF)
self.send_command(0x45) # SET_RAM_Y_ADDRESS_START_END_POSITION
self.send_data(y_start & 0xFF)
self.send_data((y_start >> 8) & 0xFF)
self.send_data(y_end & 0xFF)
self.send_data((y_end >> 8) & 0xFF)
'''
function : Set Cursor
parameter:
x : X-axis starting position
y : Y-axis starting position
'''
def SetCursor(self, x, y):
self.send_command(0x4E) # SET_RAM_X_ADDRESS_COUNTER
# x point must be the multiple of 8 or the last 3 bits will be ignored
self.send_data(x & 0xFF)
self.send_command(0x4F) # SET_RAM_Y_ADDRESS_COUNTER
self.send_data(y & 0xFF)
self.send_data((y >> 8) & 0xFF)
'''
function : Initialize the e-Paper register
parameter:
'''
def init(self, update):
if (epdconfig.module_init() != 0):
return -1
if update == self.FULL_UPDATE:
# 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(0xf9)
self.send_data(0x00)
self.send_data(0x00)
self.send_command(0x11) #data entry mode
self.send_data(0x03)
self.SetWindow(0, 0, self.width-1, self.height-1)
self.SetCursor(0, 0)
self.send_command(0x3c)
self.send_data(0x05)
self.send_command(0x21) # Display update control
self.send_data(0x00)
self.send_data(0x80)
self.send_command(0x18)
self.send_data(0x80)
self.ReadBusy()
else:
epdconfig.digital_write(self.reset_pin, 0)
epdconfig.delay_ms(1)
epdconfig.digital_write(self.reset_pin, 1)
self.send_command(0x01) #Driver output control
self.send_data(0xf9)
self.send_data(0x00)
self.send_data(0x00)
self.send_command(0x3C) #BorderWavefrom
self.send_data(0x80)
self.send_command(0x11) #data entry mode
self.send_data(0x03)
self.SetWindow(0, 0, self.width - 1, self.height - 1)
self.SetCursor(0, 0)
return 0
'''
function : Display images
parameter:
image : Image data
'''
def getbuffer(self, image):
img = image
imwidth, imheight = img.size
if(imwidth == self.width and imheight == self.height):
img = img.rotate(180, expand=True).convert('1')
elif(imwidth == self.height and imheight == self.width):
# image has correct dimensions, but needs to be rotated
img = img.rotate(270, expand=True).convert('1')
else:
logger.warning("Wrong image dimensions: must be " + str(self.width) + "x" + str(self.height))
# return a blank buffer
return [0x00] * (int(self.width/8) * self.height)
buf = bytearray(img.tobytes('raw'))
return buf
'''
function : Sends the image buffer in RAM to e-Paper and displays
parameter:
image : Image data
'''
def display(self, image):
if self.width%8 == 0:
linewidth = int(self.width/8)
else:
linewidth = int(self.width/8) + 1
self.send_command(0x24)
# for j in range(0, self.height):
# for i in range(0, linewidth):
# self.send_data(image[i + j * linewidth])
self.send_data2(image)
self.TurnOnDisplay()
'''
function : Sends the image buffer in RAM to e-Paper and partial refresh
parameter:
image : Image data
'''
def displayPartial(self, image):
epdconfig.digital_write(self.reset_pin, 0)
epdconfig.delay_ms(1)
epdconfig.digital_write(self.reset_pin, 1)
self.send_command(0x01) #Driver output control
self.send_data(0xf9)
self.send_data(0x00)
self.send_data(0x00)
self.send_command(0x3C) #BorderWavefrom
self.send_data(0x80)
self.send_command(0x11) #data entry mode
self.send_data(0x03)
self.SetWindow(0, 0, self.width - 1, self.height - 1)
self.SetCursor(0, 0)
self.send_command(0x24) # WRITE_RAM
self.send_data2(image)
self.TurnOnDisplayPart()
def displayPartial_Wait(self, image):
epdconfig.digital_write(self.reset_pin, 0)
epdconfig.delay_ms(1)
epdconfig.digital_write(self.reset_pin, 1)
self.send_command(0x01) #Driver output control
self.send_data(0xf9)
self.send_data(0x00)
self.send_data(0x00)
self.send_command(0x3C) #BorderWavefrom
self.send_data(0x80)
self.send_command(0x11) #data entry mode
self.send_data(0x03)
self.SetWindow(0, 0, self.width - 1, self.height - 1)
self.SetCursor(0, 0)
self.send_command(0x24) # WRITE_RAM
self.send_data2(image)
self.TurnOnDisplayPart_Wait()
'''
function : Refresh a base image
parameter:
image : Image data
'''
def displayPartBaseImage(self, image):
if self.width%8 == 0:
linewidth = int(self.width/8)
else:
linewidth = int(self.width/8) + 1
self.send_command(0x24)
for j in range(0, self.height):
for i in range(0, linewidth):
self.send_data(image[i + j * linewidth])
self.send_command(0x26)
for j in range(0, self.height):
for i in range(0, linewidth):
self.send_data(image[i + j * linewidth])
self.TurnOnDisplay()
'''
function : Clear screen
parameter:
'''
def Clear(self, color):
if self.width%8 == 0:
linewidth = int(self.width/8)
else:
linewidth = int(self.width/8) + 1
# logger.debug(linewidth)
self.send_command(0x24)
for j in range(0, self.height):
for i in range(0, linewidth):
self.send_data(color)
self.TurnOnDisplay()
'''
function : Enter sleep mode
parameter:
'''
def sleep(self):
self.send_command(0x10) #enter deep sleep
self.send_data(0x01)
epdconfig.delay_ms(2000)
def Dev_exit(self):
epdconfig.module_exit()
### END OF FILE ###
@@ -0,0 +1,586 @@
# *****************************************************************************
# * | File : epd2in9_V2.py
# * | Author : Waveshare team
# * | Function : Electronic paper driver
# * | Info :
# *----------------
# * | This version: V1.0
# * | Date : 2020-10-20
# # | Info : python demo
# -----------------------------------------------------------------------------
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documnetation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS OR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
#
import logging
from . import epdconfig
import numpy as np
# Display resolution
EPD_WIDTH = 128
EPD_HEIGHT = 296
class EPD_2IN9_V2:
def __init__(self):
self.reset_pin = epdconfig.EPD_RST_PIN
self.dc_pin = epdconfig.EPD_DC_PIN
self.busy_pin = epdconfig.EPD_BUSY_PIN
self.cs_pin = epdconfig.EPD_CS_PIN
self.width = EPD_WIDTH
self.height = EPD_HEIGHT
epdconfig.address = 0x48
WF_PARTIAL_2IN9 = [
0x0,0x40,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x80,0x80,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x40,0x40,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x80,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0A,0x0,0x0,0x0,0x0,0x0,0x0,
0x1,0x0,0x0,0x0,0x0,0x0,0x0,
0x1,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x22,0x22,0x22,0x22,0x22,0x22,0x0,0x0,0x0,
0x22,0x17,0x41,0xB0,0x32,0x36,
]
WF_PARTIAL_2IN9_Wait = [
0x0,0x40,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x80,0x80,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x40,0x40,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x80,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0A,0x0,0x0,0x0,0x0,0x0,0x2,
0x1,0x0,0x0,0x0,0x0,0x0,0x0,
0x1,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x0,0x0,0x0,0x0,0x0,0x0,0x0,
0x22,0x22,0x22,0x22,0x22,0x22,0x0,0x0,0x0,
0x22,0x17,0x41,0xB0,0x32,0x36,
]
Gray4 = [
0x00, 0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x20, 0x60, 0x10, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x28, 0x60, 0x14, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x2A, 0x60, 0x15, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x02, 0x00, 0x05, 0x14, 0x00, 0x00,
0x1E, 0x1E, 0x00, 0x00, 0x00, 0x00, 0x01,
0x00, 0x02, 0x00, 0x05, 0x14, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x24, 0x22, 0x22, 0x22, 0x23, 0x32, 0x00, 0x00, 0x00,
0x22, 0x17, 0x41, 0xAE, 0x32, 0x28,
]
WF_FULL = [
0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x90, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x60, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x19, 0x19, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x24, 0x42, 0x22, 0x22, 0x23, 0x32, 0x00, 0x00, 0x00,
0x22, 0x17, 0x41, 0xAE, 0x32, 0x38]
# Hardware reset
def reset(self):
epdconfig.digital_write(self.reset_pin, 1)
epdconfig.delay_ms(20)
epdconfig.digital_write(self.reset_pin, 0)
epdconfig.delay_ms(2)
epdconfig.digital_write(self.reset_pin, 1)
epdconfig.delay_ms(20)
def send_command(self, command):
epdconfig.digital_write(self.dc_pin, 0)
epdconfig.digital_write(self.cs_pin, 0)
epdconfig.spi_writebyte([command])
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])
epdconfig.digital_write(self.cs_pin, 1)
def send_data2(self, data):
epdconfig.digital_write(self.dc_pin, 1)
epdconfig.digital_write(self.cs_pin, 0)
epdconfig.spi_writebyte2(data)
epdconfig.digital_write(self.cs_pin, 1)
def ReadBusy(self):
# logging.debug("e-Paper busy")
while(epdconfig.digital_read(self.busy_pin) == 1): # 0: idle, 1: busy
epdconfig.delay_ms(0.1)
# logging.debug("e-Paper busy release")
def TurnOnDisplay(self):
self.send_command(0x22) # DISPLAY_UPDATE_CONTROL_2
self.send_data(0xF7)
self.send_command(0x20) # MASTER_ACTIVATION
self.ReadBusy()
def TurnOnDisplay_Partial(self):
self.send_command(0x22) # DISPLAY_UPDATE_CONTROL_2
self.send_data(0x0F)
self.send_command(0x20) # MASTER_ACTIVATION
# self.ReadBusy()
def TurnOnDisplay_Partial_Wait(self):
self.send_command(0x22) # DISPLAY_UPDATE_CONTROL_2
self.send_data(0x0F)
self.send_command(0x20) # MASTER_ACTIVATION
self.ReadBusy()
def TurnOnDisplay_4Gray(self):
self.send_command(0x22) # DISPLAY_UPDATE_CONTROL_2
self.send_data(0xC7)
self.send_command(0x20) # MASTER_ACTIVATION
self.ReadBusy()
def SendLut(self, lut):
self.send_command(0x32)
# for i in range(0, 153):
# self.send_data(self.WF_PARTIAL_2IN9[i])
if(lut):
self.send_data2(self.WF_PARTIAL_2IN9)
else:
self.send_data2(self.WF_PARTIAL_2IN9_Wait)
self.ReadBusy()
def lut(self, lut):
self.send_command(0x32)
for i in range(0, 153):
self.send_data(lut[i])
self.ReadBusy()
def SetLut(self, lut):
self.lut(lut)
self.send_command(0x3f)
self.send_data(lut[153])
self.send_command(0x03); # gate voltage
self.send_data(lut[154])
self.send_command(0x04); # source voltage
self.send_data(lut[155]) # VSH
self.send_data(lut[156]) # VSH2
self.send_data(lut[157]) # VSL
self.send_command(0x2c); # VCOM
self.send_data(lut[158])
def SetWindow(self, x_start, y_start, x_end, y_end):
self.send_command(0x44) # SET_RAM_X_ADDRESS_START_END_POSITION
# x point must be the multiple of 8 or the last 3 bits will be ignored
self.send_data((x_start>>3) & 0xFF)
self.send_data((x_end>>3) & 0xFF)
self.send_command(0x45) # SET_RAM_Y_ADDRESS_START_END_POSITION
self.send_data(y_start & 0xFF)
self.send_data((y_start >> 8) & 0xFF)
self.send_data(y_end & 0xFF)
self.send_data((y_end >> 8) & 0xFF)
def SetCursor(self, x, y):
self.send_command(0x4E) # SET_RAM_X_ADDRESS_COUNTER
# x point must be the multiple of 8 or the last 3 bits will be ignored
self.send_data(x & 0xFF)
self.send_command(0x4F) # SET_RAM_Y_ADDRESS_COUNTER
self.send_data(y & 0xFF)
self.send_data((y >> 8) & 0xFF)
self.ReadBusy()
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(0x27)
self.send_data(0x01)
self.send_data(0x00)
self.send_command(0x11) #data entry mode
self.send_data(0x03)
self.SetWindow(0, 0, self.width-1, self.height-1)
self.send_command(0x21) # Display update control
self.send_data(0x00)
self.send_data(0x80)
self.SetCursor(0, 0)
self.ReadBusy()
# EPD hardware init end
return 0
def init_Fast(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(0x27)
self.send_data(0x01)
self.send_data(0x00)
self.send_command(0x11) #data entry mode
self.send_data(0x03)
self.SetWindow(0, 0, self.width-1, self.height-1)
self.send_command(0x3C)
self.send_data(0x05)
self.send_command(0x21) # Display update control
self.send_data(0x00)
self.send_data(0x80)
self.SetCursor(0, 0)
self.ReadBusy()
self.SetLut(self.WF_FULL)
# EPD hardware init end
return 0
def Init_4Gray(self):
if (epdconfig.module_init() != 0):
return -1
self.reset()
epdconfig.delay_ms(100)
self.ReadBusy()
self.send_command(0x12) #SWRESET
self.ReadBusy()
self.send_command(0x01) #Driver output control
self.send_data(0x27)
self.send_data(0x01)
self.send_data(0x00)
self.send_command(0x11) #data entry mode
self.send_data(0x03)
self.SetWindow(8, 0, self.width, self.height-1)
self.send_command(0x3C)
self.send_data(0x04)
self.SetCursor(1, 0)
self.ReadBusy()
self.SetLut(self.Gray4)
# EPD hardware init end
return 0
def getbuffer(self, image):
# logging.debug("bufsiz = ",int(self.width/8) * self.height)
buf = [0xFF] * (int(self.width/8) * self.height)
image_monocolor = image.convert('1')
imwidth, imheight = image_monocolor.size
pixels = image_monocolor.load()
# logging.debug("imwidth = %d, imheight = %d",imwidth,imheight)
if(imwidth == self.width and imheight == self.height):
# logging.debug("Vertical")
for y in range(imheight):
for x in range(imwidth):
# Set the bits for the column of pixels at the current position.
if pixels[x, y] == 0:
buf[int((x + y * self.width) / 8)] &= ~(0x80 >> (x % 8))
elif(imwidth == self.height and imheight == self.width):
# logging.debug("Horizontal")
for y in range(imheight):
for x in range(imwidth):
newx = y
newy = self.height - x - 1
if pixels[x, y] == 0:
buf[int((newx + newy*self.width) / 8)] &= ~(0x80 >> (y % 8))
return buf
def getbuffer_4Gray(self, image):
# logger.debug("bufsiz = ",int(self.width/8) * self.height)
buf = [0xFF] * (int(self.width / 4) * self.height)
image_monocolor = image.convert('L')
imwidth, imheight = image_monocolor.size
pixels = image_monocolor.load()
i=0
# logger.debug("imwidth = %d, imheight = %d",imwidth,imheight)
if(imwidth == self.width and imheight == self.height):
# logger.debug("Vertical")
for y in range(imheight):
for x in range(imwidth):
# Set the bits for the column of pixels at the current position.
if(pixels[x, y] == 0xC0):
pixels[x, y] = 0x80
elif (pixels[x, y] == 0x80):
pixels[x, y] = 0x40
i= i+1
if(i%4 == 0):
buf[int((x + (y * self.width))/4)] = ((pixels[x-3, y]&0xc0) | (pixels[x-2, y]&0xc0)>>2 | (pixels[x-1, y]&0xc0)>>4 | (pixels[x, y]&0xc0)>>6)
elif(imwidth == self.height and imheight == self.width):
# logger.debug("Horizontal")
for x in range(imwidth):
for y in range(imheight):
newx = y
newy = self.height - x - 1
if(pixels[x, y] == 0xC0):
pixels[x, y] = 0x80
elif (pixels[x, y] == 0x80):
pixels[x, y] = 0x40
i= i+1
if(i%4 == 0):
buf[int((newx + (newy * self.width))/4)] = ((pixels[x, y-3]&0xc0) | (pixels[x, y-2]&0xc0)>>2 | (pixels[x, y-1]&0xc0)>>4 | (pixels[x, y]&0xc0)>>6)
return buf
def display(self, image):
if (image == None):
return
self.send_command(0x24) # WRITE_RAM
# for j in range(0, self.height):
# for i in range(0, int(self.width / 8)):
# self.send_data(image[i + j * int(self.width / 8)])
self.send_data2(image)
self.TurnOnDisplay()
def display_Base(self, image):
if (image == None):
return
self.send_command(0x24) # WRITE_RAM
# for j in range(0, self.height):
# for i in range(0, int(self.width / 8)):
# self.send_data(image[i + j * int(self.width / 8)])
self.send_data2(image)
self.send_command(0x26) # WRITE_RAM
# for j in range(0, self.height):
# for i in range(0, int(self.width / 8)):
# self.send_data(image[i + j * int(self.width / 8)])
self.send_data2(image)
self.TurnOnDisplay()
def display_Partial(self, image):
if (image == None):
return
# epdconfig.digital_write(self.reset_pin, 0)
# epdconfig.delay_ms(2)
# epdconfig.digital_write(self.reset_pin, 1)
# epdconfig.delay_ms(2)
self.SendLut(1)
self.send_command(0x37)
self.send_data(0x00)
self.send_data(0x00)
self.send_data(0x00)
self.send_data(0x00)
self.send_data(0x00)
self.send_data(0x40)
self.send_data(0x00)
self.send_data(0x00)
self.send_data(0x00)
self.send_data(0x00)
self.send_command(0x3C) #BorderWavefrom
self.send_data(0x80)
self.send_command(0x22)
self.send_data(0xC0)
self.send_command(0x20)
self.ReadBusy()
self.SetWindow(0, 0, self.width - 1, self.height - 1)
self.SetCursor(0, 0)
self.send_command(0x24) # WRITE_RAM
# for j in range(0, self.height):
# for i in range(0, int(self.width / 8)):
# self.send_data(image[i + j * int(self.width / 8)])
self.send_data2(image)
self.TurnOnDisplay_Partial()
def display_Partial_Wait(self, image):
if (image == None):
return
epdconfig.digital_write(self.reset_pin, 0)
epdconfig.delay_ms(1)
epdconfig.digital_write(self.reset_pin, 1)
# epdconfig.delay_ms(2)
self.SendLut(0)
self.send_command(0x37)
self.send_data(0x00)
self.send_data(0x00)
self.send_data(0x00)
self.send_data(0x00)
self.send_data(0x00)
self.send_data(0x40)
self.send_data(0x00)
self.send_data(0x00)
self.send_data(0x00)
self.send_data(0x00)
self.send_command(0x3C) #BorderWavefrom
self.send_data(0x80)
self.send_command(0x22)
self.send_data(0xC0)
self.send_command(0x20)
self.ReadBusy()
self.SetWindow(0, 0, self.width - 1, self.height - 1)
self.SetCursor(0, 0)
self.send_command(0x24) # WRITE_RAM
# for j in range(0, self.height):
# for i in range(0, int(self.width / 8)):
# self.send_data(image[i + j * int(self.width / 8)])
self.send_data2(image)
self.TurnOnDisplay_Partial_Wait()
def Clear(self, color):
self.send_command(0x24) # WRITE_RAM
for j in range(0, self.height):
for i in range(0, int(self.width / 8)):
self.send_data(color)
self.TurnOnDisplay()
def display_4Gray(self, image):
self.send_command(0x24)
for i in range(0, 4736):
temp3=0
for j in range(0, 2):
temp1 = image[i*2+j]
for k in range(0, 2):
temp2 = temp1&0xC0
if(temp2 == 0xC0):
temp3 |= 0x00
elif(temp2 == 0x00):
temp3 |= 0x01
elif(temp2 == 0x80):
temp3 |= 0x01
else: #0x40
temp3 |= 0x00
temp3 <<= 1
temp1 <<= 2
temp2 = temp1&0xC0
if(temp2 == 0xC0):
temp3 |= 0x00
elif(temp2 == 0x00):
temp3 |= 0x01
elif(temp2 == 0x80):
temp3 |= 0x01
else : #0x40
temp3 |= 0x00
if(j!=1 or k!=1):
temp3 <<= 1
temp1 <<= 2
self.send_data(temp3)
self.send_command(0x26)
for i in range(0, 4736):
temp3=0
for j in range(0, 2):
temp1 = image[i*2+j]
for k in range(0, 2):
temp2 = temp1&0xC0
if(temp2 == 0xC0):
temp3 |= 0x00
elif(temp2 == 0x00):
temp3 |= 0x01
elif(temp2 == 0x80):
temp3 |= 0x00
else: #0x40
temp3 |= 0x01
temp3 <<= 1
temp1 <<= 2
temp2 = temp1&0xC0
if(temp2 == 0xC0):
temp3 |= 0x00
elif(temp2 == 0x00):
temp3 |= 0x01
elif(temp2 == 0x80):
temp3 |= 0x00
else: #0x40
temp3 |= 0x01
if(j!=1 or k!=1):
temp3 <<= 1
temp1 <<= 2
self.send_data(temp3)
self.TurnOnDisplay_4Gray()
def sleep(self):
self.send_command(0x10) # DEEP_SLEEP_MODE
self.send_data(0x01)
def Dev_exit(self):
epdconfig.module_exit()
### END OF FILE ###
@@ -0,0 +1,140 @@
# /*****************************************************************************
# * | File : epdconfig.py
# * | Author : Waveshare team
# * | Function : Hardware underlying interface
# * | Info :
# *----------------
# * | This version: V1.0
# * | Date : 2020-12-21
# * | Info :
# ******************************************************************************
# Permission is hereby granted, free of charge, to any person obtaining a copy
# of this software and associated documnetation files (the "Software"), to deal
# in the Software without restriction, including without limitation the rights
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
# copies of the Software, and to permit persons to whom the Software is
# furished to do so, subject to the following conditions:
#
# The above copyright notice and this permission notice shall be included in
# all copies or substantial portions of the Software.
#
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
# FITNESS OR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
# LIABILITY WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
# THE SOFTWARE.
#
import gpiozero
import time
from smbus import SMBus
import spidev
import ctypes
import logging
# e-Paper
EPD_RST_PIN = 17
EPD_DC_PIN = 25
EPD_CS_PIN = 8
EPD_BUSY_PIN = 24
# TP
TRST = 22
INT = 27
spi = spidev.SpiDev(0, 0)
address = 0x0
# address = 0x14
# address = 0x48
bus = SMBus(1)
GPIO_RST_PIN = gpiozero.LED(EPD_RST_PIN)
GPIO_DC_PIN = gpiozero.LED(EPD_DC_PIN)
# GPIO_CS_PIN = gpiozero.LED(EPD_CS_PIN)
GPIO_TRST = gpiozero.LED(TRST)
GPIO_BUSY_PIN = gpiozero.Button(EPD_BUSY_PIN, pull_up = False)
GPIO_INT = gpiozero.Button(INT, pull_up = False)
def digital_write(pin, value):
if pin == EPD_RST_PIN:
if value:
GPIO_RST_PIN.on()
else:
GPIO_RST_PIN.off()
elif pin == EPD_DC_PIN:
if value:
GPIO_DC_PIN.on()
else:
GPIO_DC_PIN.off()
# elif pin == EPD_CS_PIN:
# if value:
# GPIO_CS_PIN.on()
# else:
# GPIO_CS_PIN.off()
elif pin == TRST:
if value:
GPIO_TRST.on()
else:
GPIO_TRST.off()
def digital_read(pin):
if pin == EPD_BUSY_PIN:
return GPIO_BUSY_PIN.value
elif pin == INT:
return GPIO_INT.value
def delay_ms(delaytime):
time.sleep(delaytime / 1000.0)
def spi_writebyte(data):
spi.writebytes(data)
def spi_writebyte2(data):
spi.writebytes2(data)
def i2c_writebyte(reg, value):
bus.write_word_data(address, (reg>>8) & 0xff, (reg & 0xff) | ((value & 0xff) << 8))
def i2c_write(reg):
bus.write_byte_data(address, (reg>>8) & 0xff, reg & 0xff)
def i2c_readbyte(reg, len):
i2c_write(reg)
rbuf = []
for i in range(len):
rbuf.append(int(bus.read_byte(address)))
return rbuf
def module_init():
spi.max_speed_hz = 10000000
spi.mode = 0b00
return 0
def module_exit():
logging.debug("spi end")
spi.close()
bus.close()
logging.debug("close 5V, Module enters 0 power consumption ...")
GPIO_RST_PIN.off()
GPIO_DC_PIN.off()
# GPIO_CS_PIN.off()
GPIO_TRST.off()
GPIO_RST_PIN.close()
GPIO_DC_PIN.close()
# GPIO_CS_PIN.close()
GPIO_TRST.close()
GPIO_BUSY_PIN.close()
GPIO_INT.close()
### END OF FILE ###
@@ -0,0 +1,84 @@
import logging
from . import epdconfig as config
class GT_Development:
def __init__(self):
self.Touch = 0
self.TouchpointFlag = 0
self.TouchCount = 0
self.Touchkeytrackid = [0, 1, 2, 3, 4]
self.X = [0, 1, 2, 3, 4]
self.Y = [0, 1, 2, 3, 4]
self.S = [0, 1, 2, 3, 4]
class GT1151:
def __init__(self):
# e-Paper
self.ERST = config.EPD_RST_PIN
self.DC = config.EPD_DC_PIN
self.CS = config.EPD_CS_PIN
self.BUSY = config.EPD_BUSY_PIN
# TP
self.TRST = config.TRST
self.INT = config.INT
def digital_read(self, pin):
return config.digital_read(pin)
def GT_Reset(self):
config.digital_write(self.TRST, 1)
config.delay_ms(100)
config.digital_write(self.TRST, 0)
config.delay_ms(100)
config.digital_write(self.TRST, 1)
config.delay_ms(100)
def GT_Write(self, Reg, Data):
config.i2c_writebyte(Reg, Data)
def GT_Read(self, Reg, len):
return config.i2c_readbyte(Reg, len)
def GT_ReadVersion(self):
buf = self.GT_Read(0x8140, 4)
print(buf)
def GT_Init(self):
self.GT_Reset()
self.GT_ReadVersion()
def GT_Scan(self, GT_Dev, GT_Old):
buf = []
mask = 0x00
if(GT_Dev.Touch == 1):
GT_Dev.Touch = 0
buf = self.GT_Read(0x814E, 1)
if(buf[0]&0x80 == 0x00):
self.GT_Write(0x814E, mask)
config.delay_ms(10)
else:
GT_Dev.TouchpointFlag = buf[0]&0x80
GT_Dev.TouchCount = buf[0]&0x0f
if(GT_Dev.TouchCount > 5 or GT_Dev.TouchCount < 1):
self.GT_Write(0x814E, mask)
return
buf = self.GT_Read(0x814F, GT_Dev.TouchCount*8)
self.GT_Write(0x814E, mask)
GT_Old.X[0] = GT_Dev.X[0];
GT_Old.Y[0] = GT_Dev.Y[0];
GT_Old.S[0] = GT_Dev.S[0];
for i in range(0, GT_Dev.TouchCount, 1):
GT_Dev.Touchkeytrackid[i] = buf[0 + 8*i]
GT_Dev.X[i] = (buf[2 + 8*i] << 8) + buf[1 + 8*i]
GT_Dev.Y[i] = (buf[4 + 8*i] << 8) + buf[3 + 8*i]
GT_Dev.S[i] = (buf[6 + 8*i] << 8) + buf[5 + 8*i]
print(GT_Dev.X[0], GT_Dev.Y[0], GT_Dev.S[0])
@@ -0,0 +1,89 @@
import logging
from . import epdconfig as config
class ICNT_Development:
def __init__(self):
self.Touch = 0
self.TouchGestureid = 0
self.TouchCount = 0
self.TouchEvenid = [0, 1, 2, 3, 4]
self.X = [0, 1, 2, 3, 4]
self.Y = [0, 1, 2, 3, 4]
self.P = [0, 1, 2, 3, 4]
class INCT86:
def __init__(self):
# e-Paper
self.ERST = config.EPD_RST_PIN
self.DC = config.EPD_DC_PIN
self.CS = config.EPD_CS_PIN
self.BUSY = config.EPD_BUSY_PIN
# TP
self.TRST = config.TRST
self.INT = config.INT
def digital_read(self, pin):
return config.digital_read(pin)
def ICNT_Reset(self):
config.digital_write(self.TRST, 1)
config.delay_ms(100)
config.digital_write(self.TRST, 0)
config.delay_ms(100)
config.digital_write(self.TRST, 1)
config.delay_ms(100)
def ICNT_Write(self, Reg, Data):
config.i2c_writebyte(Reg, Data)
def ICNT_Read(self, Reg, len):
return config.i2c_readbyte(Reg, len)
def ICNT_ReadVersion(self):
buf = self.ICNT_Read(0x000a, 4)
print(buf)
def ICNT_Init(self):
self.ICNT_Reset()
self.ICNT_ReadVersion()
def ICNT_Scan(self, ICNT_Dev, ICNT_Old):
buf = []
mask = 0x00
if(ICNT_Dev.Touch == 1):
# ICNT_Dev.Touch = 0
buf = self.ICNT_Read(0x1001, 1)
if(buf[0] == 0x00):
self.ICNT_Write(0x1001, mask)
config.delay_ms(1)
# print("buffers status is 0")
return
else:
ICNT_Dev.TouchCount = buf[0]
if(ICNT_Dev.TouchCount > 5 or ICNT_Dev.TouchCount < 1):
self.ICNT_Write(0x1001, mask)
ICNT_Dev.TouchCount = 0
# print("TouchCount number is wrong")
return
buf = self.ICNT_Read(0x1002, ICNT_Dev.TouchCount*7)
self.ICNT_Write(0x1001, mask)
ICNT_Old.X[0] = ICNT_Dev.X[0];
ICNT_Old.Y[0] = ICNT_Dev.Y[0];
ICNT_Old.P[0] = ICNT_Dev.P[0];
for i in range(0, ICNT_Dev.TouchCount, 1):
ICNT_Dev.TouchEvenid[i] = buf[6 + 7*i]
ICNT_Dev.X[i] = 295 - ((buf[2 + 7*i] << 8) + buf[1 + 7*i])
ICNT_Dev.Y[i] = 127 - ((buf[4 + 7*i] << 8) + buf[3 + 7*i])
ICNT_Dev.P[i] = buf[5 + 7*i]
print(ICNT_Dev.X[0], ICNT_Dev.Y[0], ICNT_Dev.P[0])
return
return
@@ -0,0 +1,261 @@
# This little program is for the Waveshare 2.9
# inch Version 2 black and white only epaper display
# It uses OpenWeatherMap API to display weather info
import sys
import os
picdir = os.path.join(os.path.dirname(os.path.realpath(__file__)), '../../pic/2in9')
icondir = os.path.join(picdir, 'icon')
fontdir = os.path.join(os.path.dirname(os.path.realpath(__file__)), '../../pic')
# Search lib folder for display driver modules
sys.path.append('lib')
from . import epd2in9_V2
epd = epd2in9_V2.EPD_2IN9_V2()
from datetime import datetime
import time
from PIL import Image,ImageDraw,ImageFont
import traceback
import requests, json
from io import BytesIO
import csv
# define funciton for writing image and sleeping for 5 min.
def write_to_screen(image, sleep_seconds):
print('Writing to screen.')
# Write to screen
h_image = Image.new('1', (epd.height, epd.width), 255)
# Open the template
screen_output_file = Image.open(os.path.join(picdir, image))
# Initialize the drawing context with template as background
h_image.paste(screen_output_file, (0, 0))
epd.display(epd.getbuffer(h_image))
# Sleep
print('Sleeping for ' + str(sleep_seconds) +'.')
time.sleep(sleep_seconds)
# define function for displaying error
def display_error(error_source):
# Display an error
print('Error in the', error_source, 'request.')
# Initialize drawing
error_image = Image.new('1', (epd.height, epd.width), 255)
# Initialize the drawing
draw = ImageDraw.Draw(error_image)
draw.text((5, 5), error_source +' ERROR', font=font20, fill=black)
draw.text((5, 30), 'Retrying in 30 seconds', font=font20, fill=black)
current_time = datetime.now().strftime('%H:%M')
draw.text((5, 55), 'Last Refresh: ' + str(current_time), font = font20, fill=black)
# Save the error image
error_image_file = 'error.png'
error_image.save(os.path.join(picdir, error_image_file))
# Close error image
error_image.close()
# Write error to screen
write_to_screen(error_image_file, 30)
# Set the fonts
font12 = ImageFont.truetype(os.path.join(fontdir, 'Font.ttc'), 12)
font16 = ImageFont.truetype(os.path.join(fontdir, 'Font.ttc'), 16)
font20 = ImageFont.truetype(os.path.join(fontdir, 'Font.ttc'), 20)
font24 = ImageFont.truetype(os.path.join(fontdir, 'Font.ttc'), 24)
font30 = ImageFont.truetype(os.path.join(fontdir, 'Font.ttc'), 30)
font35 = ImageFont.truetype(os.path.join(fontdir, 'Font.ttc'), 35)
font50 = ImageFont.truetype(os.path.join(fontdir, 'Font.ttc'), 50)
font60 = ImageFont.truetype(os.path.join(fontdir, 'Font.ttc'), 60)
font100 = ImageFont.truetype(os.path.join(fontdir, 'Font.ttc'), 100)
font160 = ImageFont.truetype(os.path.join(fontdir, 'Font.ttc'), 160)
# Set the special fonts
font18_Roboto_Bold = ImageFont.truetype(os.path.join(fontdir, 'Roboto-Bold.ttf'), 18)
font20_Roboto_Bold = ImageFont.truetype(os.path.join(fontdir, 'Roboto-Bold.ttf'), 20)
font20_Roboto_Regular = ImageFont.truetype(os.path.join(fontdir, 'Roboto-Regular.ttf'), 20)
font34_Roboto_Black = ImageFont.truetype(os.path.join(fontdir, 'Roboto-Black.ttf'), 34)
# Set the colors
black = 'rgb(0,0,0)'
white = 'rgb(255,255,255)'
grey = 'rgb(235,235,235)'
# Initialize and clear screen
# print('Initializing and clearing screen.')
# epd.init()
# epd.Clear()
# I provide my API_KEY for you to test: 82ec63bb0530e31e0ef9042786d195cc, Please try to use your own API_KEY
API_KEY = '******API KEY*******'
LOCATION = 'Shenzhen'
LATITUDE = '22.543097'
LONGITUDE = '114.057861'
UNITS = 'imperial'
CSV_OPTION = False # if csv_option == True, a weather data will be appended to 'record.csv'
BASE_URL = 'http://api.openweathermap.org/data/2.5/onecall?'
URL = BASE_URL + 'lat=' + LATITUDE + '&lon=' + LONGITUDE + '&units=' + UNITS +'&appid=' + API_KEY
def get_weather_png():
# Ensure there are no errors with connection
error_connect = True
while error_connect == True:
try:
# HTTP request
print('Attempting to connect to OWM.')
response = requests.get(URL)
print('Connection to OWM successful.')
error_connect = None
except:
# Call function to display connection error
print('Connection error.')
display_error('CONNECTION')
error = None
while error == None:
# Check status of code request
if response.status_code == 200:
print('Connection to Open Weather successful.')
# get data in jason format
data = response.json()
# get current dict block
current = data['current']
# get current
temp_current = current['temp']
# get feels like
feels_like = current['feels_like']
# get humidity
humidity = current['humidity']
# get pressure
wind = current['wind_speed']
# get description
weather = current['weather']
report = weather[0]['description']
# get icon url
icon_code = weather[0]['icon']
#icon_URL = 'http://openweathermap.org/img/wn/'+ icon_code +'@4x.png'
# get daily dict block
daily = data['daily']
# get daily precip
daily_precip_float = daily[0]['pop']
#format daily precip
daily_precip_percent = daily_precip_float * 100
# get min and max temp
daily_temp = daily[0]['temp']
temp_max = daily_temp['max']
temp_min = daily_temp['min']
# Append weather data to CSV if csv_option == True
if CSV_OPTION == True:
# Get current year, month, date, and time
current_year = datetime.now().strftime('%Y')
current_month = datetime.now().strftime('%m')
current_date = datetime.now().strftime('%d')
current_time = datetime.now().strftime('%H:%M')
#open the CSV and append weather data
with open('records.csv', 'a', newline='') as csv_file:
writer = csv.writer(csv_file, delimiter=',')
writer.writerow([current_year, current_month, current_date, current_time,
LOCATION,temp_current, feels_like, temp_max, temp_min,
humidity, daily_precip_float, wind])
print('Weather data appended to CSV.')
# Set strings to be printed to screen
string_location = 'City: ' + LOCATION
string_temp_current = format(temp_current, '.0f') + u'\N{DEGREE SIGN}F'
string_temp_current_C = format((temp_current-32)/1.8, '.0f') + u'\N{DEGREE SIGN}C'
string_temp = string_temp_current + ' / ' + string_temp_current_C
string_feels_like = 'Feels like: ' + format(feels_like, '.0f') + u'\N{DEGREE SIGN}F'
string_humidity = 'Humidity: ' + str(humidity) + '%'
string_wind = 'Wind: ' + format(wind, '.1f') + ' MPH'
# string_report = 'Now: ' + report.title()
string_report = report.title()
string_temp_max = 'High: ' + format(temp_max, '>.0f') + u'\N{DEGREE SIGN}F'
string_temp_min = 'Low: ' + format(temp_min, '>.0f') + u'\N{DEGREE SIGN}F'
string_precip_percent = 'Precip: ' + str(format(daily_precip_percent, '.0f')) + '%'
# Set error code to false
error = False
'''
print('Location:', LOCATION)
print('Temperature:', format(temp_current, '.0f'), u'\N{DEGREE SIGN}F')
print('Feels Like:', format(feels_like, '.0f'), 'F')
print('Humidity:', humidity)
print('Wind Speed:', format(wind_speed, '.1f'), 'MPH')
print('Report:', report.title())
print('High:', format(temp_max, '.0f'), 'F')
print('Low:', format(temp_min, '.0f'), 'F')
print('Probabilty of Precipitation: ' + str(format(daily_precip_percent, '.0f')) + '%')
'''
else:
# Call function to display HTTP error
display_error('HTTP')
# Open template file
template = Image.open(os.path.join(picdir, 'template.bmp'))
# Initialize the drawing context with template as background
draw = ImageDraw.Draw(template)
draw.rectangle((0, 0, 295, 67), fill=white)
# Draw top left box
## Open icon file
icon_file = icon_code + '.png'
icon_image = Image.open(os.path.join(icondir, icon_file))
icon_image_resize = icon_image.resize((68, 68))
### Paste the image
template.paste(icon_image_resize, (0, 0))
## Place a black rectangle outline
# draw.rectangle((15, 5, 80, 60), outline=black)
## Draw text
font_report = font20_Roboto_Bold
font_report_size = 20
while(font_report.getsize(string_report)[0] > 120):
font_report_size -= 2
font_report = ImageFont.truetype(os.path.join(fontdir, 'Roboto-Bold.ttf'), font_report_size)
draw.text((70, 12), string_report, font=font_report, fill=black)
draw.text((70, 34), string_precip_percent, font=font20_Roboto_Bold, fill=black)
# Draw top right box
draw.text((12, 72), string_temp, font=font18_Roboto_Bold, fill=white)
# draw.text((60, 30), string_feels_like, font=font20, fill=white)
# Draw bottom left box
# draw.text((15, 85), string_temp_max, font=font20, fill=black)
# draw.rectangle((15, 108, 265, 110), fill=black)
# draw.text((15, 105), string_temp_min, font=font20, fill=black)
# Draw bottom middle box
# draw.text((120, 85), string_humidity, font=font20, fill=black)
# draw.text((120, 105), string_wind, font=font20, fill=black)
# Draw bottom right box
draw.text((295-11-font20_Roboto_Regular.getsize('UPDATED')[0], 7), 'UPDATED', font=font20_Roboto_Regular, fill=black, align='right')
current_time = datetime.now().strftime('%H:%M')
draw.text((295-11-font34_Roboto_Black.getsize(current_time)[0], 25), current_time, font = font34_Roboto_Black, fill=black, align='right')
# draw.rectangle((193, 35, 288, 85), outline=black)
draw.text((295-11-font18_Roboto_Bold.getsize(string_location)[0], 72), string_location, font = font18_Roboto_Bold, fill=white, align='right')
## Add a reminder to take out trash on Mon and Thurs
# weekday = datetime.today().weekday()
# if weekday == 0 or weekday == 3:
# draw.rectangle((345, 13, 705, 55), fill =black)
# draw.text((355, 15), 'TAKE OUT TRASH TODAY!', font=font18, fill=white)
# Save the image for display as PNG
screen_output_file = os.path.join(picdir, 'screen_output.png')
template.save(screen_output_file)
# Close the template file
template.close()
# Refresh clear screen to avoid burn-in at 3:00 AM
# if datetime.now().strftime('%H') == '03':
# print('Clearning screen to avoid burn-in.')
# epd.Clear()
# Write to screen
# write_to_screen(screen_output_file, 600)