简体   繁体   English

带有伺服电机的Arduino无法响应Python中pySerial的串行输入

[英]Arduino with servomotors does not respond to serial input from pySerial in Python

I am a noob looking for help. 我是菜鸟,正在寻求帮助。 Here is my problem. 这是我的问题。 I have an Arduino Uno with two servomotors; 我有一个带两个伺服电机的Arduino Uno; one attached to pin 10, the other to pin 11. I want the servos to move independently according to instructions sent through a serial port to the Arduino from Python on Windows. 一个连接到引脚10,另一个连接到引脚11。我希望伺服器根据通过串行端口从Windows上的Python发送到Arduino的指令进行独立移动。 As such I need Arduino code and Python code. 因此,我需要Arduino代码和Python代码。 I have used both Python 2.7 and 3.6 with pySerial installed. 我已经使用了安装了pySerial的Python 2.7和3.6。 So far I have only been able to move the servos when using C# to send the coordinates to the Arduino, or from the Arduino code itself. 到目前为止,我只能在使用C#将坐标发送到Arduino或从Arduino代码本身发送坐标时移动伺服器。 Here is the code. 这是代码。 I do not take credit for the Arduino code or the C# code. 我不相信Arduino代码或C#代码。

Arduino code (Credit to Michael Reeves) Arduino代码(感谢Michael Reeves)

#include<Servo.h>

Servo serX;
Servo serY;

String serialData;

void setup() {
  serX.attach(10);
  serY.attach(11);
  Serial.begin(9600);
  Serial.setTimeout(10);
}

void loop() {
}

void serialEvent() {
  serialData = Serial.readString();
  serX.write(parseDataX(serialData));
  serY.write(parseDataY(serialData));
}

int parseDataX(String data){
  data.remove(data.indexOf("Y"));
  data.remove(data.indexOf("X"), 1);
  return data.toInt();
}

int parseDataY(String data){
  data.remove(0, data.indexOf("Y") + 1);
  return data.toInt();
}

I know that the Arduino code works because I can write to the servos within it and the servos respond correctly. 我知道Arduino代码有效,因为我可以在其中编写伺服器,并且伺服器可以正确响应。 It is also working with C#. 它还与C#一起使用。

C# code (Credit to Michael Reeves): C#代码(提供给Michael Reeves):

using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using System.Windows.Forms;
using System.Diagnostics;

namespace LaserControl {
  public partial class Form1 : Form {
    public Stopwatch watch { get; set; }
    public Form1() {
      InitializeComponent();
    }
    private void Form1_Load(object sender, System.EventArgs e) {
      watch = Stopwatch.StartNew();
      port.Open();
    }
    private void Form1_MouseMove(object sender, MouseEventArgs e) {
      writeToPort(new Point(e.X, e.Y));
    }
    public void writeToPort(Point coordinates) {
      if (watch.ElapsedMilliseconds > 15) {
        watch = Stopwatch.StartNew();
        port.Write(string.Format("X{0}Y{1}", (180 - coordinates.X / (Size.Width / 180)), (coordinates.Y / (Size.Height / 180))));
        System.Diagnostics.Debug.WriteLine(string.Format("X{0}Y{1}", (coordinates.X / (Size.Width / 180)), (coordinates.Y / (Size.Height / 180))));
      }
    }
  }
}

This code takes mouse input from a form and sends it to the servos. 此代码从表单获取鼠标输入,并将其发送到舵机。 The data structure is a string that looks like this "X90Y100", where the letters correspond to servos and the numbers are the angle. 数据结构是一个看起来像“ X90Y100”的字符串,其中字母对应于舵机,数字表示角度。

It is working and the servos move correctly. 它正在工作,并且伺服器正确移动。

Here is the Python code. 这是Python代码。 It is simply a test of moving the servos. 这只是移动伺服器的测试。

import serial
port = serial.Serial("COM3", 9600)
port.write(b"X100Y70")

The servos do not move. 伺服器不移动。 What is the problem? 问题是什么? Any help would be greatly appreciated. 任何帮助将不胜感激。

Thank you. 谢谢。

The answer is on this page: Arduino and Python 答案在此页面上: Arduino和Python

It is worth noting that the example above will not work on a Windows machine; 值得注意的是,以上示例在Windows计算机上不起作用; the Arduino serial device takes some time to load, and when a serial connection is established it resets the Arduino. Arduino串行设备需要花费一些时间来加载,并且在建立串行连接后会重置Arduino。

Any write() commands issued before the device initialised will be lost. 设备初始化之前发出的所有write()命令都将丢失。 A robust server side script will read from the serial port until the Arduino declares itself ready, and then issue write commands. 一个强大的服务器端脚本将从串口读取,直到Arduino声明自己准备就绪,然后发出写命令。 Alternatively It is possible to work around this issue by simply placing a 'time.sleep(2)' call between the serial connection and the write call. 或者,可以通过在串行连接和写调用之间放置一个“ time.sleep(2)”调用来解决此问题。

I've tested it and it works with the delay added: 我已经对其进行了测试,并且可以添加延迟:

import serial
import time

port = serial.Serial("COM3", 9600)
time.sleep(2)
port.write(b"X100Y70")

You should consider a more robust message format. 您应该考虑一种更健壮的消息格式。 At the least, it should have a terminator char (like "\\n"). 至少,它应该有一个终止符char(例如“ \\ n”)。 Serial.readString(); relies on a timeout to determine when a complete message has been received. 依靠超时来确定何时收到完整的消息。 This can cause errors. 这可能会导致错误。 You can change your message format to have a terminator (or a fixed size): 您可以将消息格式更改为具有终止符(或固定大小):

void serialEvent() {
  static String serialData;
  while (Serial.available()) {
    char c = (char)Serial.read();
    if (c == '\n') {
       // Complete message, call a function to handle it
       serX.write(parseDataX(serialData));
       serY.write(parseDataY(serialData));
       // Reset for next message
       serialData = "";
    }
    else {
      // Otherwise keep building the message
      serialData += c;
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM