2016-07-28 5 views
2

Wenn ich mehrere Zeilen von seriellen Daten auf einem Arduino zu lesen versuche, verwende ich folgendes Idiom:Was entspricht Serial.available() in Pyserial?

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

In Arduino C, Serial.available() gibt die Anzahl der verfügbaren Bytes aus dem seriellen Puffer gelesen werden (siehe Docs). Was entspricht Serial.available() in Python?

Zum Beispiel, wenn ich mehrere Zeilen von seriellen Daten zu lesen, benötigen würde ich erwarten, den folgenden Code zu den ues:

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

Bitte beschreiben Sie entweder, was 'Serial.available()' ist oder stellen Sie einen Link zu seiner Dokumentation bereit. –

Antwort

2

Die Eigenschaft Serial.in_waiting die „die Anzahl der Bytes in den Empfangspuffer“ zurückgibt.

Dies scheint die Entsprechung von Serial.available() 's Beschreibung zu sein: "Die Anzahl der Bytes ... das ist bereits angekommen und im seriellen Empfangspuffer gespeichert."

Versuchen:

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

Für Versionen vor 3.0 bis pyserial, .inWaiting() verwenden. Um Ihre pyserial Version zu bestimmen, tun Sie dies:

import serial 
print(serial.__version__) 
+0

In allen einleitenden Tutorials für 'pyserial' habe ich nie den Befehl' ser.in_waiting' gesehen. Gibt es einen Grund, warum es vermieden wird? 'Serial.available()' ist in der seriellen Arduino C-Kommunikation allgegenwärtig. Verwenden Python-Entwickler normalerweise ein anderes Idiom, um dieselbe Aufgabe zu erfüllen? –

+0

AttributeError: 'serial' Objekt hat kein Attribut 'in_waiting' root @ raspberrypi:/home/wf # python3 - Version Python 3.4.2 –

+0

@WolfgangFahl - Wenn Ihre Version von 'pyserial' älter als 3.0 ist, versuchen Sie' .inWaiting() '. –

-1

Ich habe meinen Code wie folgt geschrieben. Hoffe, dass Sie es verwenden können, ändern Sie Ihren 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() 
+0

Vielen Dank für das Feedback Ajit, aber Ihr Code geht leider nicht auf mein Problem. Sie erwarten einfach, dass 150 Bytes serieller Daten mit 'ser.read (150)' verfügbar sind, anstatt zu prüfen, wieviel (falls überhaupt) verfügbar ist. Einige zusätzliche Tipps, viel von diesem Code kann durch pythonähnliche (kürzer, sauberer, schneller, einfacher zu lesen) verbessert werden. Versuchen Sie es mit dem 'with' Schlüsselwort in der Wiedergabe von' f = open() ',' f.close() 'und' ser.close() '. Zusätzlich sollte Ihr 'while COUNT <= 100:' durch ein 'für i in xrange (100)' oder 'für i in xrange (1, 101)' ersetzt werden, wenn Zero Indizierung ein Problem ist. –

0

Ich löste das gleiche Problem wie so. Der einzige Nachteil dieses Codes ist, dass ser.inWaiting(), wenn ich das erste Mal den Buchstaben 'a' sende, 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, ich werde die Anzahl der Bits erhalten RPi mit ser.inWaiting() und dann lese ich so viele Daten mit ser.read(), kombiniert 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() 
0

Eine korrekte Antwort hängt von der Version von Python ab - das hat mich für einige Zeit heute schon überfordert. Ich vermute, einige der Kommentare wurden auf Raspberry Pi ausgeführt, die derzeit bei Python 2.7.9 und ähnlich weniger als aktuelle pySerial ist.

Also auf einem Pi könnten Sie ser.inWaiting() verwenden, die Serial.available() in Arduino C ähnlich ist - beide geben die Anzahl der Bytes im Empfangspuffer zurück; 3.0 für pyserial> = Sie verwenden ser.in_waiting (beachten Sie, dies ist ein Attribut keine Funktion - http://pyserial.readthedocs.io/en/latest/pyserial_api.html#serial.Serial.in_waiting)

übrigens auf einem Pi (und vermutlich ältere Pythons/pySerials) import serial ; print (serial.__version__) Ergebnisse in einem Attribut Fehler, sondern arbeitet auf neuere Versionen.