set
09
2009

PySerial – Utilize o Python para controlar a interface serial

Embora seja uma tecnologia antiga ainda é utilizada amplamente, muitos dos projetos eletrônicos no estilo “faça você mesmo” utilizam o protocolo de comunicação serial. Este post mostra como é possível (e fácil) 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 depuração.

1. Instalação

Consideraremos a utilização algum sistema operacional GNU (com a linguagem Python instalada) para o desenvolvimento, a instalação do módulo é feita através do gerenciador de pacotes da sua distribuição ou pelo easy_install

easy_install pyserial

2. Uso

Se você não possuir onde testar utilize o próprio cabo serial: faça um curto entre os pinos 2 (RX) e 3 (TX).

Abra um programa para acessar a serial como o gtkterm (modo gráfico) 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

Após 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 parâmetro timeout). Ao utilizar o gtkterm e o cabo em curto não irá funcionar muito bem para enviar muitos bytes (teste feito com o conversor USB/Serial), mas é possível fazer a prova do conceito. Se você digitar uma letra no gtkterm irá vê-la na interface de linha de comando do Python.

3. Parâmetros

Até agora não falamos dos parâmetros da porta serial, eles vão depender muito do equipamento que você irá se conectar. Por padrão o construtor define os seguintes valores:

ser = serial.Serial(
    port=None,			# número do device, a numeração começa no zero
 	               		# Se algo falhar, o usuário pode
                                # espeficiar a string do device (/dev/ttyX, COMX,
                                # etc). Se nada é especificado um objeto com a
                                # porta fechada e não configurada é criado.
    baudrate=9600,		# baud rate
    bytesize=EIGHTBITS,		# número de databits
    parity=PARITY_NONE,		# bit de paridade
    stopbits=STOPBITS_ONE,	# número de bits de parada
    timeout=None,		# ajusta um timeout, coloque "None" para não 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 não preenchermos nada ele irá utilizar os valores padrão. Pode-se ajustar os valores no construtor da classe ou então separadamente, por exemplo, para reajustar o timeout faça:

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 aplicações embarcadas e modens o acesso aos pinos de controle RTS/CTS são essenciais . Os métodos mais populares para as instâncias são:

# abre a porta serial
open()
# fecha a porta imediadamente
close()
# muda o baudrate
setBaudrate(baudrate)
# lê "size" caracteres , por padrão lê 1 byte
read(size=1)
# escrever um dado na porta serial
write(s)
# limpa o buffer de entrada, desconsidera todo o conteúdo
flushInput()
# limpa o buffer da saída, interrompe a saída.
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 são arbitrárias, são pequenas partes que fui utilizando ao longo do tempo e tentei organizá-las aqui.

  • Para enviar um conteúdo hexadecimal utilze \x, por exemplo, para enviar o caracter ‘1′ e ‘2′ faça 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 não foi encontrado, uma solução é a abordagem abaixo.
import serial
import glob

def scan():
    """busca por portas disponíveis, 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 distribuições entregam o Linux (kernel) com o suporte aos conversores seriais. Se o seu kernel não suportar ou você tem alguma particularidade, veja no menu de configuração:
Device Drivers  --->
        Character devices  --->
                Serial drivers  --->
  • Utilize o PyQT ou PyGTK para incrementar a interface com o usuário.

Como uma aplicação é específica para cada caso, preferiu-se não dar nenhum detalhe do uso particular, acredito que o objetivo é motivar o leitor a acessar a documentação disponível e procurar fazer os próprios testes. Na referência há bons exemplos e rapidamente você irá fazer seus programas utilizando a serial. Com Python nem a imaginação é o limite ;-)

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

tags: , , ,
posted in programação by Tiago Maluta

Follow comments via the RSS Feed | Deixe um comentário | Trackback URL

3 Comments to "PySerial – Utilize o Python para controlar a interface serial"

  1. Luigi wrote:

    Ola!!!!!!!

    eu instalei o Py serial no Windows… mas parece que eu não consigo importar essa função no compilador….. algume saberia me dizer porque?

    att,
    Luigi

  2. Tiago Maluta wrote:

    Luigi,
    Qual o procedimento que você está usando e a mensagem de erro?
    Um erro muito comum é na hora de dar o import escrever pyserial e não apenas serial.

  3. Sergio wrote:

    Olá pessoal.
    Estou tentando estabelecer contato de um uC PIC com o Python pela serial.
    As dicas acima funcionam, mas quando transmito o caracter ‘A’(65d), chega um caracter código 140, um C colado em um E(CE).
    Alguém poderia me auxiliar?

Leave Your Comment