PySerial - Utilize o Python para controlar a interface serial

September 9, 2009

[Warning: This post is a backup recovery from my previous Wordpress blog. All content was automatically converted accessing a MySQL database using a Python script (details). Mostly are in Portuguese but if you are interest I can translate to English. If you found any problem dont’t hesitate to contact me in comments.]

Embora seja uma tecnologia antiga ainda utilizada amplamente, muitos dos projetos eletrnicos no estilo "faa voc mesmo" utilizam o protocolo de comunicao serial. Este post mostra como possvel (e fcil) utilizar a linguagem Python para fazer a interface com a porta serial (RS232) seja no Windows, GNU/Linux, *BSD, Solaris, etc. Com o PySerial dentro de um sistema embarcado pode-se fazer coisas muito interessante como direcionamento do fluxo de dados e coleta de dados para depurao.

1. Instalao

Consideraremos a utilizao algum sistema operacional GNU (com a linguagem Python instalada) para o desenvolvimento, a instalao do mdulo feita atravs do gerenciador de pacotes da sua distribuio ou pelo easy_install

easy_install pyserial

2. Uso

Se voc no possuir onde testar utilize o prprio cabo serial: faa um curto entre os pinos 2 (RX) e 3 (TX).

Abra um programa para acessar a serial como o gtkterm (modo grfico) ou minicom (modo texto) e veja que o que voc digitar ir ecoar. Para os exemplos utilizaremos o gtkterm e o primeiro ser para escrita.

#!/usr/bin/python
import serial
ser = serial.Serial(0)	        # abre a primeira serial que encontrar
                                # (/dev/ttySX). No Windows seria a COMX.
print ser.portstr		# mostra a porta utilizada
ser.write("hello")	        # envia
ser.close()			# fecha a porta

Aps rodar esse exemplo voc ir ver no gtkterm o texto "hello". Agora vamos ver como fazer uma leitura:

#!/usr/bin/python
import serial
ser = serial.Serial(0)
ser.read()			# espera 1 byte (um caracter)
ser.close()

O programa ficar travado esperando receber algum dado da serial (veja o parmetro timeout). Ao utilizar o gtkterm e o cabo em curto no ir funcionar muito bem para enviar muitos bytes (teste feito com o conversor USB/Serial), mas possvel fazer a prova do conceito. Se voc digitar uma letra no gtkterm ir v-la na interface de linha de comando do Python.

3. Parmetros

At agora no falamos dos parmetros da porta serial, eles vo depender muito do equipamento que voc ir se conectar. Por padro o construtor define os seguintes valores:

ser = serial.Serial(
    port=None,			# nmero do device, a numerao comea no zero
 	               		# Se algo falhar, o usurio pode
                                # espeficiar a string do device (/dev/ttyX, COMX,
                                # etc). Se nada  especificado um objeto com a
                                # porta fechada e no configurada  criado.
    baudrate=9600,		# baud rate
    bytesize=EIGHTBITS,		# nmero de databits
    parity=PARITY_NONE,		# bit de paridade
    stopbits=STOPBITS_ONE,	# nmero de bits de parada 
    timeout=None,		# ajusta um timeout, coloque "None" para no haver
    xonxoff=0,			# ativa controle de fluxo por software
    rtscts=0,			# ativa controle de fluxo RTS/CTS
    interCharTimeout=None	# Inter-character timeout, "None" para desabilitar
)

Veja que se no preenchermos nada ele ir utilizar os valores padro. Pode-se ajustar os valores no construtor da classe ou ento separadamente, por exemplo, para reajustar o timeout faa:

ser.timeout=3	# Aguarda 3 segundos quando for fazer
                # um read() ou at completar o tamanho em bytes
                # especificado.

No mbito geral importante definir os valores de port, baudrate e o timeout, embora em muitas aplicaes embarcadas e modens o acesso aos pinos de controle RTS/CTS so essenciais . Os mtodos mais populares para as instncias so:

# abre a porta serial
open()
# fecha a porta imediadamente
close()
# muda o baudrate
setBaudrate(baudrate)
# l "size" caracteres , por padro l 1 byte
read(size=1)
# escrever um dado na porta serial
write(s)
# limpa o buffer de entrada, desconsidera todo o contedo
flushInput()
# limpa o buffer da sada, interrompe a sada.
flushOutput()

Exemplo:

>>> import serial
>>> ser = serial.Serial(0)
>>> ser
Serial(port='/dev/ttyUSB0', baudrate=9600, bytesize=8, parity='N', stopbits=1, timeout=None,
xonxoff=0, rtscts=0, dsrdtr=0)
>>> print ser.isOpen()
True

4. Dicas

Estas dicas so arbitrrias, so pequenas partes que fui utilizando ao longo do tempo e tentei organiz-las aqui.

  • Para enviar um contedo hexadecimal utilze \x, por exemplo, para enviar o caracter '1' e '2' faa ser.write('\x31\x32')
  • Pode-se converter para outras bases entre 2 e 36 utilizando int(), exemplo:
>>> print int('g',18)
16
  • No GNU/Linux, se voc utilizar algum conversor USB/Serial e seu sistema produzir um erro ao tentar iniciar a porta pelo construtor serial.Serial(0) porqu o device /dev/ttyUSBX no foi encontrado, uma soluo a abordagem abaixo.
import serial
import glob

def scan():
    """busca por portas disponveis, retorna uma lista de dispositivos"""
    return glob.glob('/dev/ttyUSB*') + glob.glob('/dev/ttyS*')

ser = serial.Serial(scan()[0])
  • Sobre os conversores USB/Serial: normalmente as distribuies entregam o Linux (kernel) com o suporte aos conversores seriais. Se o seu kernel no suportar ou voc tem alguma particularidade, veja no menu de configurao:
Device Drivers  --->
        Character devices  --->
                Serial drivers  --->
  • Utilize o PyQT ou PyGTK para incrementar a interface com o usurio.

Como uma aplicao especfica para cada caso, preferiu-se no dar nenhum detalhe do uso particular, acredito que o objetivo motivar o leitor a acessar a documentao disponvel e procurar fazer os prprios testes. Na referncia h bons exemplos e rapidamente voc ir fazer seus programas utilizando a serial. Com Python nem a imaginao o limite ;-)

http://pyserial.wiki.sourceforge.net/pySerial