web-dev-qa-db-fra.com

Quel est l'équivalent de Serial.available () dans pyserial?

Lorsque j'essaie de lire plusieurs lignes de données série sur un Arduino, j'utilise l'idiome suivant:

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

Dans Arduino C, Serial.available() renvoie le nombre d'octets pouvant être lus dans le tampon série (voir Documents ). Quel est l'équivalent de Serial.available() en python?

Par exemple, si je dois lire plusieurs lignes de données série, le code suivant doit être utilisé:

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

La propriété Serial.in_waiting renvoie le "nombre d'octets contenus dans le tampon de réception". 

Cela semble être l’équivalent de la description de Serial.available() : "le nombre d’octets ... déjà arrivés et stockés dans le tampon de réception série".

Essayer:

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

Pour les versions antérieures à pyserial 3.0, utilisez .inWaiting(). Pour déterminer votre version de pyserial, procédez comme suit:

import serial
print(serial.__version__)
9
Robᵩ

Une réponse correcte dépendra de la version de Python - cela m’a fait trébucher depuis un certain temps. Je soupçonne que certains des commentaires étaient en cours d'exécution sur Raspberry Pi qui est actuellement à Python 2.7.9 et de manière similaire à pySerial.

Donc, sur un Pi, vous pouvez utiliser ser.inWaiting() qui est similaire à Serial.available() dans Arduino C - les deux renvoient le nombre d'octets dans le tampon de réception; Pour pySerial> = 3.0, vous utilisez ser.in_waiting (notez qu'il s'agit d'un attribut et non d'une fonction - http://pyserial.readthedocs.io/en/latest/pyserial_api.html#serial.Serial.in_waiting )

Incidemment, sur un Pi (et vraisemblablement sur des Pythons/pySerials plus anciens), import serial ; print (serial.__version__) entraîne une erreur d’attribut mais fonctionne sur les versions les plus récentes.

1
jaydublu2002

J'ai résolu le même problème comme ça. Le seul inconvénient de ce code est que la première fois que j'envoie la lettre 'a', ser.inWaiting () renvoie 0. Pour supprimer cet effet, j'ai ajouté un délai de 1 seconde avant celle-ci. Cela semble résoudre le problème.

Dans mon cas, ATmega16 renvoie une chaîne de 8 ou 12 bits. Donc, je vais obtenir le nombre de bits arrivant à RPi avec ser.inWaiting (), puis je lirai autant de données avec ser.read (), en les combinant dans 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()
1
Evaldas22

J'ai écrit mon code comme ci-dessous. J'espère que vous pourrez l'utiliser pour modifier votre code

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()
0
Ajit Nayak