251121
This commit is contained in:
parent
cfec76ee40
commit
134384051f
|
|
@ -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)
|
||||||
|
|
@ -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), # 表示当前进度和速度
|
||||||
|
}
|
||||||
|
|
@ -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
|
|
||||||
134
发送摩斯码/main.py
134
发送摩斯码/main.py
|
|
@ -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")
|
|
||||||
Loading…
Reference in New Issue