Raspberry PI – GPIO input com Python

raspberry-pi-gpio-python
raspberry-pi-gpio-python

Introdução

 

A primeira parte da série de interação com o GPIO (General Purpose Input Output) do Raspberry PI no modo Output possui os passos fundamentais para esta segunda etapa como a preparação do ambiente. Nesta segunda etapa vamos ver o modo Input, e para a prática será utilizado o Raspberry PI B, protoboard, pushbutton e alguns resistores. Serão mencionados os possíveis modos de trabalho com Input utilizando resistores de pull-up e pull-down, internos ou externos, e recursos como detecção de borda, debounce por software e uma “interrupção” baseada na detecção por borda.

 

 

Configuração do ambiente host

 

  • Board: Raspberry PI B;

  • Distribuição: Raspbian – Debian Wheezy (2014-01-07);

  • Kernel 3.12.22;

  • Python 2.7.3;

  • RPi.GPIO 0.5.7.

 

 

RPi.GPIO

 

Já vimos na primeira parte da série as funções RPi.GPIO.setmode(), RPi.GPIO.setup(), RPi.GPIO.output(), RPi.GPIO.input() e RPi.GPIO.cleanup(), e agora vamos ver algumas funções e parâmetros que tornam o modo input muito interessante.

 

  • RPi.GPIO.RISING => Borda de subida, quando passa de 0V para 3.3V;
  • RPi.GPIO.FALLING => Borda de descida, quando passa de 3.3V para 0V;
  • RPi.GPIO.BOTH => Os dois estados, ocorre ação tanto na subida [0V → 3.3V] quanto na descida [3.3V → 0V];
  • RPi.GPIO.LOW => Nivel lógico baixo [low] ou 0V;
  • RPi.GPIO.HIGH => Nivel lógico alto [high] ou 3.3V;
  • RPi.GPIO.PUD_UP => Pino Input em modo pull-up;
  • RPi.GPIO.PUD_DOWN => Pino Input em modo pull-down;
  • RPi.GPIO.PUD_OFF => Padrão.

 

  • RPi.GPIO.wait_for_edge() => Bloqueia a execução até que o botão seja pressionado ou a ação setada aconteça;
  • RPi.GPIO.event_detected() => Guarda o estado de um evento no pino, e quando for verificado no loop, indica se houve ou não mudança no pino. Pode ser utilizado dentro do loop e não irá perder a informação;
  • RPi.GPIO.add_event_detect() => Adiciona um evento baseado no pino, se o evento irá ocorrer na borda de descida [FALLING], subida [RISING] ou em ambos [BOTH]. Adiciona uma função para ser chamada e aceita parâmetro de tempo debounce;
  • RPi.GPIO.remove_event_detect() => Permite remover um evento em qualquer parte do código se não for mais utilizado.

 

A Figura 1 ilustra os comportamentos que ocorrerão no decorrer do artigo ao acionar o pushbutton.

 

LOWtoHIGH_with_bouncing_PortalEmbarcados
Figura 1 - Detalhes sobre a mudança do nível lógico com chaves mecânicas

 

 

Olhando a Figura 1, fica fácil entender os parâmetros LOW (representado por 0V), HIGH (como 3.3V), Edge Rising ou RISING (transição de 0V a 3.3V), Edge Falling ou FALLING (transição de 3.3V a 0V) e o efeito bouncing. Esse último, se você não conhece, pode ver o artigo Leitura de chaves mecânicas e o processo de debounce, escrito pelo Rodrigo Almedia, indicando como contornar o problema via hardware e software, e neste artigo iremos estudar a solução via software.

 

 

PushButton com pull-down interno

 

EsquematicoRaspberryPIPushButtonPullDownInterno
Figura 2 - Esquema de ligação do PushButton em pull-down interno

 

 

O primeiro exemplo prático será adicionar um pushbutton. Uma de suas extremidades será conectada ao 3.3V (pino 1) e a outra ao pino 16 (ou GPIO 23) da Raspberry Pi no modo BCM, como na Figura 2. Configuraremos via software utilizando RPi.GPIO o pino 16 (GPIO 23) no modo INPUT e com pull-down interno.

 

Código:

 

