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

Arduino摇杆驱动Pygame圆形对象移动问题排查

问题概述

需求:通过Arduino输出的摇杆坐标控制Pygame中的圆形对象,测试X轴值达到1023时使圆形右移。
遇到两个问题:

  1. 运行main.py后仅打印几次Arduino摇杆坐标就停止,需按键才恢复;
  2. 摇杆X轴值为1023时,圆形未右移。

具体疑问:

  1. 为何X轴值为1023时圆形不移动(按键时会打印ballpos[0]且短暂继续循环,此时X轴数据为1023)?
  2. 如何在Pygame事件循环中持续读取Arduino摇杆数据?

附Arduino代码(JSPy.ino)

//input pins

//analog
int JSx = A0;
int JSy = A1;

//digital
int JSpin = 9;

//read JS position values
int JSxVal;
int JSyVal;
int JSVal;

// delay(ms)
int dt = 500;

void setup() {
    // put your setup code here, to run once:

    pinMode(JSx,INPUT);
    pinMode(JSy,INPUT);
    digitalWrite(JSpin,HIGH);
    Serial.begin(9600);
    
}
void loop() {
    // put your main code here, to run repeatedly:

    JSxVal = analogRead(JSx);
    JSyVal = analogRead(JSy);
    JSVal = digitalRead(JSpin);
    
    delay(dt);

    //JSx coor
    Serial.print(JSxVal);
    Serial.print(" ");

    //JSy coor
    Serial.println(JSyVal); 
}

附Python代码(main.py)

import serial
import time 
import pygame as pg

# default port is 9600 baud rate so didnt have to set
arduinoData = serial.Serial("com3")
time.sleep(1)


# pygame settings

#screen
bgSize =screenW,screenH = 500,600
screen = pg.display.set_mode((bgSize))


ballx,bally = 250,300
ballPos=(ballx,bally)

GRAY = (112,112,112)
BLUE = (0,0,255)



run =True

while run:

    for event in pg.event.get():
        while(arduinoData.inWaiting()==0):
            pass
        dataPacket = arduinoData.readline()
        # convert from binary to string
        dataPacket = dataPacket.decode(encoding='utf-8')
        
            # make list of string numbers of coordinates
        dataPacket = dataPacket.split()
        # turn coordinates into int in the list
        dataPacket = [eval(i) for i in dataPacket]

        
        if event.type == pg.QUIT:
            run=False
        if event.type == pg.KEYDOWN:
            if event.key == pg.K_ESCAPE:
                run= False
            if dataPacket[0] == 1023:
                ballx+=1
                print(f"x pos = {ballPos[0]}")

        screen.fill(BLUE)
        print(f" JS - x - {dataPacket[0]}")
        pg.draw.circle(screen, GRAY,ballPos,15,4)
        pg.display.update()

问题解答

疑问1:X轴值1023时圆形不移动的原因

  1. 你把摇杆数据的判断逻辑放在了pg.KEYDOWN事件分支内,只有触发按键事件时才会检查X轴数值,即便摇杆X轴到1023,无按键操作这段代码就不会执行。
  2. ballPos是元组(不可变类型),你修改了ballx但没有更新ballPos,绘制时始终用初始坐标,所以圆形位置不会变化。

疑问2:如何持续读取Arduino摇杆数据

当前代码把串口读取逻辑放在Pygame事件循环内部,只有有事件触发时才会读取一次数据;且while(arduinoData.inWaiting()==0): pass是阻塞式等待,会让程序卡在等待串口数据的状态,只有事件(比如按键)触发才能继续。正确做法是把串口读取放在主循环顶层,与事件循环并行,同时改用非阻塞式判断。


修正后的代码

Arduino代码(无需修改)

保留原代码即可。

修正后的Python代码(main.py)

import serial
import time 
import pygame as pg

# 明确指定串口波特率,避免参数不匹配
arduinoData = serial.Serial("com3", 9600)
time.sleep(1)

# pygame初始化
pg.init()

# screen设置
bgSize = screenW, screenH = 500, 600
screen = pg.display.set_mode(bgSize)

# 用列表存储圆形位置,方便修改
ballPos = [250, 300]

GRAY = (112,112,112)
BLUE = (0,0,255)

run = True

while run:
    # 处理Pygame事件
    for event in pg.event.get():
        if event.type == pg.QUIT:
            run = False
        if event.type == pg.KEYDOWN:
            if event.key == pg.K_ESCAPE:
                run = False

    # 非阻塞式读取串口数据
    if arduinoData.inWaiting() > 0:
        try:
            # 读取并处理串口数据
            dataPacket = arduinoData.readline().decode('utf-8').strip()
            dataPacket = dataPacket.split()
            if len(dataPacket) == 2:
                js_x = int(dataPacket[0])
                print(f"JS - x - {js_x}")
                # 检测X轴值并移动圆形
                if js_x == 1023:
                    ballPos[0] += 1
                    print(f"x pos = {ballPos[0]}")
        except:
            # 处理数据解析错误,避免程序崩溃
            pass

    # 绘制画面
    screen.fill(BLUE)
    pg.draw.circle(screen, GRAY, ballPos, 15, 4)
    pg.display.update()

# 程序结束后清理资源
arduinoData.close()
pg.quit()

关键修改点

  • 将串口读取逻辑移到主循环顶层,脱离事件循环,实现持续读取
  • 用if arduinoData.inWaiting() > 0替代阻塞式while循环,避免程序卡顿
  • 把ballPos从元组改为列表,修改后直接生效
  • 将摇杆X轴的判断逻辑移到串口数据读取分支,不再依赖按键事件
  • 添加异常处理,避免串口数据解析错误导致程序崩溃
  • 明确指定串口波特率,消除潜在参数不匹配问题

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.09 16:25:22