Raspberry PI – GPIO input com Python

modo Input

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.

 

modo Input
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

 

modo Input
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

 

modo Input
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

 

modo Input
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

 

modo Input
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 >>

NEWSLETTER

Receba os melhores conteúdos sobre sistemas eletrônicos embarcados, dicas, tutoriais e promoções.

Obrigado! Sua inscrição foi um sucesso.

Ops, algo deu errado. Por favor tente novamente.

Cleiton Bueno
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.

17
Deixe um comentário

avatar
 
7 Comment threads
10 Thread replies
1 Followers
 
Most reacted comment
Hottest comment thread
5 Comment authors
JonathanEmerson AlvesRoniere RezendeCleiton BuenoRoniere Rezende Recent comment authors
  Notificações  
recentes antigos mais votados
Notificar
Jonathan
Visitante
Jonathan

Os códigos de interrupção realmente funcionam? Testei no raspberry pi 3 e apenas fica retornando polling mesmo clicando no botão.

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!

Roniere Rezende
Membro
Roniere Rezende

Cleiton, esses dias eu fiz dois códigos usando o controle PWM. Um usando dois leds, um aumentava a sua luminosidade ao mesmo tempo que o outro iria diminuindo quando chegava nos seus limites retornavam ao estado inicia.O outro, eu controlava o duty cycle usando dois botões, um para aumenta e outro para dimunuir. Ficaram bem simples e interessantes para usuários iniciantes como eu. Se quiser, posso te envio os códigos e você faz o artigo em cima deles. Ou gostaria de sugerir, um artigo falando como usar display LCD na Raspberry, é isso que estou estudando como fazer agora. Abraço!

Roniere Rezende
Visitante
Roniere Rezende

Podemos pensar nisso Cleiton. Mas podemos conversar mais reservadamente sobre isso, pode me passar alguma forma de contatar você?

Roniere Rezende
Visitante
Roniere Rezende

Cleiton, como podemos iniciar os trabalhos. Estou no seu aguardo!

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 […]