树莓派和arduino之间使用pyserial进行通信

时间:2019-02-17 16:28:53

标签: python-3.x python-2.7 arduino raspberry-pi3 pyserial

我正在为我的学习做一个小项目。已经快完成了,但是我遇到了一个小问题,实际上我不知道发生了什么。

最主要的是使用USB和pyserial在树莓派和arduino之间进行通信。那至少工作了1个月才停止。

我正在使用Raspberry Pi 3模型B(带有python 2.7 / 3.5)和arduino UNO板。 Arduino代码还通过Windows 10使用python 3.7进行了测试

Raspberry-python代码:

read_all来自https://stackoverflow.com/a/47614497/4946344,用于检查我的函数是否没有丢失

def read_all(port, chunk_size=200):
    """Read all characters on the serial port and return them."""
    if not port.timeout:
        raise TypeError('Port needs to have a timeout set!')

    read_buffer = b''

while True:
    # Read in chunks. Each chunk will wait as long as specified by
    # timeout. Increase chunk_size to fail quicker
    byte_chunk = port.read(size=chunk_size)
    read_buffer += byte_chunk
    if not len(byte_chunk) == chunk_size:
        break

return read_buffer

def ArduinoConnection(portName):
global ser
try:
    ser = Serial(
                port = portName,
                baudrate = 9600,
                parity = serial.PARITY_NONE,
                stopbits = serial.STOPBITS_ONE,
                bytesize = serial.EIGHTBITS,
                timeout=2, # IMPORTANT, can be lower or higher
                inter_byte_timeout=0.1 # Alternative
            )
    print("Successfully connected with Arduino board with speed of 9600 bounds")
    return None
except:
    print("Can not connect with Arduino board, please contact with the system administrator")
    print("press a key to exit ...")
    input()
    return exit()

def serialRead():
global ser
return ser.read(ser.in_waiting).decode()

def serialWrite(command):
global ser
print("sended {0}".format(command))
ser.write(command.encode())
return None


while True:
lc = time.localtime()
sec = lc.tm_sec
if sec != prev_sec:
    prev_sec = sec
    print(str(lc.tm_hour) + ":" + str(lc.tm_min) + ":" + str(sec))
    if sec == 50:
        board_cfg = getCfg()
        serialWrite(board_cfg)
    elif sec == 0:
        serialWrite("112:112")
        time.sleep(2)
        print(serialRead())
    elif sec == 5:
        serialWrite("11:11")
        time.sleep(2)
        setMeasures(serialRead())

我认为arduino方面是正确的。我在两个Arduino Uno板上检查了这一点。 当我直接在串行监视器中键入命令时,我会得到预期的输出,例如112:112命令,我应该得到类似的东西:

 ===== config #0 =====
@ sensor id  -> 0
@ event -> 0
@ value -> 0
@ relay -> 0
@ time (ms) -> 0

 ===== config #1 =====
@ sensor id  -> 0
@ event -> 0
@ value -> 0
@ relay -> 0
@ time (ms) -> 0

 ===== config #2 =====
@ sensor id  -> 0
@ event -> 0
@ value -> 0
@ relay -> 0
@ time (ms) -> 0

 ===== config #3 =====
@ sensor id  -> 0
@ event -> 0
@ value -> 0
@ relay -> 0
@ time (ms) -> 0

但是在树莓派以及现在的Windows 10上,在两种情况下-当尝试使用serialRead()read_all()函数进行读取时,我都得到了一个空字节响应(b'')

那是什么样子:http://prntscr.com/mmaglv

现在停下来。

我还观察到,当Rpi发送命令时,在Arduino上,只有RX led发光以进行读取,而从没发出TX二极管进行响应。

但是正如我所说的,它可以在arduino IDE的串行监视器上直接工作,并且两个二极管都发光。 (屏幕截图:http://prntscr.com/mmajih

我有点困惑。

任何提示可能有什么问题吗?

NEW EDIT 27.02:

我发现通讯错误。

问题是缓冲区的大小为600个字符,并且Serial.readBytes()函数阻塞了Arduino线程(我不知道为什么直接在串行监视器上可以正常工作)。我使用Serial.readBytes()而不是Serial.readBytesUntil()

关于arduino的最后一个奇怪的问题

Arduino sread()函数

void sread (){
    int cfgnr = -1;
    int INPUT_SIZE = 600;
    char input[INPUT_SIZE + 1];
    byte size = Serial.readBytesUntil('>', input, INPUT_SIZE);
    input[size] = 0;
    bool writeConfig = false;

    String a = String(input);
    if (a != "")
      log(a);
    char* command = strtok(input, "&");
    while (command != 0)
    {
      char* separator = strchr(command, ':');
      if (separator != 0)
      {
          *separator = 0;
          int a = atoi(command);
          ++separator;
          int b = atoi(separator);

          if(writeConfig){
            _config[cfgnr][a] = b;
          }

          if(a == 99 && b == 99){
            writeConfig = true;
            cfgnr++;
          }
          else if(a == 11 && b == 11){
            writeConfig = false;
            log(responseMeasures());
          }
          else if(a == 112 && b == 112){
            typeConfig();
          }
      }
      command = strtok(0, "&");
    }
}
void log(String s){
  Serial.println(s);
}

我正在使用strtok()strchr()拆分字符串以读取并设置配置

这是一个示例字符串(为了更好的可读性,我将其分成几行)
99:99&0:2&1:2&2:1&3:4&4:6000&
99:99&0:1&1:2&2:1&3:3&4:4000&
99:99&0:5&1:2&2:1&3:1&4:5000&
99:99&0:6&1:2&2:1&3:2&4:5000

while循环在99:99之后的第三次迭代(上面的第三行)期间停止

来自串行监视器https://prnt.sc/mqzyf5的屏幕截图

我有点困惑
有什么想法吗?

0 个答案:

没有答案