FunPack 2-5 - 基于ESP32-S3-BOX-LITE的网络电子书
项目需求
使用板卡的屏幕和联网功能,实现一个在线电子书浏览器,从网络上获取文本并显示在屏幕上,通过按键翻页。
板卡介绍
ESP32-S3-BOX-Lite 是目前对应的 AIoT 应用开发板,搭载支持 AI 加速的 ESP32-S3 Wi-Fi + Bluetooth 5 (LE) SoC。为用户提供了一个基于语音助手、传感器、红外控制器和智能 Wi-Fi 网关等功能开发和控制智能家居设备的平台。开发板出厂支持离线语音交互功能,用户通过乐鑫丰富的 SDK 和解决方案,能够轻松构建在线和离线语音助手、智能语音设备、HMI 人机交互设备、控制面板、多协议网关等多样的应用。
硬件搭载:
核心微控制器:ESP32-S3
Xtensa® 32 位 LX7 双核处理器,主频高达 240 MHz
内置 512 KB SRAM、384 KB ROM 存储空间,并支持多个外部 SPI、Dual SPI、 Quad SPI、Octal SPI、QPI、OPI flash 和片外 RAM
额外增加用于加速神经网络计算和信号处理等工作的向量指令 (vector instructions)
45 个可编程 GPIO,支持常用外设接口如 SPI、I2S、I2C、PWM、RMT、ADC、UART、SD/MMC 主机控制器和 TWAITM 控制器等
基于 AES-XTS 算法的 Flash 加密和基于 RSA 算法的安全启动,数字签名和 HMAC 模块,“世界控制器 (World Controller)”模块
实现过程
在MicroPython环境下,通过ESP32与ST7789液晶屏显示器结合,实现以下功能:连接到Wi-Fi网络,并在液晶屏上显示连接状态和网络信息。载入字体:使用ufont库和自定义的字体文件,载入需要使用的字体。获取文字:使用HTTP GET请求获取文字数据,并对数据进行处理和显示。在液晶屏上显示文字,收到服务器发送的文字时进行分行在字库中找相应文字,发送给驱动芯片buffer,并进行显示。在main()函数中,循环调用ADC读取函数,实现循环获取ADC按键的电压值,当按下按键时去向网站发出请求获取文字。
在Windows环境下搭建http服务器,服务器代码的主要思路是创建一个简单的HTTP服务器,用于处理客户端的GET请求。服务器的功能包括以下步骤:创建一个HTTP服务器对象,并指定服务器监听的端口号。当接收到客户端的GET请求时,服务器会调用do_GET方法进行处理。在do_GET方法中,服务器会打开相应的文件,并根据文件位置读取字符。服务器将读取的内容封装在一个字典中,包含了一个固定的消息电子书的名字和从文件中读取的数据。将字典转换为JSON字符串,并设置字符编码为UTF-8。服务器通过HTTP响应将JSON数据发送给客户端,确保正确的Content-type和头信息。服务器会更新文件的读取位置,以确保每次请求返回不重复的数据。在服务器接收和处理请求的过程中,会打印相关的请求信息。通过这些步骤,服务器能够持续监听指定端口的GET请求,并将文件中的一部分内容以JSON格式返回给客户端。服务器通过更新文件读取位置,确保每次请求返回的数据不会重复
这样就完成了网络电子书的实现,流程图如下:
现象展示
上电运行代码之后就会屏幕上显示:
等待一会就会打印连接WiFi的状态
向服务器请求到数据之后打印:
按键翻页:
代码讲解
已经将主要的函数进行了注释。
ESP32的Micropython代码如下:
import time
import network
from machine import SPI, Pin, ADC
import ufont
from st7789 import ST7789
from fonts import urequests
import ujson
adc_key = ADC(Pin(1)) # 初始化ADC引脚
spi = SPI(1, 30000000, sck=Pin(7), mosi=Pin(6)) # 初始化SPI接口
display = ST7789(spi=spi, cs=5, dc=4, rst=48, bl=None, width=320, height=240, rotate=2, offset=(0, 0, 320, 240)) # 初始化液晶屏
font = ufont.BMFont("unifont-14-12917-16.v3.bmf") # 初始化字体
def do_connect():
wlan = network.WLAN(network.STA_IF)
wlan.active(True)
if not wlan.isconnected(): # 如果未连接到Wi-Fi
font.text(display, "连接网络中...", 120, 90, show=True) # 显示连接中信息
wlan.connect('taylor', 'asdfghjkl') # 连接指定Wi-Fi网络
while not wlan.isconnected():
pass
font.text(display, "已经连接网络啦", 0, 0, show=True, clear=True, font_size=16) # 显示连接成功信息
font.text(display, "IP:{}".format(wlan.ifconfig()[0]), 0, 32, show=True) # 显示IP地址
font.text(display, "网关:{}".format(wlan.ifconfig()[1]), 0, 64, show=True) # 显示网关地址
font.text(display, "主机:{}".format(wlan.ifconfig()[2]), 0, 96, show=True) # 显示主机地址
time.sleep(3)
def Get_json():
try:
Text = urequests.get("http://192.168.26.41:6080/data") # 发送HTTP请求获取JSON数据
Dic = ujson.loads(Text.text) # 解析JSON数据
shuming = Dic["shuming"]
code = Dic["data"]
# 分割成适当长度的行
lines = [code[i:i+16] for i in range(0, len(code), 16)]
# 在每行之间添加换行符
formatted_code = "\n".join(lines)
font.text(display, shuming, 0, 0, show=True, clear=True) # 显示书名
font.text(display, formatted_code, 10, 32, show=True) # 显示内容
except:
font.text(display, "数据异常!", 24, 24, show=True, clear=True) # 数据异常处理
time.sleep(5)
def main():
do_connect() # 连接Wi-Fi
Get_json() # 获取并显示初始JSON数据
while True:
adc_value = adc_key.read() # 读取ADC值
if adc_value < 4000: # 当ADC值低于4000时触发
Get_json() # 获取并显示新的JSON数据
if __name__ == "__main__":
main()
电脑上位机的http服务器的代码:
from http.server import BaseHTTPRequestHandler, HTTPServer
import json
# 定义 HTTP 请求处理器
class RequestHandler(BaseHTTPRequestHandler):
file_position = 0 # 记录文件读取位置的类变量
def do_GET(self):
self.send_response(200)
self.send_header('Content-type', 'application/json')
self.end_headers()
# 从文件中读取下一段个字符
with open('sanguo.txt', 'r', encoding='utf-8') as file:
file.seek(RequestHandler.file_position)
data = {
'shuming': '三国演义',
'data': file.read(104)
}
RequestHandler.file_position = file.tell() # 更新文件读取位置
# 将数据转换为JSON字符串
json_data = json.dumps(data, ensure_ascii=False)
# 发送JSON数据
self.wfile.write(json_data.encode('utf-8'))
# 打印读取的内容
print("Finish")
def log_message(self, format, *args):
# 打印请求信息
print(f"[{self.address_string()}] {format % args}")
# 运行 HTTP 服务器
def run_server():
server_address = ('', 6080) # 将 6060 替换为服务器监听的端口号
httpd = HTTPServer(server_address, RequestHandler)
print('Server is running on port', 6080)
httpd.serve_forever()
run_server()
心得体会
通过完成ESP32-S3-Box-Lite电子书阅读器项目,我学会了使用MicroPython编程语言和相应的库,实现网络连接、液晶屏显示和错误处理。这个项目提高了我的嵌入式开发技能,增强了我在处理硬件和网络交互方面的能力。我也意识到持续学习和实践的重要性,它们是解决问题和提升自己的关键。