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
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
Link | fevereiro 6th, 2010 at 19:38
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.
Link | fevereiro 7th, 2010 at 10:06
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?
Link | novembro 30th, 2010 at 21:32