Wenn ich versuche, mehrere Zeilen serieller Daten auf einem Arduino zu lesen, verwende ich folgende Redewendung:
String message = "";
while (Serial.available()){
message = message + serial.read()
}
In Arduino C gibt Serial.available()
die Anzahl der verfügbaren Bytes aus dem seriellen Puffer zurück (siehe Docs ). Was ist das Äquivalent von Serial.available()
in Python?
Wenn ich zum Beispiel mehrere Zeilen serieller Daten lesen muss, würde ich erwarten, dass der folgende Code verwendet wird:
import serial
ser = serial.Serial('/dev/ttyACM0', 9600, timeout=0.050)
...
while ser.available():
print ser.readline()
Die Eigenschaft Serial.in_waiting
gibt die "Anzahl der Bytes im Empfangspuffer" zurück.
Dies scheint gleichbedeutend mit der Beschreibung von Serial.available()
zu sein: "Die Anzahl der Bytes ... die bereits eingetroffen sind und im seriellen Empfangspuffer gespeichert sind."
Versuchen:
import serial
ser = serial.Serial('/dev/ttyACM0', 9600, timeout=0.050)
...
while ser.in_waiting: # Or: while ser.inWaiting():
print ser.readline()
Verwenden Sie für Versionen vor pyserial 3.0 .inWaiting()
. Gehen Sie folgendermaßen vor, um Ihre physische Version zu ermitteln:
import serial
print(serial.__version__)
Eine korrekte Antwort hängt von der Version von Python ab - dies hat mich heute für einige Zeit in die Irre geführt. Ich vermute, einige der Kommentare liefen auf Raspberry Pi, das sich derzeit auf Python 2.7.9 befindet, und in ähnlicher Weise pySerial.
Auf einem Pi können Sie also ser.inWaiting()
verwenden, was Serial.available()
in Arduino C ähnelt. Beide geben die Anzahl der Bytes im Empfangspuffer zurück. Für pySerial> = 3.0 verwenden Sie ser.in_waiting
(beachten Sie, dass dies kein Attribut ist - http://pyserial.readthedocs.io/de/latest/pyserial_api.html#serial.Serial.in_waiting )
Übrigens führt import serial ; print (serial.__version__)
auf einem Pi (und vermutlich älteren Pythons/pySerials) zu einem Attribut-Fehler, funktioniert aber bei neueren Versionen.
Ich habe das gleiche Problem so gelöst. Der einzige Nachteil dieses Codes ist, dass ser.inWaiting () beim ersten Senden des Buchstabens 'a' 0 zurückgibt. Um diesen Effekt zu entfernen, habe ich eine Verzögerung von 1 Sekunde davor hinzugefügt. Das scheint das Problem zu lösen.
In meinem Fall sendet ATmega16 eine Zeichenfolge entweder 8 oder 12 Bit zurück. Also bekomme ich die Anzahl der Bits, die mit ser.inWaiting () in RPi eintreffen, und dann lese ich diese Daten mit ser.read () und kombiniere sie in 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()
Ich habe meinen Code wie folgt geschrieben. Ich hoffe, Sie können es verwenden, um Ihren Code zu ändern
import serial
import csv
import os
import time
import sys
import string
from threading import Timer
def main():
pass
if __== '__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()