交互式进度条
本教程的核心逻辑适用于所有 ESP32 开发板,但所有操作步骤均以 微雪 ESP32-S3-Zero 迷你开发板 为例进行讲解。如果您使用其他型号的开发板,请根据实际情况修改相应设置。
项目介绍
这个项目展示了一个交互式进度条显示系统,通过 ESP32 读取电位器的模拟信号,并在 微雪 1.5 寸 OLED 显示屏上实时显示进度。程序提供了两种显示模式:水平进度条和半圆仪表盘,用户可以通过旋转电位器来观察进度值的变化。
硬件连接
需要使用的器件有:
- 微雪 1.5 寸 OLED 模块 * 1
- 电位器 * 1
- 面包板 * 1
- 导线
- ESP32 开发板
按照下面接线图连接电路:
ESP32-S3-Zero 引脚图

以下用 SPI 接口连接 OLED 显示屏,此屏幕也支持 I2C,通过 BS1 和 BS2 控制,如果使用 I2C 模式,请参考 第7节 I2C 通信 中的接线方式。
| ESP32 引脚 | OLED 模块 | 说明 |
|---|---|---|
| GPIO 13 | SCK | SPI 时钟线 |
| GPIO 11 | MOSI | SPI 数据输出 |
| GPIO 10 | CS | 片选信号 |
| GPIO 8 | DC | 数据/命令选择 |
| 5V | VCC | 电源正极 |
| GND | GND | 电源负极 |

