Michael Molter
Michael Molter

Reputation: 1326

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

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

Upvotes: 20

Views: 80125

Answers (6)

When you initialize port and baud rate, you have to set timeout because without time out ser.readline() is not working.

Upvotes: -1

Chauhan Milan
Chauhan Milan

Reputation: 1

you can use ser.readline() with timeout=1

Upvotes: -1

Robᵩ
Robᵩ

Reputation: 168616

The property Serial.in_waiting returns "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__)

Upvotes: 30

jaydublu2002
jaydublu2002

Reputation: 11

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.

Upvotes: 1

evsu
evsu

Reputation: 31

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

Upvotes: 2

Ajit Nayak
Ajit Nayak

Reputation: 37

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

Upvotes: 2

Related Questions