小结
电子相册功能已完成,附带一个日历效果。
可以通过同局域网samba实现手机或者电脑直接将图片传到vf2中,并在代码中设定轮流播放的时间。
记录生活照片或者做成文物日历。
基础功能暂时告一段落。
使用感受:
- vf2提供了python控制gpio接口,简化了驱动的实现。
- vf2的python实现很方便,直接调用库实现图片的等比放大,转成想要的色深等等。
- 后续完全可以结合i2c等实现对应传感器数据的显示,我就不在这里更新了。
此外还有一些遗憾
- 缺少wifi,始终需要使用网口
- 测试下来,使用python将一张图解析出来转色深到lcd上,需要3s以上,之后我再基于同版参数和其他的开发板做评估吧。
- 本打算实现音频接口功能,由于时间有限,加上刷机有点没弄明白,不是一次性刷到sd卡中,所以音频的部分只能搁置。
- 人脸识别的部分以后再做吧,可以结合led灯阵做成寄存柜,之后项目再更新。
"""
Please make sure the 2.4inch LCD Moudle is connected to the correct pins.
The following table describes how to connect the 2.4inch LCD Module to the 40-pin header.
-------------------------------------------------
__2.4inch LCD Module___Pin Number_____Pin Name
VCC 17 3.3 V Power
GND 39 GND
DIN 19 SPI MOSI
CLK 23 SPI SCLK
CS 13 GPIO43 y
DC 11 GPIO42 y -
RST 07 GPIO55 y -
BL 15 GPIO47 y
-------------------------------------------------
"""
import os
import sys
import time
import logging
from PIL import Image
from datetime import datetime
sys.path.append("..")
import VisionFive.boardtype as board_t
from lib import LCD_ST7735_lib
from lib import LCD_GC9306_lib
from lib import LCD_ILI9488_lib
"""
--------------------------------------------------------------- {
Init
"""
WHITE = 0xffffff
BLUE = 0xFF0000
lcd_num = 3
pin_res = 7
pin_dc = 11
vf_t = board_t.boardtype()
print("vf_t ",vf_t)
if vf_t == 1:
SPI_DEVICE = "/dev/spidev0.0"
elif vf_t == 2:
SPI_DEVICE = "/dev/spidev1.0"
else:
print("This module can only be run on a VisionFive board!")
"""The initialization settings of 2inch and 2.4inch are distinguished"""
match lcd_num:
case 1:
print("lcd st7735")
disp = LCD_ST7735_lib.LCD_ST7735(7, 11, SPI_DEVICE)
disp.lcd_init_st7735()
case 2:
print("lcd gc9306")
disp = LCD_GC9306_lib.LCD_GC9306(7, 11, SPI_DEVICE)
disp.lcd_init_gc9306()
case 3:
print("lcd ili9488")
disp = LCD_ILI9488_lib.LCD_ILI9488(7, 11, SPI_DEVICE)
disp.lcd_init_ili9488()
case _:
print("unknown lcd")
folder_path = "./picture"
items = os.listdir(folder_path)
file_paths = []
for item in items:
item_path = os.path.join(folder_path, item)
if os.path.isfile(item_path) and "._" not in item and ".DS_Store" not in item:
file_paths.append(item_path)
"""
} ---------------------------------------------------------------
"""
def show_img(image_path):
time_start = time.time()
print(image_path)
disp.lcd_ShowImage(image_path, 0, 50)
time_end = time.time()
print("cost time:",time_end-time_start)
def test_clear():
print("clear screen -- White")
disp.lcd_clear(WHITE)
time.sleep(2)
print("clear screen -- Blue")
if lcd_num == 3:
Blue=0x03F000
else:
Blue=0x001f
disp.lcd_clear(Blue)
time.sleep(2)
def get_time():
times = time.time()
local_times = time.localtime(times)
local_time_asctimes = time.asctime(local_times)
return local_time_asctimes
def get_time2():
now = datetime.now()
formatted_time = now.strftime("%Y年%m月%d日 %H时%M分%S秒")
latinFileName = formatted_time.encode("utf-8").decode("latin1")
return latinFileName
def get_file_list():
file_nummax = 0
folder_path = "./picture"
items = os.listdir(folder_path)
file_paths = []
for item in items:
item_path = os.path.join(folder_path, item)
if os.path.isfile(item_path) and "._" not in item and ".DS_Store" not in item:
file_paths.append(item_path)
file_nummax += 1
print("file max",file_nummax)
return file_paths,file_nummax
def is_12h():
time_hour = datetime.now().hour
if time_hour == 24 & flag_update == True:
print("12点了")
flag_update = False
return True
else:
flag_update = True
print(time_hour)
return False
def is_sec(sec=0):
time_second = datetime.now().second
if time_second % sec == 0 :
return True
return False
def main():
print("-----------lcd demo-------------")
disp.lcd_clear(WHITE)
print(get_time(),"show text")
disp.display_text(get_time())
show_img("./picture_column/a.png")
file_num = 1
(file_list, file_num_max) = get_file_list()
print(file_list[file_num], file_num_max)
show_img(file_list[file_num])
flag_update = False
print(get_time(),"start")
while 1:
disp.display_text(get_time())
if is_sec(10) == True:
if flag_update == True:
file_num += 1
if file_num == file_num_max:
file_num = 0
print("\n= ",get_time())
show_img(file_list[file_num])
flag_update = False
else:
flag_update = True
print("Exit demo!")
if __name__ == '__main__':
main()
import os
import sys
import time
import logging
import VisionFive.spi as spi
import VisionFive.gpio as gpio
import numpy as np
from PIL import Image, ImageDraw, ImageFont
class LCD_ILI9488:
width = 320
height = 480
rotate = 180
WHITE = 0xffffff
def __init__(self, rst_pin, dc_pin, dev):
gpio.setmode(gpio.BOARD)
self.pin_rst = rst_pin
self.pin_dc = dc_pin
self.pin_bl = 15
self.spidev = dev
spi.getdev(self.spidev)
"""Reset the maximum clock frequency of communication"""
"""The display speed of the picture is positively correlated with the clock frequency"""
spi.setmode(40000000, 0, 8)
gpio.setup(self.pin_rst, gpio.OUT)
gpio.setup(self.pin_dc, gpio.OUT)
gpio.setup(self.pin_bl, gpio.OUT)
def __del__(self):
spi.freedev()
"""add a short delay for each change of electrical level"""
def lcd_reset(self):
gpio.output(self.pin_bl, gpio.HIGH)
gpio.output(self.pin_rst, gpio.LOW)
time.sleep(0.100)
gpio.output(self.pin_rst, gpio.HIGH)
time.sleep(0.100)
gpio.output(self.pin_bl, gpio.HIGH)
def lcd_spisend(self, data):
spi.transfer(data)
def lcd_sendcmd(self, cmd):
gpio.output(self.pin_dc, gpio.LOW)
spi.transfer(cmd)
def lcd_senddata(self, data):
gpio.output(self.pin_dc, gpio.HIGH)
spi.transfer(data)
"""write multiple bytes"""
def lcd_sendnbytes(self, data):
gpio.output(self.pin_dc, gpio.HIGH)
spi.write(data)
"""common registers' initialization of 2.4inch LCD module"""
def lcd_init_ili9488(self):
self.lcd_reset()
self.lcd_sendcmd(0xE0)
self.lcd_senddata(0x00)
self.lcd_senddata(0x03)
self.lcd_senddata(0x09)
self.lcd_senddata(0x08)
self.lcd_senddata(0x16)
self.lcd_senddata(0x0A)
self.lcd_senddata(0x3F)
self.lcd_senddata(0x78)
self.lcd_senddata(0x4C)
self.lcd_senddata(0x09)
self.lcd_senddata(0x0A)
self.lcd_senddata(0x08)
self.lcd_senddata(0x16)
self.lcd_senddata(0x1A)
self.lcd_senddata(0x0F)
self.lcd_sendcmd(0xE1)
self.lcd_senddata(0x00)
self.lcd_senddata(0x16)
self.lcd_senddata(0x19)
self.lcd_senddata(0x03)
self.lcd_senddata(0x0F)
self.lcd_senddata(0x05)
self.lcd_senddata(0x32)
self.lcd_senddata(0x45)
self.lcd_senddata(0x46)
self.lcd_senddata(0x04)
self.lcd_senddata(0x0E)
self.lcd_senddata(0x0D)
self.lcd_senddata(0x35)
self.lcd_senddata(0x37)
self.lcd_senddata(0x0F)
self.lcd_sendcmd(0xC0)
self.lcd_sendcmd(0x17)
self.lcd_senddata(0x15)
self.lcd_sendcmd(0xC1)
self.lcd_senddata(0x41)
self.lcd_sendcmd(0xC5)
self.lcd_sendcmd(0x00)
self.lcd_senddata(0x12)
self.lcd_senddata(0x80)
self.lcd_sendcmd(0x36)
self.lcd_sendcmd(0x88)
self.lcd_sendcmd(0x3A)
self.lcd_senddata(0x66)
self.lcd_sendcmd(0xC8)
self.lcd_senddata(0xB1)
self.lcd_sendcmd(0xB0)
self.lcd_sendcmd(0x80)
self.lcd_sendcmd(0xB1)
self.lcd_sendcmd(0x80)
self.lcd_sendcmd(0xB4)
self.lcd_sendcmd(0x02)
self.lcd_sendcmd(0xB6)
self.lcd_sendcmd(0x02)
self.lcd_senddata(0x02)
self.lcd_sendcmd(0xE9)
self.lcd_senddata(0x00)
self.lcd_sendcmd(0x53)
self.lcd_senddata(0x28)
self.lcd_sendcmd(0x51)
self.lcd_senddata(0x7F)
self.lcd_sendcmd(0xF7)
self.lcd_senddata(0xA9)
self.lcd_senddata(0x51)
self.lcd_senddata(0x2C)
self.lcd_senddata(0x02)
self.lcd_sendcmd(0x11)
time.sleep(0.100)
self.lcd_sendcmd(0x29)
def lcd_set_rotate():
match self.rotate:
case 0:
self.lcd_sendcmd(0x36)
self.lcd_sendcmd(0x88)
case 90:
self.lcd_sendcmd(0x36)
self.lcd_sendcmd(0x28)
case 180:
self.lcd_sendcmd(0x36)
self.lcd_sendcmd(0x48)
case 270:
self.lcd_sendcmd(0x36)
self.lcd_sendcmd(0xE8)
case _:
self.lcd_sendcmd(0x36)
self.lcd_sendcmd(0x88)
def lcd_setPos(self, Xstart, Ystart, Xend, Yend):
self.lcd_sendcmd(0x2A)
self.lcd_senddata(Xstart >> 8)
self.lcd_senddata(Xstart & 0xFF)
self.lcd_senddata((Xend - 1) >> 8)
self.lcd_senddata((Xend - 1) & 0xFF)
self.lcd_sendcmd(0x2B)
self.lcd_senddata(Ystart >> 8)
self.lcd_senddata(Ystart & 0xFF)
self.lcd_senddata((Yend - 1) >> 8)
self.lcd_senddata((Yend - 1) & 0xFF)
self.lcd_sendcmd(0x2C)
def lcd_clear(self, color):
"""Clear contents of image buffer"""
_buffer = [color] * (self.width * self.height * 3)
print(_buffer[0],_buffer[1],_buffer[2])
self.lcd_setPos(0, 0, self.width, self.height)
gpio.output(self.pin_dc, gpio.HIGH)
"""modify the original single byte write to multi byte write"""
self.lcd_sendnbytes(_buffer)
def lcd_clear_range(self, color, x_start, y_start, x_end, y_end):
"""Clear contents of image buffer"""
_buffer = [color] * (self.width * self.height * 3)
print(_buffer[0],_buffer[1],_buffer[2])
self.lcd_setPos(x_start, y_start, x_end, y_end)
gpio.output(self.pin_dc, gpio.HIGH)
"""modify the original single byte write to multi byte write"""
self.lcd_sendnbytes(_buffer)
def Image_to_RGB565(self, Image):
img = np.asarray(Image)
pix = np.zeros((self.width, self.height, 3), dtype=np.uint8)
pix[..., [0]] = np.add(
np.bitwise_and(img[..., [0]], 0xF8), np.right_shift(img[..., [1]], 5)
)
pix[..., [1]] = np.add(
np.bitwise_and(np.left_shift(img[..., [1]], 3), 0xE0),
np.right_shift(img[..., [2]], 3),
)
pix = pix.flatten().tolist()
return pix
def Image_to_RGB666(self, Image):
img = np.asarray(Image)
pix = np.zeros((self.width, self.height, 3), dtype=np.uint8)
pix[..., 0] = np.right_shift(img[..., 0], 2)
pix[..., 1] = np.right_shift(img[..., 1], 2)
pix[..., 2] = np.right_shift(img[..., 2], 2)
return pix
def Image_RGB888_to_RGB666(self, Image):
img = np.asarray(Image)
pix = np.zeros((self.height, self.width, 3), dtype=np.uint8)
pix[..., [0]] = np.left_shift(np.left_shift(img[..., [0]], 2), 2)
pix[..., [1]] = np.left_shift(np.left_shift(img[..., [1]], 2), 2)
pix[..., [2]] = np.left_shift(np.left_shift(img[..., [2]], 2), 2)
return pix.flatten().tolist()
def display_text(self, text, font_size=30, x=0, y=10, color=(0,0,0)):
font_width = 320
font_height = 50
image = Image.new('RGB', (font_width, font_height), color=(255, 255, 255))
draw = ImageDraw.Draw(image)
try:
font = ImageFont.truetype('/usr/01_LCD/lib/DejaVuSans.ttf', font_size)
except IOError:
font = ImageFont.load_default()
draw.text((x, y), text, font=font, fill=color)
img_array = np.asarray(image, dtype=np.uint8)
pix = np.zeros((self.height, self.width, 3), dtype=np.uint8)
scale_factor = 63 * 4 / 255
pix = np.round(img_array * scale_factor).astype(np.uint8)
pix = pix.flatten().tolist()
self.lcd_sendcmd(0x36)
self.lcd_senddata(0x48)
self.lcd_setPos(0, 0, font_width, font_height)
gpio.output(self.pin_dc, gpio.HIGH)
self.lcd_sendnbytes(pix)
def lcd_ShowImage(self, image_path, Xstart, Ystart):
"""Set buffer to value of Python Imaging Library Image_show."""
"""Write display buffer to physical display"""
Image_show = Image.open(image_path)
tmp_width, tmp_height = Image_show.size
if tmp_width > tmp_height:
width_ratio = self.width / tmp_height
height_ratio = self.height / tmp_width
else:
width_ratio = self.width / tmp_width
height_ratio = self.height / tmp_height
scale_ratio = min(width_ratio, height_ratio)
new_width = int(tmp_width * scale_ratio)
new_height = int(tmp_height * scale_ratio)
new_size = (new_width, new_height)
Image_show = Image_show.resize(new_size, 1)
imwidth, imheight = Image_show.size
if Image_show.mode == "RGBA":
Image_show = Image_show.convert("RGB")
if imwidth > imheight:
img_array = np.asarray(Image_show, dtype=np.uint8)
pix = np.zeros((self.width, self.height, 3), dtype=np.uint8)
scale_factor = 63 * 4 / 255
pix = np.round(img_array * scale_factor).astype(np.uint8)
pix = pix.flatten().tolist()
self.lcd_sendcmd(
0x36
)
self.lcd_senddata(0x28)
math_x = imwidth+Ystart
self.lcd_setPos(Ystart, 0, math_x, self.width)
gpio.output(self.pin_dc, gpio.HIGH)
"""modify the original single byte write to multi byte write"""
self.lcd_sendnbytes(pix)
else:
print("same direction")
img_array = np.asarray(Image_show, dtype=np.uint8)
pix = np.zeros((self.height, self.width, 3), dtype=np.uint8)
scale_factor = 63 * 4 / 255
pix = np.round(img_array * scale_factor).astype(np.uint8)
pix = pix.flatten().tolist()
self.lcd_sendcmd(0x36)
self.lcd_senddata(0x48)
self.lcd_setPos(0, Ystart, self.width, self.height)
gpio.output(self.pin_dc, gpio.HIGH)
"""modify the original single byte write to multi byte write"""
self.lcd_sendnbytes(pix)
Image_show.close()