代码实现
此代码示例依赖 ssd1327.py 驱动库。该库基于社区开发者 mcauser 的 micropython-ssd1327 项目。
下载链接:micropython-ssd1327-master.zip
请将该库中的 ssd1327.py 文件上传到开发板的根目录中。
import time
import math
from machine import Pin, SPI, ADC
import ssd1327
# SPI 引脚配置
SCK_PIN = 13
MOSI_PIN = 11
CS_PIN = 10
DC_PIN = 8
RST_PIN = 9
# 电位器引脚
POT_PIN = 7
# 初始化 SPI
spi = SPI(1, baudrate=10000000, sck=Pin(SCK_PIN), mosi=Pin(MOSI_PIN))
# 初始化 OLED
oled = ssd1327.SSD1327_SPI(128, 128, spi, dc=Pin(DC_PIN), res=Pin(RST_PIN), cs=Pin(CS_PIN))
# 若使用 I2C,取消注释以下代码
# from machine import I2C
# SDA_PIN = 2
# SCL_PIN = 1
# I2C_ADDR = 0x3d
# i2c = I2C(0, scl=Pin(SCL_PIN), sda=Pin(SDA_PIN), freq=400000)
# oled = ssd1327.SSD1327_I2C(128, 128, i2c, I2C_ADDR)
# 初始化 ADC
adc = ADC(Pin(POT_PIN))
def get_percentage():
"""读取电位器并返回 0-100 的整数"""
val = adc.read_u16() # 0-65535
percent = int((val / 65535) * 100)
return max(0, min(100, percent))
# 效果函数 1:水平进度条
def show_horizontal_bar(oled, percent):
"""
绘制水平进度条
"""
oled.fill(0) # 清除缓冲区
# 布局参数
bar_x = 10
bar_y = 55
bar_w = 108
bar_h = 18
# 1. 绘制外框 (使用灰色,颜色值 6)
# 注意:使用 framebuf.rect
oled.framebuf.rect(bar_x, bar_y, bar_w, bar_h, 6)
# 2. 绘制内部填充 (使用亮白色,颜色值 15)
# 计算填充宽度,预留 2 像素边距
inner_max_w = bar_w - 4
fill_w = int((percent / 100) * inner_max_w)
if fill_w > 0:
oled.framebuf.fill_rect(bar_x + 2, bar_y + 2, fill_w, bar_h - 4, 15)
# 3. 绘制文字信息
oled.text("Progress", 32, 35, 8) # 标题
p_str = f"{percent}%"
# 简单居中计算:屏幕宽 128,假设字符宽 8
text_x = 64 - (len(p_str) * 4)
oled.text(p_str, text_x, 80, 15) # 数值
oled.show() # 刷新显示
# 效果函数 2:半圆仪表盘
def show_gauge(oled, percent):
"""
绘制半圆仪表盘
"""
oled.fill(0) # 清除缓冲区
# 仪表盘参数
cx, cy = 64, 105 # 圆心位置 (屏幕下方居中)
radius = 55 # 半径
pointer_len = 48 # 指针长度
# 1. 绘制刻度线 (模拟半圆)
# 角度范围:180 度(左) -> 0 度(右)
for i in range(0, 11): # 0 到 10,共 11 个大刻度
angle = 180 - (i * 18)
rad = math.radians(angle)
# 外圈点
x1 = int(cx + math.cos(rad) * radius)
y1 = int(cy - math.sin(rad) * radius)
# 内圈点 (刻度长度 5)
x2 = int(cx + math.cos(rad) * (radius - 6))
y2 = int(cy - math.sin(rad) * (radius - 6))
oled.line(x1, y1, x2, y2, 6) # 颜色 6 (灰色)
# 2. 绘制指针
# 计算当前值的角度
current_angle = 180 - (percent / 100 * 180)
current_rad = math.radians(current_angle)
px = int(cx + math.cos(current_rad) * pointer_len)
py = int(cy - math.sin(current_rad) * pointer_len)
oled.line(cx, cy, px, py, 15) # 颜色 15 (高亮)
# 3. 绘制圆心装饰
oled.framebuf.fill_rect(cx-2, cy-2, 5, 5, 15)
# 4. 底部文字
oled.text(f"{percent}", 56, 110, 15)
oled.text("GAUGE", 44, 10, 8)
oled.show() # 刷新显示
# ================= 主循环 =================
print("Started.")
while True:
# 读取数据
val = get_percentage()
# 选择显示模式 (取消注释你需要的一个)
# 模式 A: 水平进度条
show_horizontal_bar(oled, val)
# 模式 B: 半圆仪表盘
# show_gauge(oled, val)
# 简单的延时防止刷新过快
time.sleep(0.05)
代码解释
-
导入库:
machine库用于控制硬件(SPI、I2C、ADC 和 GPIO),ssd1327库用于驱动 1.5 寸 OLED 显示屏,time库用于实现延时,math库用于绘制仪表盘时的三角函数计算。 -
引脚配置:程序开头定义了 SPI 通信的引脚号和电位器的 ADC 引脚号。将这些参数集中管理,便于后续根据实际需求快速调整。
# SPI 引脚配置
SCK_PIN = 13
MOSI_PIN = 11
CS_PIN = 10
DC_PIN = 8
RST_PIN = 9
# 电位器引脚
POT_PIN = 7 -
硬件初始化:
- SPI 方式(默认):
- 使用
machine.SPI()初始化 SPI 总线,设置波特率为 10MHz。 - 使用
ssd1327.SSD1327_SPI()初始化 OLED,传入分辨率、SPI 对象及控制引脚。
- 使用
- I2C 方式(可选):
- 代码中预留了 I2C 初始化代码(默认注释)。若使用 I2C 接口的屏幕,需取消注释相关代码。
- 使用
machine.I2C()初始化 I2C 总线,并使用ssd1327.SSD1327_I2C()初始化 OLED,需指定 I2C 地址(通常为0x3d)。
- ADC 初始化:使用
machine.ADC()初始化电位器模拟输入。
# 初始化 SPI (默认)
spi = SPI(1, baudrate=10000000, sck=Pin(SCK_PIN), mosi=Pin(MOSI_PIN))
oled = ssd1327.SSD1327_SPI(128, 128, spi, dc=Pin(DC_PIN), res=Pin(RST_PIN), cs=Pin(CS_PIN))
# 初始化 I2C (可选)
# i2c = I2C(0, scl=Pin(SCL_PIN), sda=Pin(SDA_PIN), freq=400000)
# oled = ssd1327.SSD1327_I2C(128, 128, i2c, I2C_ADDR)
# 初始化 ADC
adc = ADC(Pin(POT_PIN)) - SPI 方式(默认):
-
辅助函数
get_percentage():读取电位器的 ADC 值并转换为 0-100 的百分比。- 使用
adc.read_u16()读取 16 位无符号整数(范围 0-65535)。 - 将读取值映射到 0-100 范围,并使用
max()和min()确保结果在有效范围内。
def get_percentage():
"""读取电位器并返回 0-100 的整数"""
val = adc.read_u16() # 0-65535
percent = int((val / 65535) * 100)
return max(0, min(100, percent)) - 使用
-
效果函数 1:
show_horizontal_bar():绘制水平进度条。- 清屏:调用
oled.fill(0)清除显示缓冲区。 - 绘制外框:使用
oled.framebuf.rect()绘制进度条边框,颜色值为 6(灰色)。 - 计算填充宽度:根据百分比计算内部填充条的宽度,预留 2 像素边距以避免与外框重叠。
- 绘制填充:使用
oled.framebuf.fill_rect()绘制填充部分,颜色值为 15(亮白色)。 - 显示文字:在进度条上方显示标题 "Progress",下方显示百分比数值。
- 刷新显示:调用
oled.show()将缓冲区内容发送到屏幕。
- 清屏:调用
-
效果函数 2:
show_gauge():绘制半圆仪表盘。-
清屏:调用
oled.fill(0)清除显示缓冲区。 -
绘制刻度线:通过循环绘制 11 条刻度线(0% 到 100%,每 10% 一条)。使用三角函数计算每条刻度线的起点和终点坐标,角度范围从 180°(左侧)到 0°(右侧)。
for i in range(0, 11): # 0 到 10,共 11 个大刻度
angle = 180 - (i * 18)
rad = math.radians(angle) -
绘制指针:根据百分比计算指针角度,使用
oled.line()绘制从圆心到指针末端的线段,颜色值为 15(高亮)。current_angle = 180 - (percent / 100 * 180)
current_rad = math.radians(current_angle)
px = int(cx + math.cos(current_rad) * pointer_len)
py = int(cy - math.sin(current_rad) * pointer_len)
oled.line(cx, cy, px, py, 15) -
绘制圆心装饰:在圆心位置绘制一个小方块作为视觉焦点。
-
显示文字:在底部显示百分比数值和标题 "GAUGE"。
-
-
主循环逻辑:程序在一个无限循环
while True中执行以下操作:- 读取数据:调用
get_percentage()获取电位器的百分比值。 - 选择显示模式:程序提供两种显示模式(水平进度条和半圆仪表盘),通过注释/取消注释切换。
- 延时控制:使用
time.sleep(0.05)实现 50 毫秒延时,防止刷新过快导致闪烁或资源浪费。
while True:
val = get_percentage()
# 模式 A: 水平进度条
show_horizontal_bar(oled, val)
# 模式 B: 半圆仪表盘
# show_gauge(oled, val)
time.sleep(0.05) - 读取数据:调用