Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/python/360.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
一次串行通信-Python脚本和Arduino之间的多次读写_Python_Serial Port_Arduino - Fatal编程技术网

一次串行通信-Python脚本和Arduino之间的多次读写

一次串行通信-Python脚本和Arduino之间的多次读写,python,serial-port,arduino,Python,Serial Port,Arduino,我想在Python守护进程和Arduino之间建立一个串行通信。 首先,Python守护进程设置一个串行连接,该连接将持续守护进程的整个生命周期。通过这个连接,我希望每次Python守护进程接收命令时,都向Arduino发送数据并在acks变量中接收回数据 问题是,虽然第一次通信进展顺利,但之后没有通过串行通信发送任何信息。如果我为每个请求建立一个新的连接,它会工作,但它会使程序非常慢,这是我想要避免的。 编辑:真正的问题是何时将正确的字符串发送到arduio evrything运行正常,但当我

我想在Python守护进程和Arduino之间建立一个串行通信。 首先,Python守护进程设置一个串行连接,该连接将持续守护进程的整个生命周期。通过这个连接,我希望每次Python守护进程接收命令时,都向Arduino发送数据并在
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()) {
     ....
在这两种情况下,您可能会在等待时丢失序列字符,因此您可能需要重新考虑该策略