跳到主要内容

交互式进度条

重要提示:关于开发板的兼容性

本教程的核心逻辑适用于所有 ESP32 开发板,但所有操作步骤均以 微雪 ESP32-S3-Zero 迷你开发板 为例进行讲解。如果您使用其他型号的开发板,请根据实际情况修改相应设置。

项目介绍

这个项目展示了一个交互式进度条显示系统,通过 ESP32 读取电位器的模拟信号,并在 微雪 1.5 寸 OLED 显示屏上实时显示进度。程序提供了两种显示模式:水平进度条和半圆仪表盘,用户可以通过旋转电位器来观察进度值的变化。

硬件连接

需要使用的器件有:

按照下面接线图连接电路:

ESP32-S3-Zero 引脚图

ESP32-S3-Zero-Pinout

提示

以下用 SPI 接口连接 OLED 显示屏,此屏幕也支持 I2C,通过 BS1 和 BS2 控制,如果使用 I2C 模式,请参考 第7节 I2C 通信 中的接线方式。

ESP32 引脚OLED 模块说明
GPIO 13SCKSPI 时钟线
GPIO 11MOSISPI 数据输出
GPIO 10CS片选信号
GPIO 8DC数据/命令选择
5VVCC电源正极
GNDGND电源负极
接线图

代码实现

提示

此代码示例依赖 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))
  • 辅助函数 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)

参考链接