From 134384051fdd68b44620875d6352d864752bd1c6 Mon Sep 17 00:00:00 2001 From: liubiren Date: Fri, 21 Nov 2025 23:30:00 +0800 Subject: [PATCH] 251121 --- RP2350ZERO/main.py | 14 ++++ RP2350ZERO/utils.py | 165 ++++++++++++++++++++++++++++++++++++++++++++ WS2812/main.py | 97 -------------------------- 发送摩斯码/main.py | 134 ----------------------------------- 4 files changed, 179 insertions(+), 231 deletions(-) create mode 100644 RP2350ZERO/main.py create mode 100644 RP2350ZERO/utils.py delete mode 100644 WS2812/main.py delete mode 100644 发送摩斯码/main.py diff --git a/RP2350ZERO/main.py b/RP2350ZERO/main.py new file mode 100644 index 0000000..57f2b5d --- /dev/null +++ b/RP2350ZERO/main.py @@ -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) \ No newline at end of file diff --git a/RP2350ZERO/utils.py b/RP2350ZERO/utils.py new file mode 100644 index 0000000..88adbe9 --- /dev/null +++ b/RP2350ZERO/utils.py @@ -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并联1K~10K欧电阻 + """ + 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("通道数据数值应在0~255范围内") + + 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数值应在0~60范围内") + + # 初始化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), # 表示当前进度和速度 + } diff --git a/WS2812/main.py b/WS2812/main.py deleted file mode 100644 index a3e3c7b..0000000 --- a/WS2812/main.py +++ /dev/null @@ -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 diff --git a/发送摩斯码/main.py b/发送摩斯码/main.py deleted file mode 100644 index 3ae9374..0000000 --- a/发送摩斯码/main.py +++ /dev/null @@ -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")