ESP32 - Interrupção GPIO

Neste tutorial, vamos aprender a usar as interrupções GPIO no ESP32. As interrupções GPIO do ESP32 permitem tratar eventos externos de forma rápida e eficiente, sendo essenciais para aplicações em tempo real em IoT e sistemas embarcados. Ao entender e configurar bem essas interrupções, você pode criar projetos robustos e responsivos, que reagem imediatamente ao ambiente.

ESP32 Interrupção GPIO

O que é uma Interrupção GPIO?

Uma interrupção GPIO é um sinal que faz o processador parar a execução atual e saltar para um trecho de código específico, conhecido como rotina de serviço de interrupção (ISR). Isso permite que o ESP32 trate tarefas de alta prioridade imediatamente, sem precisar verificar continuamente (polling) os pinos GPIO.

Interrupções no ESP32

O ESP32 oferece suporte a vários tipos de interrupções GPIO:

  • Rising Edge (borda de subida): Disparada quando o pino GPIO passa de LOW para HIGH.
  • Falling Edge (borda de descida): Disparada quando o pino GPIO passa de HIGH para LOW.
  • Both Edge (ambas as bordas): Disparada em qualquer mudança de estado, de LOW para HIGH ou de HIGH para LOW.
  • Level Low (nível baixo): Disparada quando o pino GPIO permanece em LOW.
  • Level High (nível alto): Disparada quando o pino GPIO permanece em HIGH.

Como configurar Interrupções GPIO no ESP32

Para configurar uma interrupção GPIO no ESP32, siga estes passos:

Inicialize o GPIO: Defina o modo do pino GPIO como entrada ou saída, conforme necessário. Por exemplo:

pinMode(GPIO_Pin, INPUT_PULLUP);

Anexe a Interrupção: Use a função attachInterrupt() para ligar o pino GPIO a uma ISR.

attachInterrupt(GPIO_Pin, ISR_function, mode);

Essa função aceita três argumentos:

  • GPIO_Pin: Especifica o pino GPIO que será usado como pino de interrupção, indicando qual pino o ESP32 deve monitorar.
  • ISR_function: O nome da função que será chamada sempre que a interrupção ocorrer.
  • mode: Define a condição que dispara a interrupção. Existem cinco constantes predefinidas que podem ser usadas:
    • RISING: Dispara quando o pino passa de LOW para HIGH (na Rising Edge).
    • FALLING: Dispara quando o pino passa de HIGH para LOW (na Falling Edge).
    • CHANGE: Dispara em qualquer mudança no estado do pino (em Both Edge).
    • HIGH: Dispara quando o pino está em HIGH (em Level High).
    • LOW: Dispara quando o pino está em LOW (em Level Low).

    Defina a função ISR: Escreva a rotina de serviço de interrupção que será executada quando a interrupção for disparada.

    A rotina de serviço de interrupção (ISR) é uma função chamada toda vez que ocorre uma interrupção no pino GPIO. A sintaxe dela é como abaixo.

    void IRAM_ATTR ISR_function() { Statements; }

    Vamos ver um exemplo prático de uso de interrupções com um pino GPIO do ESP32 conectado a um botão.

Diagrama de Ligação

ESP32 Botão Diagrama de Ligação

This image is created using Fritzing. Click to enlarge image

Se você não sabe como alimentar o ESP32 e outros componentes, veja as instruções no tutorial a seguir: Como alimentar o ESP32.

Código de Interrupções do ESP32

#define BUTTON_PIN 21 // The ESP32 pin GPIO21 connected to the button void IRAM_ATTR handleButtonPress(); void setup() { Serial.begin(9600); // Initialize the GPIO pin as an input pinMode(BUTTON_PIN, INPUT_PULLUP); // Attach interrupt to the GPIO pin attachInterrupt(digitalPinToInterrupt(BUTTON_PIN), handleButtonPress, FALLING); } void loop() { // Main code here } // Interrupt Service Routine (ISR) void IRAM_ATTR handleButtonPress() { Serial.println("Button pressed!"); }

