I/O su porta seriale

 ☗ 

Importare il modulo serial descritto nella pagina http://pyserial.sourceforge.net/. Il modulo in versioni vecchie di Python per Windows può richiedere la presenza delle estensioni per Windows, mentre su Ubuntu/Linux è sufficiente installare i pacchetti python-serial o python3-serial. È possibile usare sia le porte seriali reali che quelle emulate tramite convertitore USB/RS232. Su Windows i nomi delle porte seriali sono "com1" "com2" ecc, mentre su Linux sono "/dev/ttyS0" "/dev/ttyS1" ecc (o "/dev/ttyUSB0" "/dev/ttyACM0" ecc quelle emulate su convertitore USB).


I dati binari

Tipo di dati trasmessi e ricevuti



Istanziare oggetto seriale e regolare i parametri di funzionamento

La porta si apre nel momento in cui si istanzia l'oggetto, di default i parametri sono settati 9600 8 N 1.

import serial
ser = serial.Serial("com1", 38400, 8, "N", 1, timeout=1)


Scrivere sulla seriale

I dati sono rappresentati da una stringa binaria in Python2 o da un oggetto bytes in Python3
ser.write(dati)


Leggere dalla seriale

I dati ritornati da read sono sotto forma di stringa binaria in Python2 o oggetto bytes in Python3.
dati = ser.read(n)   # lettura di n byte

Il metodo readline serve per ricevere una sequenza binaria da considerare come una singola riga di testo codificata, terminante con il carattere di fineriga \n (LF, byte 10, line feed).

dati = ser.readline() # lettura di una riga di testo


Svuotare i buffers di ingresso e uscita

ser.flushInput()
ser.flushOutput()


Conoscere il numero di byte presenti nel buffer di ricezione

ser.inWaiting()


Catturare le eccezioni della porta

try:  
    ser = serial.Serial("/dev/ttyUSB0", 9600, 8, "N", 1, timeout=1)  
except serial.serialutil.SerialException:  
    print("Porta seriale non apribile")  


Chiudere la porta

ser.close()



Esempio, lettura 256 byte da un modulo seriale esterno

Il modulo comunica con parametri 9600,8,N,2. Quando riceve la sequenza di byte 33, 0, 0, 0, 1 risponde inviando 256 byte. Vogliamo visualizzare su schermo il valore di questi byte in formato decimale disponendoli in una matrice di 16x16 elementi:

import serial
import struct

PORT = "/dev/ttyUSB0"

print("Lettura 256 byte da modulo seriale")
print("-" * 63)

data = 33, 0, 0, 0 ,1
txData = struct.pack("B"*len(data), *data)
ser = serial.Serial(PORT, 9600, 8, "N", 2, timeout=2)
ser.write(txData)
rxData = ser.read(256)
ser.close()
data = struct.unpack("B"*len(rxData), rxData)

for i in range(0, len(data), 16):
    chunk = data[i:i+16]
    print(" ".join("%3d" % n for n in chunk))

print("-" * 63)

Risultato:

Lettura 256 byte da modulo seriale
---------------------------------------------------------------
 33   0  32   1   0  32  62 255 119 190 194 136   0 175 119 190
194 136   0  35  11 120 177  32 237  49 239  63 221  33 240  63
 62 205  50 240  63  62 201  50 243  63 205 160   1 254   1  40
  7 254   2 204   0   2  24 242 122 254  32  32   5 205 167   0
 24 232 254  33  32   5 205 227   0  24 223 254  34  32   5 205
 29   1  24 214 254  31  32   5 205 154   0  24 205 254  35  32
  5 205  67   1  24 196 254  36  32   5 205  94   1  24 187 254
 37  32   5 205 107   1  24 178 254  38  32   5 205 125   1  24
169 254  39 204 149   1  24 162  14 128 121 238  64  79 211  16
 33  52  58  43 124 181  32 251  24 240 197  14  79 205 229   1
 14  75 205 229   1 193 201 245 197 213 229 205 160   1 254   1
 32  39 106 205 160   1 254   1  32  31  98 205 160   1 254   1
 32  23  74 205 160   1 254   1  32  15  66 205 160   1 254   1
 32   7 114  35  11 120 177  32 242 254   2 204   0   2 225 209
193 241 201 245 197 213 229 205 160   1 254   1  32  37 106 205
160   1 254   1  32  29  98 205 160   1 254   1  32  21  74 205
---------------------------------------------------------------


Determinare le porte seriali usabili sul sistema

#------------------------------------------------------------------------------
# Ritorna una tupla di nomi validi ('com1', 'com2', ....) ecc
# Le porte seriali presenti ma gia' in uso sono escluse
#------------------------------------------------------------------------------
def availableSerialPort():
    suffixes = "S", "USB", "ACM", "AMA"
    nameList = ["com"] + ["/dev/tty%s" % suffix for suffix in suffixes]
    portList = []
    for name in nameList:
        for number in range(48):
            portName = "%s%s" % (name, number)
            try:
                serial.Serial(portName).close()
                portList.append(portName)
            except IOError:
                pass
    return tuple(portList)