我想在Python守护进程和Arduino之间建立一个串行通信。
首先,Python守护程序设置一个串行连接,该连接将持续守护进程的整个生命周期。通过这种连接,我想在每次Python守护进程接收命令时将数据发送到Arduino并在acks
变量中接收数据。
问题在于,当第一次通信顺利时,之后没有任何内容通过串行发送。如果我为它的每个请求建立一个新的连接,但它使程序非常慢,我想避免。 编辑真正的问题是,当发送正确的字符串到arduio evrything顺利但是当我发送错误的串口端口块并且它永远不会再次重新确定corrct字符串时(问题是在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);
}
答案 0 :(得分:2)
在你的Arduino代码中,你的逻辑有点时髦 - 所以,我不确定,但你是否在再次开始循环之前将索引清除为0?它看起来像一旦index == 19,它可能会或可能不会重置为0,具体取决于后面的逻辑。如果您再次输入Comp()并且索引&gt; = 19,那么您将永远不会再次读取串口。
答案 1 :(得分:0)
我认为 @Zeus 是完全正确的(因此我赞成这个答案),但也存在其他问题。重申 @Zeus 所说的话:
index
仅重置为0
。因此,您的缓冲区已满,您要查找的字符串不存在,index
永远不会再次返回0
。index
到达19
后,不再阅读。因此,inData
中的任何内容都会停留在inData
,并且所有未来的比较都将失败,这意味着index
永远不会重置为0
。代码中还有许多其他问题,但主要问题是设计非常脆弱,并且容易出现您遇到的那种错误。例如,如果您的Python脚本发送的换行符是CR + LF换行符,但是您只期望CR,那么您将遇到类似的失败:第一次通信工作,但再也不会。
我建议重新组织你的代码:
这可能看起来很粗糙如下
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()) {
....
在任何一种情况下,您在等待时可能会丢失连续字符,因此您可能需要重新考虑该策略。