滚珠开关

原理简介

滚珠开关(也叫倾斜开关、震动开关)是两脚元件,一根小管子里装着一颗钢珠,靠钢珠滚动接通或断开电路。

  • 工作原理:管子倾斜或摇动时,钢珠滚到一端,把管内两个触点接通;钢珠离开,两脚就断开
  • 静止时的状态由摆放角度决定:钢珠停在触点上就一直导通,停在另一头就一直断开
  • 常见型号:SW-520D 之类,两脚不分正负,随便接
  • 接口:GPIO 数字输入,和按键同类——一脚接 GPIO、一脚接 GND,开内部上拉,不需要外接电阻
  • 里面是钢珠不是水银,比老式水银开关安全

典型应用

  • 摇一摇触发(抽签、点名)
  • 倾斜检测(倒了就报警)
  • 震动 / 晃动计数
  • 翻转亮灯、翻页动画

接线图

[接线图占位,后续添加]

文字说明(具体接法见下方代码注释):

  • 滚珠开关一脚 → Pico GP14
  • 滚珠开关另一脚 → Pico GND
  • 用 Pico 内部上拉电阻(Pin.PULL_UP),不需要外接电阻

示例代码

基础示例:倾斜检测(轮询)

先别急着写功能。拿着开关慢慢转一圈,看串口读数在什么姿势下变——每只开关的导通角度都不太一样。

# ============ 接线 ============
# 滚珠开关 一脚 → Pico GP14
# 滚珠开关 另一脚 → Pico GND(内部上拉,无需外接电阻)
# =============================
from machine import Pin
import time

tilt = Pin(14, Pin.IN, Pin.PULL_UP)   # 内部上拉:导通读到 0,断开读到 1

print('慢慢转动手里的开关,看读数的变化')

while True:
    if tilt.value() == 0:             # 导通:钢珠滚到触点上了
        print('导通')
    else:                             # 断开:钢珠停在另一头
        print('断开')
    time.sleep_ms(200)                # 每 200 毫秒看一眼

进阶示例:摇动计数(中断 + 消抖)

摇的时候钢珠会连续碰出很多下。我们要的不是"通不通",而是"摇了几下",所以用一个时间门槛把同一摇的抖动并成一下。

# ============ 接线 ============
# 滚珠开关 一脚 → Pico GP14
# 滚珠开关 另一脚 → Pico GND(内部上拉,无需外接电阻)
# =============================
from machine import Pin
import time

tilt = Pin(14, Pin.IN, Pin.PULL_UP)

SHAKE_GAP = 120          # 消抖门槛(毫秒):两次通断间隔小于它,算同一下抖动
shake = 0                # 计数器:摇了几下
last = 0                 # 上一次有效摇动的时刻

def on_shake(pin):                            # 中断回调:开关一导通就自动跳进来
    global shake, last                        # 要改函数外的变量,必须声明 global
    now = time.ticks_ms()                     # 取当前时刻(毫秒)
    if time.ticks_diff(now, last) > SHAKE_GAP:  # 距上次够久了
        shake += 1                            # 才算新的一下
        print('摇动次数 =', shake)
    last = now                                # 记下这次时刻,供下次比较

tilt.irq(trigger=Pin.IRQ_FALLING, handler=on_shake)   # 导通瞬间(下降沿)触发

while True:
    time.sleep_ms(200)                        # 计数交给中断,主循环歇着

应用示例:倾倒报警

倾斜后持续导通,就当成"倒了"——蜂鸣器响、LED 亮。加一个时长门槛,路过的小震动就不会误报。

# ============ 接线 ============
# 滚珠开关 一脚 → Pico GP14,另一脚 → Pico GND(内部上拉)
# 有源蜂鸣器模块 VCC → 3V3,GND → GND,I/O → GP15
# LED 长脚(正极) → 220Ω 电阻 → GP16,短脚(负极) → GND
# =============================
from machine import Pin
import time

tilt = Pin(14, Pin.IN, Pin.PULL_UP)   # 开关
buzzer = Pin(15, Pin.OUT)             # 蜂鸣器
led = Pin(16, Pin.OUT)                # 报警灯

HOLD_MS = 300                         # 连续导通超过这个时长才算真的倒了

held = 0                              # 已连续导通的时长
print('倾倒报警已启动')

while True:
    if tilt.value() == 0:             # 导通中
        held += 20                    # 累计(下面每次循环等 20 毫秒)
        if held >= HOLD_MS:           # 持续够久了
            buzzer.on()               # 蜂鸣器响
            led.on()                  # 灯亮
    else:                             # 断开:复位
        held = 0
        buzzer.off()
        led.off()
    time.sleep_ms(20)                 # 20 毫秒一轮

注意事项

  • 上拉必须开:Pin(14, Pin.IN, Pin.PULL_UP)。不开上拉,断开时引脚悬空,读数会乱跳
  • 静止状态看角度:管子摆成珠子压住触点的姿势会一直导通,不会自己断开。所以第一件事是拿基础示例测出你这只在什么姿势下导通
  • 摇动是一串通断:钢珠在管里滚一次会碰很多下,直接计数会多算,用进阶示例的 SHAKE_GAP 并成一下
  • 两脚不分正负,但接法固定:一脚必须接 GPIO、另一脚必须接 GND。两脚都接 GPIO 是读不出变化的
  • 型号灵敏度差别大:有的轻轻一碰就通断,有的要倾斜 30° 以上才导通,按手上实物实测
  • 中断里只记数:中断回调里只改计数,别刷屏、别 sleep,显示和判断都留给主循环
  • 别摔:玻璃管的型号摔了会碎,装盒时想办法固定住

常见问题

Q: 读数一直不变? A: 先拿基础示例慢慢转一圈——很可能你现在的姿势正好卡在它固定导通(或固定断开)的角度上。怎么转都不变,就查两脚有没有一脚确实接到了 GND。

Q: 摇一下,计数加了好几下? A: 钢珠滚动本身就是连续通断,属正常现象。把 SHAKE_GAP 从 120 往上调(200 以上),或者改用应用示例那种"持续导通才动作"的判法。

Q: 放着不动它自己也在计数? A: 桌面震动、风吹都会让珠子动。换个稳的地方放,或把 SHAKE_GAP 调大。

Q: 它和按键有什么区别? A: 接口完全一样(数字输入 + 内部上拉),代码结构可以照搬按键。区别在动作方式:按键靠手按,它靠倾斜和摇动,而且一次摇动会产生一串通断,所以要配消抖。