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

萝らか妹 提交于 2020-05-25 06:38:11

问题


When I am trying to read multiple lines of serial data on an Arduino, I use the following idiom:

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

In Arduino C, Serial.available() returns the number of bytes available to be read from the serial buffer (See Docs). What is the equivalent of Serial.available() in python?

For example, if I need to read multiple lines of serial data I would expect to ues the following code:

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

回答1:


The property Serial.in_waiting returns the "the number of bytes in the receive buffer".

This seems to be the equivalent of Serial.available()'s description: "the number of bytes ... that's already arrived and stored in the serial receive buffer."

Try:

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

For versions prior to pyserial 3.0, use .inWaiting(). To determine your pyserial version, do this:

import serial
print(serial.__version__)



回答2:


I have written my code as below. Hope you can use it modify your code

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()



回答3:


I solved the same problem like so. The only drawback of this code is that when the first time I'm sending letter 'a', ser.inWaiting() will return 0. To remove this effect I added delay of 1 second before it. That seems to solve the problem.

In my case, ATmega16 sends back a string either 8 or 12bits. So, I will get the number of bits arriving to RPi with ser.inWaiting() and then I'll read that much data with ser.read(), combining them into 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()



回答4:


A correct answer will depend on the version of Python - this has tripped me up for some time today. I suspect some of the comments were running on Raspberry Pi which is currently at Python 2.7.9 and similarly less-than-current pySerial.

So on a Pi you might use ser.inWaiting() which is similar to Serial.available() in Arduino C - both return the number of bytes in the receive buffer; for pySerial >= 3.0 you use ser.in_waiting (note this is an attribute not a function - http://pyserial.readthedocs.io/en/latest/pyserial_api.html#serial.Serial.in_waiting)

Incidentally, on a Pi (and presumably older Pythons/pySerials) import serial ; print (serial.__version__) results in an attribute error but works on newer versions.



来源:https://stackoverflow.com/questions/38645060/what-is-the-equivalent-of-serial-available-in-pyserial

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!