树莓派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()
额外说明
- 死区阈值
DEAD_ZONE_MIN和DEAD_ZONE_MAX可以根据你的摇杆实际输出调整,避免轻微晃动就触发按键 - 循环间隔
time.sleep(0.05)可按需调整,值越小响应越快,但CPU占用会增加 - 代码添加了按键状态追踪,实现了按住摇杆时持续触发对应按键、松开后自动释放的效果,更符合实际使用需求
内容的提问来源于stack exchange,提问作者wahhhh
相关产品推荐
相关产品推荐

