一次串行通信-Python脚本和Arduino之间的多次读写
我想在Python守护进程和Arduino之间建立一个串行通信。 首先,Python守护进程设置一个串行连接,该连接将持续守护进程的整个生命周期。通过这个连接,我希望每次Python守护进程接收命令时,都向Arduino发送数据并在一次串行通信-Python脚本和Arduino之间的多次读写,python,serial-port,arduino,Python,Serial Port,Arduino,我想在Python守护进程和Arduino之间建立一个串行通信。 首先,Python守护进程设置一个串行连接,该连接将持续守护进程的整个生命周期。通过这个连接,我希望每次Python守护进程接收命令时,都向Arduino发送数据并在acks变量中接收回数据 问题是,虽然第一次通信进展顺利,但之后没有通过串行通信发送任何信息。如果我为每个请求建立一个新的连接,它会工作,但它会使程序非常慢,这是我想要避免的。 编辑:真正的问题是何时将正确的字符串发送到arduio evrything运行正常,但当我
acks
变量中接收回数据
问题是,虽然第一次通信进展顺利,但之后没有通过串行通信发送任何信息。如果我为每个请求建立一个新的连接,它会工作,但它会使程序非常慢,这是我想要避免的。
编辑:真正的问题是何时将正确的字符串发送到arduio evrything运行正常,但当我发送错误的字符串时,串行端口块将无法再次重新确认正确的字符串(问题在于arduino代码)
Python代码:
import serial
import time
import sys
from socket import *
import threading
import thread
def handler(clientsock,addr):
while 1:
#arduino.flush()
data = clientsock.recv(BUFSIZ)
if not data:
break
print data
print data
#time.sleep(3)
arduino.write(data)
#time.sleep(3)
ack = arduino.readline(1)
arduino.flush()
clientsock.send(ack+"\n")
clientsock.close()
if __name__=='__main__':
HOST = '0.0.0.0'
PORT = 21567
BUFSIZ = 1024
ADDR = (HOST, PORT)
arduino = serial.Serial('/dev/ttyACM0',9600,timeout=6)
serversock = socket(AF_INET, SOCK_STREAM)
serversock.bind(ADDR)
serversock.listen(2)
while 1:
print 'waiting for connection...'
clientsock, addr = serversock.accept()
print '...connected from:', addr
thread.start_new_thread(handler, (clientsock, addr))
Arduino代码:
int relayPinCH1 = 7; // pin de commande du relais 1
char inData[20]; // Allocate some space for the string
char inChar=-1; // Where to store the character read
byte index = 0; // Index into array; where to store the character
void setup()
{
pinMode(relayPinCH1, OUTPUT);
Serial.begin(9600);
}
char Comp(char* This) {
while (Serial.available() > 0) // Don't read unless
// there you know there is data
{
if(index < 19) // One less than the size of the array
{
inChar = Serial.read(); // Read a character
inData[index] = inChar; // Store it
index++; // Increment where to write next
inData[index] = '\0'; // Null terminate the string
}
}
Serial.flush();
if (strcmp(inData,This) == 0) {
for (int i=0;i<19;i++) {
inData[i]=0;
}
index=0;
return(0);
}
else {
return(1);
}
}
void loop()
{
//Serial.println("Hello Pi");
if (Comp("l11\n")==0)
{
Serial.flush();
digitalWrite(relayPinCH1, HIGH);
Serial.println("y");
}
if (Comp("l10\n")==0)
{
Serial.flush();
digitalWrite(relayPinCH1, LOW);
Serial.println("n");
}
delay(1000);
}
int relayPinCH1=7;//雷莱斯司令部1号
char inData[20];//为字符串分配一些空间
字符英寸=-1;//在何处存储读取的字符
字节索引=0;//索引到数组中;在哪里存储字符
无效设置()
{
pinMode(relayPinCH1,输出);
Serial.begin(9600);
}
char Comp(char*This){
while(Serial.available()>0)//除非
//你知道有数据
{
if(index<19)//比数组的大小小一个
{
inChar=Serial.read();//读取字符
inData[index]=inChar;//存储它
index++;//递增下一步写入的位置
inData[index]='\0';//Null终止字符串
}
}
Serial.flush();
if(strcmp(inData,This)==0){
对于(int i=0;i在您的Arduino代码中,您的逻辑有点古怪-因此,我不确定,但是您是否在再次启动循环之前将索引清除为0?看起来一旦索引==19,它可能会重置为0,也可能不会重置为0,这取决于以后的逻辑。如果您输入Comp()第二次,索引>=19,你就再也看不到串行端口了。我认为@Zeus完全正确(因此我对这个答案投了更高的票),但还有其他问题。要重申@Zeus所说的话:
- 如果比较成功,
index
仅重置为0
。因此缓冲区已满,您要查找的字符串不在那里,index
再也不会返回到0
- 一旦
index
达到19
,就不再进行读取。因此,inData
中的任何内容都会停留在inData
中,并且所有未来的比较都将失败,这意味着index
将永远不会重置为0
代码中还有许多其他问题,但主要问题是设计非常脆弱,并且容易出现与您所遇到的错误类型完全相同的错误。例如,如果您的Python脚本发送的换行符是换行符的CR+LF,但您只期望CR,那么您将遇到与现在相同的失败类型:第一次co通信是有效的,但再也不能起作用了
我建议您按照以下方式重新组织代码:
/* Read serial characters, if available and store them in strCommand
until we get a newline
Returns 0 if no command is available */
int readSerialCommand() {
idxCommandChar = 0;
while (Serial.available()) {
int in = Serial.read();
while (in!='\n') {
strCommand[idxCommandChar++] = in;
in = Serial.read();
}
strCommand[idxCommandChar++] = '\0';
return idxCommandChar;
}
return 0;
}
// Get command from serial (if available), and process it.
void processCommand() {
if (readSerialCommand()) {
....
- 用于读取串行端口的函数从串行端口读取一条线路,并将其返回给调用者(不带换行符),而不管通信内容如何
- 调用方将从串行端口接收的行与已知命令列表进行比较,并相应地执行这些命令
这可能看起来很糟糕,如下所示
char strCommand[0xFF];
int idxCommandChar;
// Read a command from serial, returning the command size
// This function BLOCKS, i.e., doesn't return until a command is available
int readSerialCommand() {
// We reset the index to zero on every read: the command is overwritten every time
idxCommandChar = 0;
// Read serial characters and store them in strCommand
// until we get a newline
int in = Serial.read();
while (in!='\n') {
strCommand[idxCommandChar++] = in;
in = Serial.read();
}
// Add the string terminator
strCommand[idxCommandChar++] = '\0';
// Return command size
return idxCommandChar;
}
// Get command from serial, and process it.
void processCommand() {
readSerialCommand();
if (strcmp(strCommand, "CMD1")==0) {
// do something
} else if (strcmp(strCommand, "CMD2")==0) {
// do something else
} else {
// Unknown command
Serial.println("Unknown command");
}
}
void loop() {
processCommand();
delay(1000);
}
此代码在串行上阻塞,即在检测到换行符之前不会返回。您可以轻松地将代码修改为非阻塞,可能如下所示:
/* Read serial characters, if available and store them in strCommand
until we get a newline
Returns 0 if no command is available */
int readSerialCommand() {
idxCommandChar = 0;
while (Serial.available()) {
int in = Serial.read();
while (in!='\n') {
strCommand[idxCommandChar++] = in;
in = Serial.read();
}
strCommand[idxCommandChar++] = '\0';
return idxCommandChar;
}
return 0;
}
// Get command from serial (if available), and process it.
void processCommand() {
if (readSerialCommand()) {
....
在这两种情况下,您可能会在等待时丢失序列字符,因此您可能需要重新考虑该策略