pyserial 中 Serial.available() 的等价物是什么?

What is the equivalent of Serial.available() in pyserial?

当我尝试读取 Arduino 上的多行串行数据时,我使用以下习惯用法:

String message = "";
while (Serial.available()){
    message = message + serial.read()
}

在 Arduino C 中,Serial.available() returns 可从串行缓冲区读取的字节数(参见 Docs)。 python中的Serial.available()相当于什么?

例如,如果我需要读取多行串行数据,我希望使用以下代码:

import serial
ser = serial.Serial('/dev/ttyACM0', 9600, timeout=0.050)
...
while ser.available():
    print ser.readline()

属性Serial.in_waitingreturns“接收缓冲区中的字节数”。

这似乎等同于 Serial.available() 的描述:“字节数......已经到达并存储在串行接收缓冲区中。”

尝试:

import serial
ser = serial.Serial('/dev/ttyACM0', 9600, timeout=0.050)
...
while ser.in_waiting:  # Or: while ser.inWaiting():
    print ser.readline()

对于 pyserial 3.0 之前的版本,使用 .inWaiting()。要确定您的 pyserial 版本,请执行以下操作:

import serial
print(serial.__version__)

我的代码如下。希望你能用它修改你的代码

import serial
import csv
import os
import time
import sys
import string
from threading import Timer

def main():
    pass

if __name__ == '__main__':
    main()
    COUNT=0

    f=open("test.csv","w+");
    result = csv.writer(f,delimiter=',')
    result_statement=("Dir","ACTUATOR_ON_OFF","MODE","DATE","TIME"," TRACKER DESIRED ANGLE"," TRACKER ACTUAL ANGLE")
    result.writerow(result_statement)
    f.close()
    while COUNT<=100:
    #while():
      time.sleep(60)
      ser=serial.Serial()
      ser.port=12
      ser.baudrate=9600
      ser.open()

      str=ser.read(150)
      # print "string are:\n",str
      print type(str)
      val=str.split(":")
      # print "value is:\n",val
      lines=str.split("\r\n")
     # print  "line statement are :\n",lines
      COUNT=COUNT+1
      print COUNT
      f=open("test.csv","a+");
      result = csv.writer(f,delimiter=',')
      wst=[]
      for line in lines[:-1]:
            parts=line.split(":")
            for p in parts[1:]:
                wst.append(p)


            #result = csv.writer(f,delimiter=',')
            #wst.append(parts[1:])

      print "wst:\n",wst
      result.writerow(wst)
      f.close()
f.close()
ser.close()

我这样解决了同样的问题。这段代码的唯一缺点是,当我第一次发送字母 'a' 时,ser.inWaiting() 将 return 0。为了消除这种效果,我在它之前添加了 1 秒的延迟.这似乎解决了问题。

在我的例子中,ATmega16 发回一个 8 位或 12 位的字符串。所以,我将使用 ser.inWaiting() 获取到达 RPi 的位数,然后我将使用 ser.read() 读取那么多数据,将它们组合成 ser.read(ser.inWaiting())

import RPi.GPIO as GPIO
from time import sleep
import serial # version is 3.2.1

ser = serial.Serial('/dev/rfcomm0', 9600)
ser.parity = serial.PARITY_ODD
ser.parity = serial.PARITY_NONE

GPIO.setmode(GPIO.BOARD)

led1 = 16
led2 = 18
button = 7

GPIO.setup(led1, GPIO.OUT)
GPIO.setup(led2, GPIO.OUT)
GPIO.setup(button, GPIO.IN, pull_up_down = GPIO.PUD_UP)

try:
    while True:
        choice = raw_input("Enter 'a' if you want to turn LED ON or 'b' "
                       + "to turn the LED OFF: ")
        if (choice == "a"):
            print "Sending command to turn LED ON"
            GPIO.output(led1, GPIO.HIGH)
            sleep(1)
            GPIO.output(led1, GPIO.LOW)
            #Send the actual data
            ser.write('a');
            #Receive what ATmega it send back
            sleep(1)
            received_data = ser.read(ser.inWaiting())
            print "Received data: " + received_data

        elif (choice == "b"):
            print "Sending command to turn LED OFF"
            GPIO.output(led2, GPIO.HIGH)
            sleep(1)
            GPIO.output(led2, GPIO.LOW)
            #Send the actual data
            ser.write('b');
            #Receive what ATmega it sends back
            sleep(1)
            received_data = ser.read(ser.inWaiting())
            print "Received data: " + received_data

        else:
            print "Invalid command"
            GPIO.output(led1, GPIO.HIGH)
            GPIO.output(led2, GPIO.HIGH)
            sleep(.3)
            GPIO.output(led1, GPIO.LOW)
            GPIO.output(led2, GPIO.LOW)
            sleep(.3)
            GPIO.output(led1, GPIO.HIGH)
            GPIO.output(led2, GPIO.HIGH)
            sleep(.3)
            GPIO.output(led1, GPIO.LOW)
            GPIO.output(led2, GPIO.LOW)
            #send invalid command
            ser.write(choice);
            #receive what ATmega sends back
            sleep(1)
            received_data = ser.read(ser.inWaiting())
            print "Received data: " + received_data

finally:
    GPIO.cleanup()

正确答案将取决于 Python 的版本 - 今天这让我困惑了一段时间。我怀疑一些评论是 Raspberry Pi 上的 运行,目前是 Python 2.7.9,同样低于当前的 pySerial。

所以在 Pi 上你可以使用 ser.inWaiting() 这类似于 Arduino C 中的 Serial.available() - return 接收缓冲区中的字节数;对于 pySerial >= 3.0,你使用 ser.in_waiting (注意这是一个属性而不是函数 - http://pyserial.readthedocs.io/en/latest/pyserial_api.html#serial.Serial.in_waiting

顺便说一下,在 Pi 上(可能是更旧的 Pythons/pySerials)import serial ; print (serial.__version__) 会导致属性错误,但适用于较新的版本。

您可以将 ser.readline()timeout=1

一起使用

当你初始化端口和波特率时,你必须设置超时,因为没有超时ser.readline()是不工作的。