问题
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