1 项目描述
按照项目要求,本项目实现了一个基于ESP32-S3-BOX-Lite 设备的电子书阅读器功能。使用Wifi连接到了本地服务器,获取到电子书的JSON元素并予以解析,将电子书内容在LCD屏幕上显示出来,并使用ADC完成了按键的上翻、下翻基本控制。本项目使用Python语言,基于CircuitPython对ESP32-S3-BOX-Lite 设备进行编程可以达到基本完成项目目标。
2 整体设计思路
通过对项目需求的分析,计划采用以下的方案完成电子书阅读器项目
2.1 使用ESP32-S3-BOX-Lite 设备内置的ESP32-S3处理器内置的Wifi功能,连接本地AP,并获取本地建立的Web服务器上存储的电子书文件。
2.2 使用ESP32-S3-BOX-Lite 设备的ST7789 LCD屏幕完成电子书的显示功能。本项目使用CircuitPython 作为底层,使用adafruit_ST7789库来完成显示屏部分的驱动。
2.3 使用ESP32-S3-BOX-Lite 设备的GPIO 的ADC 功能,完成了按键检测功能。本项目因为使用了CircuitPython 作为底层,但是CircuitPython未提供ADC 按键的GPIO1 的引出。所以从硬件上将其引出到GPIO9上完成。
3 硬件资源介绍
本设计项目硬件上使用了ESP32-S3-BOX-Lite ,购买于DigiKey 网站。简要介绍硬件资源如下:
ESP32-S3-BOX 搭载 ESP32-S3 AI SoC,在芯片内置的 512 KB SRAM 之外,还集成了 16 MB QSPI flash 和 8 MB Octal PSRAM。它板载一块2.4 寸显示屏(分辨率 320 x 240),双麦克风,一个扬声器和两个用于硬件拓展的 Pmod™ 兼容接口;采用 Type-C USB 连接器,提供 5 V 电源输入和串口/JTAG 调试接口。
图1
4 软件设计
在设计软件之前,需要对整个频率计项目有一个整体的规划。按照功能规划,软件部分需要完成以下功能:ADC按键驱动、LCD屏幕驱动、Wifi联网获取电子书、根据按键定义翻页到上一页或下一页。下面结合项目流程图,分功能对各部分进行详细叙述。
5 程序流程以及代码介绍
5.1 程序流程图分析
通过上面的对于电子书阅读器的功能分析,结合CircuitPython程序框架内,绘制程序流程图如下:
图4
5.2 各部分代码介绍
# ADC按键硬件初始化部分
KeyADC = analogio.AnalogIn(board.G9)
#屏幕初始化
displayio.release_displays()
Backlight = digitalio.DigitalInOut(board.LCD_CTRL)
Backlight.direction = digitalio.Direction.OUTPUT
Backlight.value = False
spi = busio.SPI(board.LCD_SCK,board.LCD_MOSI,board.MISO)
while not spi.try_lock():
pass
spi.configure(baudrate=24000000) # Configure SPI for 24MHz
spi.unlock()
#显示属性初始化
display_bus = displayio.FourWire(spi, command=board.LCD_DC, chip_select=board.LCD_CS, reset=board.LCD_RST)
display = ST7789(display_bus, width=240, height=320, rowstart=0)
font = bitmap_font.load_font("/wenquanyi_13px.pcf")
color = 0xE0E0E0
图五
首先程序初始化之后。使用这些代码完成了ST7789屏幕驱动,初始化了背光控制GPIO. ESP32-S3-BOX在使用了CyrcuitPython作为底层系统之后,可以通过导入board库来直接访问办GPIO。从原理图上面可以看到,背光控制的GPIO 为board.LCD_CTRL 。完成背光点亮之后,对LCD 显示屏使用的SPI端口进行初始化。最后导入了pcf字库文件并且定义其颜色为浅灰。
#网络相关初始化部分
pool = socketpool.SocketPool(wifi.radio)
requests = adafruit_requests.Session(pool, ssl.create_default_context())
TEXT_URL = "http://192.168.80.51/read.html"
wifi.radio.connect("WSTY", "********")
response = requests.get(TEXT_URL)
testpage = response.json()["page{}".format(pagenumber)]
图6
这段代码内,是针对Wifi部分的初始化。其中电子书存储与本地的服务器上面,可以通过修改TEXT_URL的定义来进行修改。使用connect 库完成连接到Wifi。注意需要在参数内传入Wifi的SSID 以及密码。最下面两行,通过调用get 请求,从服务器获取电子书的内容。其中通过testpage ,将response反馈的数据json格式的电子书解析为一页一页的字符串。使用pagenumber 来索引到对应的页面内容。
#读取按键数值,判断后反馈按键键值
def getKey():
raw = KeyADC.value
if raw > 18000 and raw <20000:
return 1
elif raw > 51000 and raw <53000:
return 2
else:
return 0
#绘制一行汉字
def showline(line, text):
text_area = label.Label(font, text=text, color=color)
text_area.x = 20
text_area.y = line * 16 + 50
group.append(text_area)
#绘制一页
def showpage(pagetext):
for i in range(0,numY):
showline(i,pagetext[i * numX : (i+1)* numX])
图7
这部分编写了三个子程序,用来供上层程序调用。第一个为获取按键ADC数值,并且根据数值判断是“上一页”“下一页”还是无按键。后面两个程序为绘制电子书页面的两个子函数。一个为绘制一行汉字,另一个为调用绘制多行,完成整页的绘制。
#进入主循环,0.5秒轮询一次按键,如果是下就调用下一页。上就调用上一页。
while True:
keyvalue = getKey()
if keyvalue != keyhistory:
keyhistory = keyvalue
if keyvalue == 1:
pagenumber = pagenumber+ 1
testpage = response.json()["page{}".format(pagenumber)]
group = displayio.Group()
display.show(group)
showpage(testpage)
elif keyvalue == 2:
pagenumber = pagenumber- 1
testpage = response.json()["page{}".format(pagenumber)]
group = displayio.Group()
display.show(group)
showpage(testpage)
time.sleep(0.2)
图8
此部分使用while建立主循环。不断轮询检测按键是否按下。在检测到向上、向下按键之后,对应的增加或者减少页面编号,并且调用显示子程序进行显示。
6 功能展示与说明
本项目通过连接Wifi,访问服务器内的电子书JSON文件,完成了一个电子书阅读器,详细的按键、翻页、联网等功能演示可以参阅视频文件。
https://www.bilibili.com/video/BV1Su4y127Ee
这里展示几幅图片吧,因为个人喜欢terminal的风格,所以这里使用了黑底白字的风格。
图9
图10
图12
7 对本活动的心得体会
通过完成这个项目,让我对于ESP32-S3的理解更深了一步。在开发过程中最开始是计划使用乐鑫的集成开发环境IDF框架来完成的,遇到的第一个问题是基于Linux的开发设计也并不是很熟悉。因为时间有限,决定使用CircuitPython完成所有的功能模块。遇到的第二个问题是电子书的格式转义的任务,由于很多电子书网站使用了TXT,格式比较大。所以本次项目将电子书文件下载后,转换为JSON格式,再转交MCU进行处理。不过我相信再有一些时间的话,我应该能够更好的设计出一个更完美的电子书阅读器的项目。
针对未来的项目进展,我需要进一步深入的学习IDF的知识,下一步使用IDF来完成更多的任务。
期待下一次能够完成的更好!