Python Forum

Full Version: How to Properly Open a Serial Port in a Function
You're currently viewing a stripped down version of our content. View the full version with proper formatting.
Being a new guy to Python, I’m trying to figure out how to properly pass information between functions so I can keep redundant code to a minimum. However, I must have figured something wrong regarding my function that opens a serial port. I want to be able to open the serial port in one function and write to and read from the serial port in other functions. I think I’m returning serial port information wrong.

What am I missing that causes this code to not work?

"""Sends a  message via serial & receives back information via serial."""
 
import serial
import time
port = ' '
PLAYING_DONE = bytearray([170, 1, 1, 0, 172])

def request(port, track_info):
    """Start playing track.  Track is??"""
    print("def request ", port, track_info)  #For debugging
    write_command(port, [7] + track_info)

def write_command(port, command):
    """Write command to serial port"""
    print("def write_command ", port, command)  #For debugging
    command = [170] + command           # Command packet starts with 0xAA
    command.append(sum(command) % 256)  # Append checksum
    print('Command = ', command)        # For debugging purposes
    port_open(port)                     # Open Serial Port
    port.write(bytearray(command))     #<--- seems the error is here
    port.close()

def port_open(port):
    """Open serial port"""
    print("def port_open ", port)       #For debugging
    ser = serial.Serial('/dev/ttyS0',   # Serial port on my computer
        baudrate=9600, parity=serial.PARITY_NONE,
        stopbits=serial.STOPBITS_ONE,
        bytesize=serial.EIGHTBITS, timeout=30)     #  timeout for read
    return port

def read_status(port, info_length):
    """Read status?  Returns  bytearray"""
    print("def read_status ", port, info_length)
    write_command(port, [1, 0])
    time.sleep(0.5)
    port_open(port)                     # Open Serial Port
    if port.inWaiting() == info_length:
         return port.read(info_length)
    port.close()

request(port, [2, 0, 9])                # Track info?
while reading != PLAYING_DONE:
    reading = read_status(port, 4)
    print(f'Return = {reading}')        # For debugging purposes

request(port, [12, 0])                  # query_MP3_count
while reading[0] != PLAYING_DONE[0]:
    reading = read_status(port, 5)
    print(f'Return = {reading}')        # For debugging purposes
print("Total MP3s ", reading[3] + reading[4])
time.sleep(2)

print("Done and closed")
Error:
pi@raspberrypi:~ $ sudo python3 QueryTest.py def request [2, 0, 9] def write_command [7, 2, 0, 9] Command = [170, 7, 2, 0, 9, 188] def port_open Traceback (most recent call last): File "QueryTest.py", line 42, in <module> request(port, [2, 0, 9]) # Track info? File "QueryTest.py", line 11, in request write_command(port, [7] + track_info) File "QueryTest.py", line 20, in write_command port.write(bytearray(command)) AttributeError: 'str' object has no attribute 'write'
On line 5 port = ' ' so port is an empty string
The error on line 20 port.write(bytearray(command)) #<--- seems the error is here is because the code is trying to call a write method on that string of which does not have that method.

def port_open(port):
    """Open serial port"""
    print("def port_open ", port)       #For debugging
    ser = serial.Serial('/dev/ttyS0',   # Serial port on my computer
        baudrate=9600, parity=serial.PARITY_NONE,
        stopbits=serial.STOPBITS_ONE,
        bytesize=serial.EIGHTBITS, timeout=30)     #  timeout for read
    return port
this function has a port parameter but is it really needed as it's aim is to open a port.
it is returned the port that is passed into it which is an empty string.
Should it be returning the opened port ser

If port_open(port) was actually returning an open port, in the two places that it's used at the moment its is not using a variable to point to that open port.
port = port_open(port)
Thanks guys.

You showed me the problem in my program. Actually 2 problems.

1st, the statement ser = serial.Serial('/dev/ttyS0', should be port = serial.Serial('/dev/ttyS0'.
2nd, I added the statement port = port_open(port) where appropriate.

I have some more fine tuning but that made all of the difference.

Thanks again.