Neste exemplo:

  • O BUTTON_PIN é definido como GPIO21.
  • A função pinMode() configura o pino GPIO como entrada com resistor de pull-up interno.
  • A função attachInterrupt() anexa a ISR handleButtonPress ao BUTTON_PIN, configurada para disparar em uma borda de descida.
  • A função handleButtonPress é a ISR que é executada quando o botão é pressionado.

O código acima mostra como é um código de interrupção, mas pode não funcionar na prática, porque usa a função Serial.println(), que leva mais tempo para ser processada do que o permitido em uma rotina de serviço de interrupção.

Para testar como as interrupções funcionam, veja o exemplo de código prático abaixo:

#define BUTTON_PIN 21 // The ESP32 pin GPIO21 connected to the button volatile bool buttonPressed = false; // use volatile for variable that is accessed from inside and outside ISR void IRAM_ATTR handleButtonPress(); void setup() { Serial.begin(9600); // Initialize the GPIO pin as an input pinMode(BUTTON_PIN, INPUT_PULLUP); // Attach interrupt to the GPIO pin attachInterrupt(digitalPinToInterrupt(BUTTON_PIN), handleButtonPress, FALLING); } void loop() { // Main code here if (buttonPressed) { Serial.println("Button pressed!"); buttonPressed = false; // Reset the flag } // Other code here } // Interrupt Service Routine (ISR) void IRAM_ATTR handleButtonPress() { // Serial.println("Button pressed!"); // do NOT use function that takes long time to execute buttonPressed = true; }

Passos Rápidos

  • Se esta é a primeira vez que você usa o ESP32, veja como configurar o ambiente do ESP32 no Arduino IDE.
  • Faça a ligação como na imagem acima.
  • Conecte a placa ESP32 ao seu PC com um cabo micro USB
  • Abra o Arduino IDE no seu PC.
  • Selecione a placa ESP32 correta (por exemplo, ESP32 Dev Module) e a porta COM.
  • Copie o código acima e abra no Arduino IDE
  • Clique no botão Upload do Arduino IDE para fazer upload do código para o ESP32
  • Pressione o botão várias vezes
  • Confira o resultado no Serial Monitor
∞
Newbiely | Arduino IDE 2.3.8
──
☐
✕
File
Edit
Sketch
Tools
Help
ESP32 Dev Module
Newbiely.ino
···
8 Serial.println("Hello World!");
Output
Serial Monitor
Message (Enter to send message to 'ESP32 Dev Module' on 'COM15')
New Line
9600 baud
Button pressed! Button pressed! Button pressed! Button pressed!
Ln 11, Col 1
ESP32 Dev Module on COM15
2

Você pode notar que um único aperto do botão resulta em vários eventos de pressionamento exibidos no Serial Monitor. Isso não é um problema da interrupção, e sim do próprio botão. Para aprender como resolver isso, consulte o tutorial ESP32 - Botão - Debounce.

Você pode ver outro exemplo que usa interrupções neste tutorial ESP32 - Encoder Rotativo.

Considerações Importantes

  • Sem Parâmetros ou Valores de Retorno: Uma função ISR não pode ter parâmetros e não deve retornar nada.
  • Tempo de Execução da ISR: Mantenha o código da ISR o mais curto e eficiente possível. ISRs longas podem fazer o sistema perder outras interrupções ou reduzir o desempenho geral.
  • Concorrência: Tenha cuidado com recursos compartilhados acessados dentro das ISRs. Use operações atômicas ou desative as interrupções, se necessário, para evitar condições de corrida. Em especial, use a palavra-chave volatile para variáveis acessadas tanto dentro quanto fora da função ISR.
  • IRAM_ATTR: Coloque o código da ISR na IRAM usando o atributo IRAM_ATTR para garantir que ela execute rapidamente, sem buscar na memória flash.

Vídeo

Tutoriais Relacionados

※ NOSSAS MENSAGENS

  • Fique à vontade para compartilhar o link deste tutorial. Porém, por favor, não use nosso conteúdo em outros sites. Investimos muito esforço e tempo para criar este conteúdo, por favor respeite nosso trabalho!