You need to enable JavaScript to run this app.
最新活动
大模型
产品
解决方案
定价
生态与合作
支持与服务
开发者
了解我们

Python串口控制Arduino舵机:键盘控制功能实现求助

嘿,我明白你想要实现的功能——用键盘按键按住时让舵机持续朝指定方向转动,松开就立刻停止,这种交互确实比点一下动一下更顺手!我之前也帮朋友解决过类似的问题,给你一套完整可行的方案,分Arduino端(硬件控制逻辑)和Python端(键盘监听+串口通信)两部分来拆解:

一、先搞定Arduino端的基础控制

首先得让Arduino能正确响应串口发来的指令,这里我们约定用+代表舵机顺时针转,-代表逆时针转,每次收到指令就微调角度(比如每次转2度),这样按住按键时Python持续发指令,舵机就会持续转动。

#include <Servo.h>

Servo myServo;
int servoAngle = 90; // 初始角度设为中间值

void setup() {
  myServo.attach(9); // 舵机接数字引脚9
  Serial.begin(9600); // 波特率和Python端保持一致
  myServo.write(servoAngle);
}

void loop() {
  if (Serial.available() > 0) {
    char cmd = Serial.read();
    // 根据指令调整角度,注意限制角度在0-180之间
    if (cmd == '+' && servoAngle < 180) {
      servoAngle += 2;
      myServo.write(servoAngle);
    } else if (cmd == '-' && servoAngle > 0) {
      servoAngle -= 2;
      myServo.write(servoAngle);
    }
  }
}

先把这段代码上传到Arduino,然后打开串口监视器,手动输入+-,确认舵机能正常转动,这一步没问题再往下走。

二、Python端用Pynput实现键盘监听+串口通信

你之前用Pynput没成功,大概率是没处理好「按住按键持续发送指令」的逻辑——我们需要标记按键的按下/释放状态,然后在主循环里根据状态持续发指令。

首先安装需要的库:

pip install pynput pyserial

然后是Python代码:

import serial
from pynput.keyboard import Listener, KeyCode
import time

# 配置串口,根据你的实际端口修改
ser = serial.Serial('COM3', 9600, timeout=1)
time.sleep(2) # 给Arduino启动时间

# 定义控制按键,比如用w顺时针转,s逆时针转
UP_KEY = KeyCode(char='w')
DOWN_KEY = KeyCode(char='s')

# 标记按键状态
up_pressed = False
down_pressed = False

def on_press(key):
    global up_pressed, down_pressed
    if key == UP_KEY:
        up_pressed = True
    elif key == DOWN_KEY:
        down_pressed = True

def on_release(key):
    global up_pressed, down_pressed
    if key == UP_KEY:
        up_pressed = False
    elif key == DOWN_KEY:
        down_pressed = False
    # 按ESC退出程序
    elif key == KeyCode(char='\x1b'):
        return False

# 启动键盘监听线程
listener = Listener(on_press=on_press, on_release=on_release)
listener.start()

# 主循环:根据按键状态持续发送指令
try:
    while listener.is_alive():
        if up_pressed:
            ser.write(b'+') # 发送字节型指令
            time.sleep(0.05) # 控制转动速度,越小转得越快
        elif down_pressed:
            ser.write(b'-')
            time.sleep(0.05)
        time.sleep(0.01)
finally:
    ser.close()
    listener.stop()
三、几个关键注意事项
  • 串口端口号要对应:Windows一般是COMx,Linux/macOS是/dev/ttyUSB0/dev/ttyACM0,你可以在Arduino IDE的「工具」→「端口」里找到
  • 舵机供电要充足:如果舵机扭矩大,别直接用Arduino的5V引脚供电,最好外接电源,不然可能出现转不动或者串口掉线的情况
  • 调整转动速度:代码里的time.sleep(0.05)可以改小一点让舵机转得更快,或者改大一点变慢,根据需求调整
  • 先单独测试:先确保Arduino端能响应串口指令,再跑Python代码,这样容易排查问题

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

火山引擎 最新活动