Executando o código:

 

 

PushButton com pull-up interno

 

EsquematicoRaspberryPIPushButtonPullUpInterno
Figura 3 - Esquema de ligação do PushButton em pull-up interno

 

 

No segundo exemplo prático o mesmo PushButton será utilizado, trocando apenas a extremidade de 3.3V (pino 1) para 0V GND (pino 6), como na Figura 3. Configuraremos via software utilizando RPi.GPIO o pino 16 (GPIO 23) no modo INPUT e com pull-up interno.

 

Código:

 

O nosso código acima é praticamente o mesmo do exemplo anterior com algumas alterações como: o setup() do GPIO 23 como pull-up; o teste que verifica o estado do pino faz uso da constante gpio.LOW, que poderia ser 0, seguindo a analogia do exemplo anterior; o botão, quando pressionado, faz o programa parar.

 

Executando o código:

 

 

PushButton com  pull-down externo

 

EsquematicoRaspberryPIPushButtonPullDownExterno
Figura 4 - Esquema de ligação do PushButton em pull-down externo

 

 

O próximo exemplo é utilizando resistores externos para configurar como pull-up ou pull-down e, como na Figura 4, vamos utilizar 2 resistores: um de 1k e outro de 10k. A configuração que foi utilizada é o resistor de 1k entre o GPIO e o PushButton e o 10k entre GPIO e o GND, caracterizando ser pull-down.

 

Código:

 

Executando o código:

 

 

PushButton com pull-up externo

 

EsquematicoRaspberryPIPushButtonPullUpExterno
Figura 5 - Esquema de ligação do PushButton em pull-up externo

 

 

O esquema final da Figura 5, praticamente o mesmo que o anterior, apenas com a alteração do resistor 10k que é entre VCC (3.3V) com GPIO e o PushButton agora é entre o pino do GPIO e o GND, caracterizando ser pull-up. A mesma ideia deve-se seguir no código.

 

Código:

 

Executando o código:

 

Não errei o código não, é que utilizando resistores externos altera-se apenas a linha do if de gpio.HIGH para gpio.LOW. No caso ainda dei uma valorizada, onde troquei gpio.LOW por 0.

 

 

Eventos e Interrupções

 

Os exemplos utilizados até agora foram legais e interessantes, porém na prática sabemos que é um pouco inconveniente aguardar o loop ou, como no exemplo que fizemos, utilizarmos um delay de 1s. Em alguns casos isso é um absurdo e pode ser que a ação de pressionar o botão não seja capturada, sendo uma falha grave e que pode ser facilmente contornada com as funções de "detecção de eventos" event_detect do RPi.GPIO, que tem uma grande relação com Edge Rising (Borda de Subida), Edge Falling (Borda de Descida) ou Both (Ambos sentidos). Utilizaremos o esquemático da Figura 2 por ser mais simples de montar, o PushButton com pull-down e vamos ao código.

 

Código:

 

Executando o código:

 

Você pode testar, e pode ver que independente do momento que pressionar o pushbutton, na ação dele ser pressionado (RISING), indo de 0V para 3.3V, como estamos com pull-down, ele irá “guardar” esta mudança de estado. Na próxima vez que for executado o loop, este evento será tratado, no nosso caso sendo chamada a função action_press_button() e saindo do programa.

 

E se por acaso quiséssemos que a ação ocorresse ao soltar o pushbutton e não ao pressionar o mesmo?

 

Código:

 

Executando o código:

 

Não mudou nada na saída do código, tirando que o programa só parou quando pressionamos e soltamos o PushButton. Enquanto o botão estiver pressionado, nada acontece. O mesmo pode ser feito com BOTH, que a ação ocorrerá ao pressionar e soltar.

Outra opção interessante no event_detect() é poder adicionar uma função a ser chamada assim que ocorrer a mudança de estado, utilizando o parâmetro callback. Seria a correspondência de uma "Interrupção", porém eu não gosto muito deste termo e prefiro aceitar o de uma chamada em paralelo ou execução já que uma segunda thread é disparada neste caso. Vamos ver!

 

Código:

 

Executando o código:

 

