You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

树莓派3B模拟摇杆映射WASD报错AttributeError: S求助

问题解决:树莓派摇杆映射WASD按键报错修复

错误原因

AttributeError: S 是因为误用了pynput.keyboard.Key枚举类——这个类仅用于特殊按键(如Key.enter、Key.space),普通字母按键不需要通过Key调用,直接传入对应的字符串即可(比如'w'、's')。

代码修复要点

除了按键调用的问题,原代码还有两处关键调整点:

  • time.sleep(0.2) 缩进错误,它必须放在while True循环内部,否则程序会直接卡死在sleep步骤
  • 原逻辑是每次循环都点按一次按键,无法实现按住摇杆持续触发按键的效果,需要添加状态变量追踪按键是否已按下

修复后的完整代码

#!/usr/bin/env python3

import RPi.GPIO as GPIO
import ADC0834
import time
from pynput.keyboard import Controller

BtnPin = 22
# 初始化按键状态,避免重复触发
key_states = {'w': False, 's': False, 'a': False, 'd': False}
# 摇杆死区阈值(可根据实际硬件调整)
DEAD_ZONE_MIN = 100
DEAD_ZONE_MAX = 155

def setup():
    GPIO.setmode(GPIO.BCM)
    GPIO.setup(BtnPin, GPIO.IN, pull_up_down=GPIO.PUD_UP)
    ADC0834.setup()

def destroy():
    keyboard = Controller()
    # 程序结束时释放所有可能按住的按键
    for key in key_states:
        if key_states[key]:
            keyboard.release(key)
    GPIO.cleanup()

def loop():
    keyboard = Controller()
    while True:
        x_val = ADC0834.getResult(0)
        y_val = ADC0834.getResult(1)
        Btn_val = GPIO.input(BtnPin)

        # 处理Y轴(上下)
        if y_val < DEAD_ZONE_MIN:
            if not key_states['w']:
                keyboard.press('w')
                key_states['w'] = True
            # 释放相反方向按键
            if key_states['s']:
                keyboard.release('s')
                key_states['s'] = False
        elif y_val > DEAD_ZONE_MAX:
            if not key_states['s']:
                keyboard.press('s')
                key_states['s'] = True
            if key_states['w']:
                keyboard.release('w')
                key_states['w'] = False
        else:
            # 回到死区,释放上下按键
            if key_states['w']:
                keyboard.release('w')
                key_states['w'] = False
            if key_states['s']:
                keyboard.release('s')
                key_states['s'] = False

        # 处理X轴(左右)
        if x_val < DEAD_ZONE_MIN:
            if not key_states['a']:
                keyboard.press('a')
                key_states['a'] = True
            if key_states['d']:
                keyboard.release('d')
                key_states['d'] = False
        elif x_val > DEAD_ZONE_MAX:
            if not key_states['d']:
                keyboard.press('d')
                key_states['d'] = True
            if key_states['a']:
                keyboard.release('a')
                key_states['a'] = False
        else:
            # 回到死区,释放左右按键
            if key_states['a']:
                keyboard.release('a')
                key_states['a'] = False
            if key_states['d']:
                keyboard.release('d')
                key_states['d'] = False

        # 处理摇杆按键(可选,可自定义逻辑)
        if Btn_val == 0:
            pass

        time.sleep(0.05)  # 调整循环间隔,平衡响应速度和资源占用

if __name__ == '__main__':
    setup()
    try:
        loop()
    except KeyboardInterrupt:
        destroy()

额外说明

  1. 死区阈值DEAD_ZONE_MIN和DEAD_ZONE_MAX可以根据你的摇杆实际输出调整,避免轻微晃动就触发按键
  2. 循环间隔time.sleep(0.05)可按需调整,值越小响应越快,但CPU占用会增加
  3. 代码添加了按键状态追踪,实现了按住摇杆时持续触发对应按键、松开后自动释放的效果,更符合实际使用需求

内容的提问来源于stack exchange,提问作者wahhhh

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.26 02:07:23