带伺服电机的 Arduino 在 Python 中不响应来自 pySerial 的串行输入
Arduino with servomotors does not respond to serial input from pySerial in Python
我是菜鸟,正在寻求帮助。这是我的问题。我有一个带有两个伺服电机的 Arduino Uno;一个连接到引脚 10,另一个连接到引脚 11。我希望伺服系统根据通过串行端口从 Python on Windows 发送到 Arduino 的指令独立移动。因此,我需要 Arduino 代码和 Python 代码。我在安装了 pySerial 的情况下同时使用了 Python 2.7 和 3.6。到目前为止,我只能在使用 C# 将坐标发送到 Arduino 或从 Arduino 代码本身发送坐标时移动伺服系统。这是代码。我不相信 Arduino 代码或 C# 代码。
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();
}
我知道 Arduino 代码可以工作,因为我可以写入其中的伺服系统并且伺服系统可以正确响应。它还与 C# 一起工作。
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))));
}
}
}
}
此代码从表单获取鼠标输入并将其发送到伺服系统。数据结构是一个字符串,看起来像这样 "X90Y100",其中字母对应舵机,数字是角度。
它正在工作并且舵机正确移动。
这是 Python 代码。就是简单的动一下舵机的测试
import serial
port = serial.Serial("COM3", 9600)
port.write(b"X100Y70")
舵机不动。问题是什么?
任何帮助将不胜感激。
谢谢。
答案在此页上:Arduino and Python
It is worth noting that the example above will not work on a Windows
machine; the Arduino serial device takes some time to load, and when a
serial connection is established it resets the Arduino.
Any write() commands issued before the device initialised will be
lost. A robust server side script will read from the serial port until
the Arduino declares itself ready, and then issue write commands.
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.
我已经测试过了,它可以在添加延迟的情况下工作:
import serial
import time
port = serial.Serial("COM3", 9600)
time.sleep(2)
port.write(b"X100Y70")
您应该考虑更可靠的消息格式。至少,它应该有一个终止符字符(如“\n”)。 Serial.readString();
依靠超时来确定何时收到完整的消息。这可能会导致错误。您可以更改消息格式以使用终止符(或固定大小):
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;
}
}
我是菜鸟,正在寻求帮助。这是我的问题。我有一个带有两个伺服电机的 Arduino Uno;一个连接到引脚 10,另一个连接到引脚 11。我希望伺服系统根据通过串行端口从 Python on Windows 发送到 Arduino 的指令独立移动。因此,我需要 Arduino 代码和 Python 代码。我在安装了 pySerial 的情况下同时使用了 Python 2.7 和 3.6。到目前为止,我只能在使用 C# 将坐标发送到 Arduino 或从 Arduino 代码本身发送坐标时移动伺服系统。这是代码。我不相信 Arduino 代码或 C# 代码。
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();
}
我知道 Arduino 代码可以工作,因为我可以写入其中的伺服系统并且伺服系统可以正确响应。它还与 C# 一起工作。
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))));
}
}
}
}
此代码从表单获取鼠标输入并将其发送到伺服系统。数据结构是一个字符串,看起来像这样 "X90Y100",其中字母对应舵机,数字是角度。
它正在工作并且舵机正确移动。
这是 Python 代码。就是简单的动一下舵机的测试
import serial
port = serial.Serial("COM3", 9600)
port.write(b"X100Y70")
舵机不动。问题是什么? 任何帮助将不胜感激。
谢谢。
答案在此页上:Arduino and Python
It is worth noting that the example above will not work on a Windows machine; the Arduino serial device takes some time to load, and when a serial connection is established it resets the Arduino.
Any write() commands issued before the device initialised will be lost. A robust server side script will read from the serial port until the Arduino declares itself ready, and then issue write commands. 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.
我已经测试过了,它可以在添加延迟的情况下工作:
import serial
import time
port = serial.Serial("COM3", 9600)
time.sleep(2)
port.write(b"X100Y70")
您应该考虑更可靠的消息格式。至少,它应该有一个终止符字符(如“\n”)。 Serial.readString();
依靠超时来确定何时收到完整的消息。这可能会导致错误。您可以更改消息格式以使用终止符(或固定大小):
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;
}
}