This commit is contained in:
liubiren 2025-11-21 23:30:00 +08:00
parent cfec76ee40
commit 134384051f
4 changed files with 179 additions and 231 deletions

14
RP2350ZERO/main.py Normal file
View File

@ -0,0 +1,14 @@
import utime
from machine import Pin
from utils import MTS102
# 配置引脚
led = Pin(0, Pin.OUT)
toggle_switch = MTS102(1)
while True:
if toggle_switch.switched:
led.on()
else:
led.off()
utime.sleep_ms(200)

165
RP2350ZERO/utils.py Normal file
View File

@ -0,0 +1,165 @@
import utime
from machine import Pin
class MTS102:
"""MTS102三脚二档钮子开关"""
def __init__(self, pin, pull_down=False):
"""
:param pin: 引脚编号
:param pull_down: 引脚下拉电阻断开为低电平接通为高电平默认为False若使用下拉电阻因钮子接通后断开可能存留电荷/漏电故需在引脚和GND并联1K10K欧电阻
"""
if not isinstance(pull_down, bool):
raise TypeError("pull_down数据类型应为布尔")
self.pull_down = pull_down
# 尝试初始化引脚
try:
self.pin = Pin(
pin, Pin.IN, Pin.PULL_DOWN if self.pull_down else Pin.PULL_UP
)
except Exception as exception:
raise RuntimeError(f"初始化引脚发生异常,{str(exception)}") from exception
# 初始化上一次检测时间
self._last_time = utime.ticks_ms()
# 初始化上一次检测状态
self._last_state = self._get_state()
def _get_state(self):
"""获取状态0为断开1为接通"""
return self.pin.value() ^ (not self.pull_down)
def _debounce(self):
"""去抖"""
current_time = utime.ticks_ms()
current_state = self._get_state()
# 若当前与上一次检测间隔大于等于防抖时间则更新时间,又若状态不同则更新状态
if utime.ticks_diff(current_time, self._last_time) >= 20:
if current_state != self._last_state:
self._last_time = current_time
self._last_state = current_state
return self._last_state
@property
def switched(self):
"""是否接通"""
return self._debounce() == 1
class WS2812:
"""WS2812可编程 RGB LED"""
def __init__(self, pin=16, led_beads=1):
"""
:param pin: 引脚编号RP2350ZERO板载WS2812使用引脚16
:param led_beads: LED灯珠数
"""
if not isinstance(led_beads, int):
raise TypeError("led_beads数据类型应为整数")
if not led_beads >= 1:
raise ValueError("led_beads数值应大于等于1")
self.led_beads = led_beads
from neopixel import NeoPixel
# 尝试初始化LED
try:
self.led = NeoPixel(Pin(pin, Pin.OUT), self.led_beads)
except Exception as exception:
raise RuntimeError(f"初始化LED发生异常{str(exception)}") from exception
def set_colors(self, colors):
"""
设置灯珠颜色
:param colors: 包含每颗灯珠RGB的颜色列表
"""
if not isinstance(colors, list):
raise TypeError("colors数据类型应为列表")
if len(colors) != self.led_beads:
raise ValueError("colors列表长度应与LED灯珠数一致")
for bead_idx, bead_color in enumerate(colors):
if not isinstance(bead_color, tuple):
raise TypeError("灯珠颜色数据类型应为元组")
if len(bead_color) != 3:
raise ValueError("灯珠颜色长度应为3")
for channel_idx, channel_value in enumerate(bead_color):
if not isinstance(channel_value, int):
raise TypeError("通道数据数据类型应为整数")
if not 0 <= channel_value <= 255:
raise ValueError("通道数据数值应在0255范围内")
for bead_idx, bead_color in enumerate(colors):
# 将RGB转为GRB并设置灯珠颜色
self.led[bead_idx] = (bead_color[1], bead_color[0], bead_color[2])
# LED刷新
self.led.write()
def iridesce(self, hue_offset=20):
"""通过HSV颜色空间生成渐变炫彩效果
:param hue_offset: 色相偏移角度
"""
if not isinstance(hue_offset, int):
raise TypeError("hue_offset数据类型应为整数")
if not 0 <= hue_offset <= 60:
raise ValueError("hue_offset数值应在060范围内")
# 初始化HSV颜色空间参数其中hue为色相saturation为饱和度value为亮度
hue, saturation, value = 0, 255, 128
while True:
colors = []
for bead_idx in range(self.led_beads):
# 色相
hue = (hue + bead_idx * hue_offset) % 360
# 色域
region = hue // 60
# 色域内相对位置
remainder = (hue - region * 60) * 255 // 60
# 最小分量
P = (value * (255 - saturation)) // 255
# 过渡值
transition = (value * remainder) // 255
# 根据色域将HSV转为RGB并新增至颜色列表
colors.append(
{
0: (value, transition, P), # 由红色渐变为黄色
1: (value - transition, value, P), # 由黄色渐变为绿色
2: (P, value, transition), # 由绿色渐变为青色
3: (P, value - transition, value), # 由青色渐变为蓝色
4: (transition, P, value), # 由蓝色渐变为洋红色
5: (value, P, value - transition), # 由洋红色渐变为红色
}[region]
)
self.set_colors(colors)
# 根据色域动态调整色相步长
hue = hue + [1, 1, 1, 1, 1, 1][region]
utime.sleep_ms(100)
class Servo:
"""舵机(基类)"""
# 运动轨迹
_TRAJECTORIES = {
"linear": lambda x: (x, 1), # 表示当前进度和速度
}

View File

@ -1,97 +0,0 @@
import utime
class WS2812B:
"""RP2350的WS2812B驱动"""
def __init__(self, pin=16):
"""
初始化WS2812B驱动
:param pin: WS2812B的DIN引脚编号RP2350ZERO默认为16
"""
import rp2
from machine import Pin
# 基于RP2350的可编程输入输出PIO生成输入数据信号
@rp2.asm_pio(
sideset_init=rp2.PIO.OUT_LOW, # 初始化侧置引脚为低电平
out_shiftdir=rp2.PIO.SHIFT_LEFT, # 输出移位方向为左移(高位先出)
autopull=True, # 自动从缓存区拉取数据
pull_thresh=24, # 拉取数据阈值
)
def ws2812b():
# 时序参数
T1 = 3 # 比特0或比特1由低电平上升为高电平前的低电平周期数
T2 = 2 # 比特0高电平周期数或比特1前置高电平周期数
T3 = 5 # 比特0由高电平下降为低电平后的低电平周期数或比特1后置高电平周期数
wrap_target()
label("bit_loop")
# 从输出移位寄存器OSR移出一个比特到X寄存器同时将侧置引脚置为低电平延迟T1-1周期数
out(x, 1).side(0)[T1 - 1]
# 判断X寄存器中为比特0同时将侧置引脚置为高电平延迟T2-1周期数。若为比特0则跳转至bit_0否则跳转至bit_loop同时将侧置引脚置为高电平延迟T3-1周期数
jmp(not_x, "bit_0").side(1)[T2 - 1]
jmp("bit_loop").side(1)[T3 - 1]
label("bit_0")
# 无操作同时将侧置引脚置为低电平延迟T3-1周期数
nop().side(0)[T3 - 1]
wrap()
try:
# 初始化状态机
self.state_mechine = rp2.StateMachine(
0, ws2812b, freq=8_000_000, sideset_base=Pin(pin)
)
# 启动状态机
self.state_mechine.active(1)
except Exception as exception:
raise
def send(self, rgb):
"""
发送RGB颜色数据
:param rgb: RGB颜色数据元组
"""
r, g, b = rgb
# 组合RGB颜色数据
rgb = (r << 24) | (g << 16) | (b << 8)
self.state_mechine.put(rgb)
def iridesce(self):
"""炫彩"""
# 色相
H = 0
# 饱和度
S = 255
# 亮度
V = 16
while True:
H = H % 360
# 色域
region = H // 60
# 色域相对位置
remainder = (H - region * 60) * 256 // 60
# 最小颜色分量值
P = (V * (255 - S)) >> 8
# 中间颜色分量值
Q = (V * (255 - ((S * remainder) >> 8))) >> 8
# 最大颜色分量值
T = (V * (255 - ((S * (256 - remainder)) >> 8))) >> 8
state_mechine.send(
{
0: (V, T, P),
1: (Q, V, P),
2: (P, V, T),
3: (P, Q, V),
4: (T, P, V),
}.get(region, (V, P, Q))
)
utime.sleep_ms(20)
H = H + 1

View File

@ -1,134 +0,0 @@
# -*- coding: utf-8 -*-
from machine import Pin, PWM, Timer
import utime
class MorseCodeTransmitter:
"""摩斯码发送器"""
# 摩斯码本
MORSECODEBOOK = {
"A": ".-",
"B": "-...",
"C": "-.-.",
"D": "-..",
"E": ".",
"F": "..-.",
"G": "--.",
"H": "....",
"I": "..",
"J": ".---",
"K": "-.-",
"L": ".-..",
"M": "--",
"N": "-.",
"O": "---",
"P": ".--.",
"Q": "--.-",
"R": ".-.",
"S": "...",
"T": "-",
"U": "..-",
"V": "...-",
"W": ".--",
"X": "-..-",
"Y": "-.--",
"Z": "--..",
"0": "-----",
"1": ".----",
"2": "..---",
"3": "...--",
"4": "....-",
"5": ".....",
"6": "-....",
"7": "--...",
"8": "---..",
"9": "----.",
}
# 合法字符集
CHARACTERSALLOWED = set("ABCDEFGHIJKLMNOPQRSTUVWXYZ 0123456789")
def __init__(self):
# 单位时距(单位为毫秒)
self.unit_time_interval = 120
# 初始化LED
self.LED = Pin("LED", Pin.OUT, value=0)
def emit(self, characters: str) -> bool:
"""发送摩斯码"""
"""
:parma characters: 字符串数据类型为字符
"""
# 检查字符串
if not all(
character.upper() in self.CHARACTERSALLOWED for character in characters
):
print("allowed: a-z, 0-9, space")
return False
# 转为大写
characters = characters.upper()
print(f"emitting {characters} ...", end="")
for character in characters:
# 单词间隔
if character == " ":
utime.sleep_ms(self.unit_time_interval * 7)
continue
for code in self.MORSECODEBOOK.get(character):
# 点亮LED
self.LED.value(1)
if code == ".":
utime.sleep_ms(self.unit_time_interval * 1)
else:
utime.sleep_ms(self.unit_time_interval * 3)
# 熄灭LED
self.LED.value(0)
# 符号间隔
utime.sleep_ms(self.unit_time_interval * 1)
# 字母间隔
utime.sleep_ms(self.unit_time_interval * 3)
print("done")
return True
def __enter__(self):
"""支持上下文管理"""
return self
def __exit__(self, exc_type, exc_val, exc_tb):
"""退出"""
self.LED.off()
if __name__ == "__main__":
with MorseCodeTransmitter() as transmitter:
result = transmitter.emit(characters="hello world")