Kravitz
Kravitz

Reputation: 2859

Pyserial - RS232 9600,8,N,1 send and receive data

I need to communicate and pass values to a serial connected device using RS232 Protocol. I need to pass commands through the 8 bytes of data and then be able to receive the response afterwards.. Im not sure how to write this in PySerial so if anyone can help out it would be great (9600 Baud, 8 data bits, No parity, and 1 stop bit.)

import serial
ser = serial.Serial('/dev/ttyUSB0')  # open serial port
print(ser.name)         # check which port was really used
ser.write(b'hello')     # write a string
ser.close()             # close port

The Timer Manager Command structure consists of one start byte, one command byte, five bytes of data, and a one byte checksum. Each message packet is formatted as follows:

BYTE 0  BYTE 1    BYTE 2    BYTE 3     BYTE 4   BYTE 5    BYTE 6    BYTE 7
200     COMMAND   DATA1     DATA2      DATA3    DATA4     DATA5     CK SUM

Im looking to receive the following back from the machine: If command was successfully received, the Timer Manager will respond with:

  BYTE 0    BYTE 1  BYTE 2
   6            0       6

The actual data that I want to send is this Data i need to pass to the timer is structured this way:

   BYTE 0   BYTE 1  BYTE 2  BYTE 3  BYTE 4  BYTE 5  BYTE 6  BYTE 7
      200       31      4      0        0        0       0  235

Is this passed via bytearray ?

      ser.write( bytearray(200,31,4,0,0,0,0,235) );

Upvotes: 2

Views: 11877

Answers (2)

First of all, due to the fact that you use RS232, you must set the ASCII characters you wanna send in variables. And then, when you got in a variable all the sentence you want to send, sent it decoding it into bytes. It would be something like this.

def sendserial(sendstring):
    ser.port(yourport)
    try:
        ser.open()
    except Exception as e:
        flag=1
    if ser.isOpen():
        try:
            ser.flushInput()
            ser.flushOutput()
            ser.write(bytes(sendstring,'iso-8859-1'))
            #iso 8859-1 is the only encode that works for me
            time.sleep(0.5)
            numOfLines = 0
            while True:
                resp = bytes.decode(ser.readline())
                result = ord(str(response))
                if result == ord(ACK)
                #I set previously the ACK var to the ASCII symbol that the machine returns
                    response = 'Y'
                else:
                    response = 'N'
                numOfLines = numOfLines +1
                if (numOfLines>=1):
                    break
            ser.close()
        except Exception as e1:
            print('Communication error...:' + str(e1))
    else:
        pass
    return(response) 

Upvotes: 2

jpkotta
jpkotta

Reputation: 9427

I generally have something like this to do binary IO over a serial port:

from timeit import default_timer as clk
from serial import Serial, SerialException

class TimeManager(object):
    def __init__(self, port, baudrate=9600):
        self.ser = Serial(port, baudrate=baudrate)
        self.ser.open()
        self.ser.flushInput()
        self.ser.flushOutput()

    def send(self, tx):
        tx = bytearray(tx)
        try:
            self.ser.write(tx)
            self.ser.flush()
        except SerialException as e:
            if e.args == (5, "WriteFile", "Access is denied."):
                # This occurs on win32 when a USB serial port is
                # unplugged and replugged.  It should be fixed by
                # closing and reopening the port, which should happen
                # in the error handling of our caller.
                raise IOError(errno.ENOENT, "Serial port disappeared.",
                              self.ser.portstr)
            else:
                raise

    def receive(self):
        rx = bytearray()
        delay = 10e-3 # s
        timeout = 1 # s
        end_time = clk() + timeout
        while True:
            time_remaining = end_time - clk()
            if time_remaining < 0:
                break
            rx += self.ser.read(self.ser.inWaiting())
            if 0 in rx:
                break
            time.sleep(delay)

        if time_remaining <= 0:
            raise IOError(errno.ETIMEDOUT, "Communication timed out.")

        return rx

tm = TimeManager("/dev/ttyS0")

My device sends null terminated messages (the if 0 in rx: line). You'd have to figure out a similar condition for your messages.

Upvotes: 2

Related Questions