如何让Python(通过串口)发送的数据等待Arduino完成当前任务?
How to make data sent by Python (via serial connection) wait for Arduino to finish current task?
我尝试让我的 Arduino 微控制器和我的 Mac 一起通话,并创建了一个功能性串行连接。我的电脑正在向我的 Arduino 发送数据,当我的 Arduino 准备好接收新数据时,我的 Arduino 正在发送 '1'
。
我创建了一个 if-else
语句(下面的 Python 脚本),它要么向 Arduino 发送一行新数据,要么等待 Arduino 准备好接收新行数据。
问题是 Python 脚本第一部分中的 ser.read()
总是 returns '1'
,这意味着脚本正在更快地发送各个数据行比 Arduino 连接的步进电机可能做出反应。
在 Arduino 脚本中,您可以看到我在 serialEvent()
函数的第一行发送了状态状态,在我的世界中,这应该让 Arduino 在新的 "task" 来了。但是,由于某种原因它不起作用。有人可以帮我吗?
Python 脚本
import os
import time
import serial
# Name of csv file with drawing coordinates
csvFile = "scaled_coordinates.csv"
# Create serial connection
ser = serial.Serial(port='/dev/tty.usbserial-A9005bDh', baudrate=9600)
wd = os.getcwd()
myFile = open(wd + "/coordinates/" + csvFile)
state = '1'
while True: # Exits when there is no more lines to read
if state == '0': # Wait for Arduino to be ready
state = ser.read()
elif state == '1': # Send one more line to Arduino
line = myFile.readline()
if not line:
break
print line
ser.write(line)
#time.sleep(1)
state = '0' # Wait for Arduino before reading next line
myFile.close
Arduino loop
函数
void loop() {
serialEvent(); // Call the serial function
if (coord_complete) {
// Steps to move from currrent to new point
target1 = steps(x_current, y_current, x_new, y_new, 1);
target2 = steps(x_current, y_current, x_new, y_new, 2);
// Start moving
stepper1.move(target1);
stepper2.move(target2);
// Update current position
x_current = x_new;
y_current = y_new;
// Reset variables
x_complete = false;
y_complete = false;
coord_complete = false;
}
// Stay in while loop until steppermotors is done
while ((stepper1.distanceToGo() != 0) && (stepper2.distanceToGo() != 0)) {
stepper1.run();
stepper2.run();
}
}
Arduino serialEvent
函数
void serialEvent() {
Serial.write('1'); // Tell Python that Arduino is ready for one more line
while (Serial.available() && coord_complete == false) {
char ch = Serial.read(); // Get new character
Serial.print(ch);
// If digit; add it to coord_string
if (isDigit(ch)) {
coord_string[index++] = ch;
// Else if ch is ","; then rename to x_new
} else if (ch == ',') {
coord_string[index++] = NULL; // Finish coord_string
x_new = atoi(coord_string); // Convert to integer
x_complete = true; // Change x_complete to true
index = 0; // Reset index
memset(coord_string, 0, sizeof(coord_string)); // Reset coord_string
// Else if ch is a new line; then rename as y_new
} else if (ch == ';') {
//Serial.write('0');
coord_string[index++] = NULL;
y_new = atoi(coord_string);
y_complete = true;
index = 0;
memset(coord_string, 0, sizeof(coord_string));
}
// Ends while-loop when true
coord_complete = x_complete * y_complete;
}
}
编辑
当前的 Python 代码如下所示:
import os
import time
import serial
# Name of csv file with drawing coordinates
csvGraphic = "Scaled_coordinates.csv"
# Create serial connection
ser = serial.Serial(port='/dev/tty.usbserial-A9005bDh', baudrate=9600)
wd = os.getcwd()
myFile = open(wd + "/graphics/" + csvGraphic)
state = '1'
while True: # Exits when there is no more lines to read
print "state", state
if state == '0': # Wait for Arduino to be ready
state = str(ser.read())
elif state == '1': # Send one more line to Arduino
line = myFile.readline()
if not line:
ser.close()
break
print line
ser.write(line)
state = '0' # Wait for Arduino before reading next line
ser.close()
myFile.close
Python 输出如下所示。代码一次性执行,无需等待 Arduino。 state = str(ser.read())
行似乎读取了某种串行缓冲区中的数据。我猜解决方案是清除缓冲区。我只是不知道如何。
state 1
239,275;
state 0
state 1
1100,275;
state 0
state 1
300,400;
state 0
state 1
200,400;
state 0
state 1
200,300;
state 0
state 1
[Finished in 0.1s]
我想我找到了。您的 SerialEvent()
在 loop
的开头被调用。它做的第一件事是 write('1')
意味着每次执行 loop
时它会告诉您的 python 代码它已准备好接受新指令(即使没有给出指令!)并用 lot 填充缓冲区你一个一个读的'1'
试试这个:
void SerialEvent(){
if((stepper1.distanceToGo() == 0) && (stepper2.distanceToGo() == 0)){
Serial.write('1');
}
//Rest of the function
另外我认为在你的循环结束时你想要
while((stepper1.distanceToGo() != 0) || (stepper2.distanceToGo() != 0))
而不是while((stepper1.distanceToGo() != 0) && (stepper2.distanceToGo() != 0))
感谢 E 先生,我找到了解决方案。基本上我需要在读取或写入之前清除串行缓冲区(flushInput()
和 flushOutput()
in Python 和 flush()
in Arduino)Python 和 Arduino 之间的新数据.此外,Python 和 Arduino 代码中的一个小延迟是必要的,以使其工作。
Pyhton
import os
import time
import serial
# Name of csv file with drawing coordinates
fileName = "coordinates.csv"
# Create serial connection
ser = serial.Serial(port='/dev/tty.usbserial-A9005bDh', baudrate=9600)
wd = os.getcwd()
myFile = open(wd + "/graphics/" + fileName)
#num_lines = sum(1 for line in myFile)
state = '0'
idx = 0
while True: # Exits when there is no more lines to read
#print "state", state
while state == '0': # Wait for Arduino to be ready
ser.flushInput() # Clear input buffer
state = str(ser.read())
if state == '1': # Send one more line to Arduino
line = myFile.readline()
if not line:
break
print "Coordinate", idx
print line
ser.flushOutput() # Clear output buffer
ser.write(line)
time.sleep(0.1)
idx = idx + 1
state = '0' # Set waiting flag – make Arduino wait for next line
ser.close()
myFile.close
Arduino serialEvent
函数
void serialEvent() {
if ((stepper1.distanceToGo() == 0) && (stepper2.distanceToGo() == 0)) {
Serial.write('1'); // Tell Python that Arduino is ready for one more line
delay(10);
Serial.flush(); // clear buffer
}
while (Serial.available() && coord_complete == false) {
char ch = Serial.read(); // Get new character
Serial.flush();
// If digit; add it to coord_string
if (isDigit(ch)) {
coord_string[index++] = ch;
// Else if ch is ","; then rename to x_new
} else if (ch == ',') {
coord_string[index++] = NULL; // Finish coord_string
x_new = atoi(coord_string); // Convert to integer
x_complete = true; // Change x_complete to true
index = 0; // Reset index
memset(coord_string, 0, sizeof(coord_string)); // Reset coord_string
// Else if ch is a new line; then rename as y_new
} else if (ch == ';') {
//Serial.write('0');
coord_string[index++] = NULL;
y_new = atoi(coord_string);
y_complete = true;
index = 0;
memset(coord_string, 0, sizeof(coord_string));
}
// Ends while-loop when true
coord_complete = x_complete * y_complete;
}
}
我尝试让我的 Arduino 微控制器和我的 Mac 一起通话,并创建了一个功能性串行连接。我的电脑正在向我的 Arduino 发送数据,当我的 Arduino 准备好接收新数据时,我的 Arduino 正在发送 '1'
。
我创建了一个 if-else
语句(下面的 Python 脚本),它要么向 Arduino 发送一行新数据,要么等待 Arduino 准备好接收新行数据。
问题是 Python 脚本第一部分中的 ser.read()
总是 returns '1'
,这意味着脚本正在更快地发送各个数据行比 Arduino 连接的步进电机可能做出反应。
在 Arduino 脚本中,您可以看到我在 serialEvent()
函数的第一行发送了状态状态,在我的世界中,这应该让 Arduino 在新的 "task" 来了。但是,由于某种原因它不起作用。有人可以帮我吗?
Python 脚本
import os
import time
import serial
# Name of csv file with drawing coordinates
csvFile = "scaled_coordinates.csv"
# Create serial connection
ser = serial.Serial(port='/dev/tty.usbserial-A9005bDh', baudrate=9600)
wd = os.getcwd()
myFile = open(wd + "/coordinates/" + csvFile)
state = '1'
while True: # Exits when there is no more lines to read
if state == '0': # Wait for Arduino to be ready
state = ser.read()
elif state == '1': # Send one more line to Arduino
line = myFile.readline()
if not line:
break
print line
ser.write(line)
#time.sleep(1)
state = '0' # Wait for Arduino before reading next line
myFile.close
Arduino loop
函数
void loop() {
serialEvent(); // Call the serial function
if (coord_complete) {
// Steps to move from currrent to new point
target1 = steps(x_current, y_current, x_new, y_new, 1);
target2 = steps(x_current, y_current, x_new, y_new, 2);
// Start moving
stepper1.move(target1);
stepper2.move(target2);
// Update current position
x_current = x_new;
y_current = y_new;
// Reset variables
x_complete = false;
y_complete = false;
coord_complete = false;
}
// Stay in while loop until steppermotors is done
while ((stepper1.distanceToGo() != 0) && (stepper2.distanceToGo() != 0)) {
stepper1.run();
stepper2.run();
}
}
Arduino serialEvent
函数
void serialEvent() {
Serial.write('1'); // Tell Python that Arduino is ready for one more line
while (Serial.available() && coord_complete == false) {
char ch = Serial.read(); // Get new character
Serial.print(ch);
// If digit; add it to coord_string
if (isDigit(ch)) {
coord_string[index++] = ch;
// Else if ch is ","; then rename to x_new
} else if (ch == ',') {
coord_string[index++] = NULL; // Finish coord_string
x_new = atoi(coord_string); // Convert to integer
x_complete = true; // Change x_complete to true
index = 0; // Reset index
memset(coord_string, 0, sizeof(coord_string)); // Reset coord_string
// Else if ch is a new line; then rename as y_new
} else if (ch == ';') {
//Serial.write('0');
coord_string[index++] = NULL;
y_new = atoi(coord_string);
y_complete = true;
index = 0;
memset(coord_string, 0, sizeof(coord_string));
}
// Ends while-loop when true
coord_complete = x_complete * y_complete;
}
}
编辑
当前的 Python 代码如下所示:
import os
import time
import serial
# Name of csv file with drawing coordinates
csvGraphic = "Scaled_coordinates.csv"
# Create serial connection
ser = serial.Serial(port='/dev/tty.usbserial-A9005bDh', baudrate=9600)
wd = os.getcwd()
myFile = open(wd + "/graphics/" + csvGraphic)
state = '1'
while True: # Exits when there is no more lines to read
print "state", state
if state == '0': # Wait for Arduino to be ready
state = str(ser.read())
elif state == '1': # Send one more line to Arduino
line = myFile.readline()
if not line:
ser.close()
break
print line
ser.write(line)
state = '0' # Wait for Arduino before reading next line
ser.close()
myFile.close
Python 输出如下所示。代码一次性执行,无需等待 Arduino。 state = str(ser.read())
行似乎读取了某种串行缓冲区中的数据。我猜解决方案是清除缓冲区。我只是不知道如何。
state 1
239,275;
state 0
state 1
1100,275;
state 0
state 1
300,400;
state 0
state 1
200,400;
state 0
state 1
200,300;
state 0
state 1
[Finished in 0.1s]
我想我找到了。您的 SerialEvent()
在 loop
的开头被调用。它做的第一件事是 write('1')
意味着每次执行 loop
时它会告诉您的 python 代码它已准备好接受新指令(即使没有给出指令!)并用 lot 填充缓冲区你一个一个读的'1'
试试这个:
void SerialEvent(){
if((stepper1.distanceToGo() == 0) && (stepper2.distanceToGo() == 0)){
Serial.write('1');
}
//Rest of the function
另外我认为在你的循环结束时你想要
while((stepper1.distanceToGo() != 0) || (stepper2.distanceToGo() != 0))
而不是while((stepper1.distanceToGo() != 0) && (stepper2.distanceToGo() != 0))
感谢 E 先生,我找到了解决方案。基本上我需要在读取或写入之前清除串行缓冲区(flushInput()
和 flushOutput()
in Python 和 flush()
in Arduino)Python 和 Arduino 之间的新数据.此外,Python 和 Arduino 代码中的一个小延迟是必要的,以使其工作。
Pyhton
import os
import time
import serial
# Name of csv file with drawing coordinates
fileName = "coordinates.csv"
# Create serial connection
ser = serial.Serial(port='/dev/tty.usbserial-A9005bDh', baudrate=9600)
wd = os.getcwd()
myFile = open(wd + "/graphics/" + fileName)
#num_lines = sum(1 for line in myFile)
state = '0'
idx = 0
while True: # Exits when there is no more lines to read
#print "state", state
while state == '0': # Wait for Arduino to be ready
ser.flushInput() # Clear input buffer
state = str(ser.read())
if state == '1': # Send one more line to Arduino
line = myFile.readline()
if not line:
break
print "Coordinate", idx
print line
ser.flushOutput() # Clear output buffer
ser.write(line)
time.sleep(0.1)
idx = idx + 1
state = '0' # Set waiting flag – make Arduino wait for next line
ser.close()
myFile.close
Arduino serialEvent
函数
void serialEvent() {
if ((stepper1.distanceToGo() == 0) && (stepper2.distanceToGo() == 0)) {
Serial.write('1'); // Tell Python that Arduino is ready for one more line
delay(10);
Serial.flush(); // clear buffer
}
while (Serial.available() && coord_complete == false) {
char ch = Serial.read(); // Get new character
Serial.flush();
// If digit; add it to coord_string
if (isDigit(ch)) {
coord_string[index++] = ch;
// Else if ch is ","; then rename to x_new
} else if (ch == ',') {
coord_string[index++] = NULL; // Finish coord_string
x_new = atoi(coord_string); // Convert to integer
x_complete = true; // Change x_complete to true
index = 0; // Reset index
memset(coord_string, 0, sizeof(coord_string)); // Reset coord_string
// Else if ch is a new line; then rename as y_new
} else if (ch == ';') {
//Serial.write('0');
coord_string[index++] = NULL;
y_new = atoi(coord_string);
y_complete = true;
index = 0;
memset(coord_string, 0, sizeof(coord_string));
}
// Ends while-loop when true
coord_complete = x_complete * y_complete;
}
}