摇杆模块

原理简介

双轴摇杆模块(常见于 PS2 手柄摇杆)里装了两个电位器和一个按钮。

  • 工作原理:
    • X 轴:一个电位器,左右推动改变电压
    • Y 轴:另一个电位器,上下推动改变电压
    • SW(按下):摇杆中间的按钮,按下导通,是数字量
  • X / Y 是模拟量,接 ADC 读位置;按下是数字量,接普通 GPIO
  • 接口:VRx → ADC,VRy → ADC,SW → 数字输入(带内部上拉)

典型应用

  • 小车方向控制(前后左右)
  • 游戏机/机器人遥控
  • 菜单光标移动
  • 控制电机转速、舵机角度
  • 调参旋钮(音量、亮度)

接线图

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

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

  • 模块 VCC → Pico 3V3
  • 模块 GND → Pico GND
  • 模块 VRx → Pico GP26(ADC0,X 轴)
  • 模块 VRy → Pico GP27(ADC1,Y 轴)
  • 模块 SW → Pico GP14(数字输入,用内部上拉;按下读到 0)

示例代码

基础示例:读取 X/Y 值和按下状态

# ============ 接线 ============
# 摇杆 VCC → Pico 3V3
# 摇杆 GND → Pico GND
# 摇杆 VRx → Pico GP26(ADC0,X 轴)
# 摇杆 VRy → Pico GP27(ADC1,Y 轴)
# 摇杆 SW  → Pico GP14(数字输入,内部上拉;按下读到 0)
# =============================
from machine import ADC, Pin
import time

x = ADC(Pin(26))
y = ADC(Pin(27))
sw = Pin(14, Pin.IN, Pin.PULL_UP)     # 内部上拉,按下读到 0

print('读取摇杆...')

while True:
    xv = x.read_u16()                 # 0 ~ 65535
    yv = y.read_u16()
    pressed = sw.value() == 0         # True 表示被按下
    print('X:', xv, 'Y:', yv, '按下:', pressed)
    time.sleep_ms(200)

进阶示例:校准中点 + 判断方向(带死区)

# ============ 接线 ============
# 摇杆 VCC → Pico 3V3,GND → GND
# VRx → GP26,VRy → GP27,SW → GP14(内部上拉)
# =============================
from machine import ADC, Pin
import time

x = ADC(Pin(26))
y = ADC(Pin(27))
sw = Pin(14, Pin.IN, Pin.PULL_UP)

# 每块模块中位值都不一样,启动时先校准"中点"
print('请松开摇杆,校准中...')
cx = 0
cy = 0
for _ in range(10):                  # 读 10 次求平均作为中点
    cx += x.read_u16()
    cy += y.read_u16()
    time.sleep_ms(20)
cx //= 10
cy //= 10
print('中点 X:', cx, 'Y:', cy)

DEAD = 4000                          # 死区:离中点这么近就算"中间",滤掉抖动
print('开始判断方向...')

while True:
    xv = x.read_u16()
    yv = y.read_u16()

    if xv < cx - DEAD:
        direction = '左'
    elif xv > cx + DEAD:
        direction = '右'
    elif yv < cy - DEAD:
        direction = '上'
    elif yv > cy + DEAD:
        direction = '下'
    else:
        direction = '中间'

    print('方向:', direction, '按下:', sw.value() == 0)
    time.sleep_ms(150)

应用示例:摇杆 X 轴控制 LED 亮度

# ============ 接线 ============
# 摇杆 VCC → Pico 3V3,GND → GND
# VRx → GP26(X 轴,控制亮度),VRy、SW 本示例不接
# LED 正极 → 串联 220Ω 限流电阻 → Pico GP15
# LED 负极 → Pico GND
# =============================
from machine import ADC, Pin, PWM
import time

x = ADC(Pin(26))
led = PWM(Pin(15))                   # GP15 输出 PWM 调亮度
led.freq(1000)

print('推动摇杆 X 轴调节 LED 亮度')

while True:
    xv = x.read_u16()                # 0 ~ 65535
    led.duty_u16(xv)                 # 占空比直接等于 X 值,越往右越亮
    time.sleep_ms(50)

想用摇杆控制舵机:舵机需要外接 5V 供电(Pico 的 3V3 带不动),把舵机信号线接 GPIO、舵机 GND 和 Pico GND 共地,再用 machine.Servo 或 PWM 输出 50Hz 信号。不要从 Pico 的 3V3 给舵机供电。

注意事项

  • 必须校准中点:摇杆中位值不是精确的 32768,每块模块都不一样,程序启动时读几次求平均(见进阶示例)
  • 留死区:靠近中点时读数会抖,用 DEAD 死区避免"中间"误判成方向
  • 不要直接驱动大电流器件:摇杆只是个信号源,接电机/舵机要另加驱动电路和电源
  • 供电:模块接 3V3;若接了舵机,舵机的 5V 要单独供,且必须和 Pico 共地
  • ADC 脚:VRx/VRy 只能接 GP26/27/28(ADC0~2),接错普通 GPIO 读不出模拟值

常见问题

Q: 读出来的 X/Y 值不动,一直是一个固定数? A: 检查 VRx/VRy 有没有接到 GP26/GP27 这些 ADC 脚;再确认 VCC、GND 接好。

Q: 摇杆放在中间,方向却显示"左"或"右"? A: 中位值有偏差,先跑进阶示例的校准,或把 DEAD 死区调大一点。

Q: 能同时控制两个东西吗(比如 X 控亮度、Y 控舵机)? A: 可以,X 和 Y 是独立的 ADC,各自 read_u16() 后分别用即可;舵机记得外接 5V 并共地。