Usando callback no add_event_detect(), podemos ver que existem “prioridades” na chamada, porque assim que o evento ocorre é lançada uma segunda thread para a chamada. Após isso vem a continuação do loop e depois é atendida nossa mudança de estado no próprio loop como antes. Assim conseguimos prioridade no tratamento de input independente do tamanho e tempo de nosso loop, caracterizando a interrupção dita. Comentando sobre a opção de utilizar o debounce via software, como na linha 30, com ou sem o callback, podemos definir o parâmetro bouncetime, que é um valor de tempo em ms para ser ignorado na detecção da borda.

 

A função remove_event_detect(), pode ser chamada e passado como parâmetro o pino. A qualquer momento o evento sobre o mesmo pino passa a não ser mais válido e você pode remover a ação sobre a borda naquele pino. Vamos ver no próximo código.

 

Código:

 

Executando o código:

 

E por último o wait_for_edge(), que podemos parar a execução do programa até que a mudança no pino ocorra, também sendo válido para a mudança RISING, FALLING ou BOTH.

 

Código:

 

Executando o código:

 

 

Conclusão

 

Podemos ver mais uma vez como Python é uma ferramenta fantástica para prototipagem. Com poucas linhas e utilizando o RPi.GPIO conseguimos manipular de diversas maneiras o GPIO do Raspberry Pi no modo input.

 

 

O que vem por aí?

 

No próximo artigo vamos continuar brincando com o GPIO do Raspberry Pi, só que desta vez partindo para PWM.

 

Outros artigos da série

<< Raspberry PI - GPIO output com PythonRaspberry PI - PWM com Python >>
Proprietário da B2Open onde oferecemos consultoria, treinamentos e desenvolvimento em Sistemas Embarcados. Entusiasta a filosofia open-source, mais de 10 anos de experiências em Linux e FOSS. Em sistemas embarcado do firmware baremetal ao Linux Embedded, e há aproximadamente 8 anos desenvolvendo em (C, Python, Qt e muito Shell Script), além de profiling, hardening e tuning para targets com Linux Embarcado. Graduado em Engenharia da Computação pela UNICEP com ênfase em robótica e sistemas embarcados.

Deixe um comentário

15 Comentários em "Raspberry PI – GPIO input com Python"

Notificar
avatar
 
Ordenar por:   recentes | antigos | mais votados
Emerson Alves
Visitante
Emerson Alves

Olá Cleiton,

Você pode me tirar uma dúvida? Qual a função do "break" dentro do if?

"while True:
if gpio.input(23) == gpio.LOW:
print(“Botão acionado”)
break
else:
printf(“Botão desligado”)"

Muito obrigado!

Emerson Alves
Visitante
Emerson Alves

Olá Cleiton.

Apenas gostaria de agradecer pela brilhante explicação sobre os programas para Raspberry, você conseguiu tirar bastantes dúvidas minhas. Meu próximo passo, assim como o Roniere, é integrar o display de LCD com o controlador.

Muito obrigado! Abraços.

Roniere Rezende
Visitante
Roniere Rezende

Emerson, eu já consegui colocar para funcionar o LCD caso tenha alguma dúvida pode me procurar nas redes sociais que te ajudo.
Abraço!

Emerson Alves
Visitante
Emerson Alves

Sua ajuda seria muito bem vinda Roniere. Estou trabalhando no projeto de TCC e isso vai alavancar uma boa parte do trabalho.

Roniere Rezende
Visitante
Roniere Rezende

Olá Cleiton Bueno, o seu artigo está muito bom e atendeu meus objetivos de entender como utilizar as GPIOs como entrada. Mas pesquisei aqui sobre o seu próximo artigo sobre PWM e não o encontrei. Houve sequência nos seus artigos? Abraço!

trackback
RaspsberryPI - Lento teclado matricial 4x4 com Python

[…] e, para isto, instalamos um módulo chamado RPi.GPIO, que pode ser conferido na primeira parte [1] sobre input e na segunda parte [2] sobre […]

trackback
O que pedir pro papai noel?

[…] Raspberry Pi – GPIO input com Python [12], escrito por Cleiton […]

trackback
Raspberry Pi A+

[…] PI – GPIO input com Python [18], escrito por Cleiton […]

wpDiscuz