ESP32 OTA升级功能的MirPython开发指南
系列文章目录
mircopython 开发ESP32
提示:写完文章后,目录可以自动生成,如何生成可参考右边的帮助文档
前言
一、mircopython开发ESP32需要哪些工具?
二、使用Tonny烧录固件
总结
前言
ESP32提供了mircopython固件库,用python语言开发项目功能,缩短开发周期,并且上手简单。本文章主要介绍用mircopython开发遇到的的一些问题,分享一些经验,希望大家能多多交流
提示:以下是本篇文章正文内容,下面案例可供参考
一、mircopython开发ESP32需要哪些工具?
1、软件:Tonny(新手适用),链接:Thonny, Python IDE for beginners

2、mircopython固件:MicroPython – Python for microcontrollers,注意选择合适的固件版本,python版本管控是一个重要的知识点

3、esp32开发板:这里选择自己需要的就好,我选用的是esp32-wroom-32
二、使用Tonny烧录固件








三、OTA升级功能思路
先对要更新的.py进行打包压缩,将打包压缩的.py放在服务器指定目录下,由设备主动获取,设备获取到固件压缩包之后,在本地解压。主要有验证:md5或者crc,这里我使用的是md5。

流程图
1、打包压缩工具:
压缩包的数据结构:

这样设计的数据结构的原因:由于esp32的内存资源有限,我们需要分段式的读取每个文件压缩包,避免内存溢出,以时间换取空间方式解决内存紧张问题。
代码如下(示例):
import zlib
import os
def compress_folder(folder_path):
# 初始化一个空列表来存储文件名、压缩后数据大小和压缩后数据
compressed_files_info = []
# 获取指定文件夹下的所有文件名
file_list = os.listdir(folder_path)
for file_name in file_list:
# 检查是否为普通文件
full_path = os.path.join(folder_path, file_name)
if os.path.isfile(full_path):
# 打开当前文件,并读取文件内容
with open(full_path, 'rb') as file:
file_data = file.read()
# 压缩文件内容
compressed_data = zlib.compress(file_data)
# 获取压缩后数据大小
compressed_size = len(compressed_data)
# 将文件名、压缩后数据大小和压缩后数据添加到列表中
compressed_files_info.append((file_name, compressed_size, compressed_data))
return compressed_files_info
def create_flash_image(compressed_files_info):
# 定义分隔符和包尾数据
separator1 = '|'
separator2 = ':'
separator3 = ';'
package_tail = b'END' # 包尾数据
# 创建一个字节数组来存储信息段
info_segment = bytearray()
# 将每个文件的信息构造为子信息段
for file_info in compressed_files_info:
file_name, compressed_size, compressed_data = file_info
# 创建子信息段
sub_info_segment = f"{file_name}{separator1}{compressed_size}{separator2}{separator3}"
info_segment.extend(sub_info_segment.encode('utf-8'))
# 确保信息段不超过1KB
if len(info_segment) > 1024:
raise ValueError("信息段超过1KB限制")
# 填充信息段到1KB
info_segment.extend(b'\x00' * (1024 - len(info_segment)))
# 将信息段和压缩数据组合在一起,每个压缩数据后面加上包尾数据
final_data = info_segment
for _, _, data in compressed_files_info:
final_data += data + package_tail
return final_data
if __name__ == '__main__':
folder_path = './python'
compressed_files_info = compress_folder(folder_path)
# 创建最终的 Flash 映像数据
final_data = create_flash_image(compressed_files_info)
# 将数据写入到输出文件
output_file = 'PR_APP_V04.zlib'
with open(output_file, 'wb') as f:
f.write(final_data)
# 输出有几个文件被压缩了
num_compressed_files = len(compressed_files_info)
print(f"总共有 {num_compressed_files} 个文件被压缩。")
# 打印每个被压缩存储的文件的信息
print("以下文件已成功压缩并存储到 Flash(output_flash.bin):")
for file_info in compressed_files_info:
print(f"文件名: {file_info[0]}, 压缩后大小: {file_info[1]} bytes")
# 输出最后压缩包的名字和大小
compressed_package_size = os.path.getsize(output_file)
print(f"压缩包的名字为: {output_file}, 大小为: {compressed_package_size} bytes")
注意:要压缩的.py文件需要存放在当前./python目录下,生成的压缩包output_flash.bin会直接放在当前目录./下。
2、解压工具
import zlib
import os
def extract_flash_image(input_file_path, output_folder):
# 确保输出文件夹存在
if not os.path.exists(output_folder):
os.makedirs(output_folder)
# 定义分隔符
separator1 = '|'
separator2 = ':'
separator3 = ';'
package_tail = b'END'
# 读取信息段(前 1024 字节)
with open(input_file_path, 'rb') as f:
info_segment = f.read(1024).rstrip(b'\x00').decode('utf-8')
# 解析信息段
file_infos = info_segment.split(separator3)[:-1] # 最后一个是空字符串,去掉
# 处理每个文件
with open(input_file_path, 'rb') as f:
f.seek(1024) # 移动到数据起始位置
for file_info in file_infos:
file_name, compressed_size_str = file_info.split(separator1)
compressed_size = int(compressed_size_str.split(separator2)[0])
# 分块读取压缩数据
compressed_data = bytearray()
bytes_read = 0
while bytes_read < compressed_size:
chunk = f.read(min(compressed_size - bytes_read, 1024))
if not chunk:
break
compressed_data.extend(chunk)
bytes_read += len(chunk)
# 跳过包尾数据
f.read(len(package_tail))
# 解压缩数据
decompressed_data = zlib.decompress(compressed_data)
# 写入解压后的文件
output_file_path = os.path.join(output_folder, file_name)
with open(output_file_path, 'wb') as out_file:
out_file.write(decompressed_data)
print("文件解压完成,已保存到:", output_folder)
if __name__ == '__main__':
input_file = 'PR_APP_V03.zlib'
output_folder = './extracted_files'#这里要改成.,直接是当前目录即可。
extract_flash_image(input_file, output_folder)
四、用ampy+uzlib向Esp32内“烧录固件”
由于使用tonny,想要将文件烧录到esp32中,只能通过新建文件方式。但是对于有多个.py文件,如果我们要给多块板子烧录多个.py文件,通过给每个板子新建文件方式,会很繁琐。
所以我们可以先将要烧录的.py文件打包压缩成xxx.uzlib文件,通过ampy工具传输到esp32里,然后把解压程序decompress.py也放入esp32里,通过ampy 去执行decompress.py将xxx.uzlib文件解压,多个.py就可以放入到esp32里面了,就不需要频创建新文件了。

解压后的文件就可以看见了

总结
这里讲的是esp32的ota升级和烧录,希望对大家有所帮助,大家有好多建议希望能多多分享!!!
作者:苏狗子