ESP32

ISR – Interrupções e timer com ESP32

ESP32 | Do bit Ao Byte | MicroPython no ESP32 | Processamento paralelo com ESP32 | Selecionar uma CPU | mutex no freertos | tasks no esp32 | FreeRTOS com ESP32 | timer com ESP32 | partições no ESP32

Interrupções e timers são os recursos que mais gosto de utilizar, seja em MCU ou CPU. Mas nem todos os makers tem habilidade com esses recursos, às vezes por não se incomodar em gastar recursos, às vezes por não compreender onde cabe o recurso. Por essa razão, vou escrever brevemente a respeito.

Se você procura por interrupção e timer com Arduino, sugiro esse artigo. Caso deseje fazê-lo com PIC, tenho esse artigo, esse outro, esse sobre timer, esse sobre Interrupt On Change. Claro que não poderia deixar de escrever a respeito para o Raspberry Pi, como você vê nesse artigo.

Material necessário



Para esse tutorial tudo o que você precisa é de um ESP32. Repare que já escrevi uns 10 artigos consecutivos sobre ESP32 e acredito que seja material suficiente para convencê-lo do poder desse monstrinho. Se ainda não tem um, sugiro que pegue o seu na CurtoCircuito.

Timer com ESP32

Suponhamos que você deseja executar uma rotina em intervalos específicos de tempo. Como se trata de ESP32, é simples criar uma task e colocá-la em suspend através do delay. Mas existem 2 tipos de timer; por software e por hardware. Se tratando de software, já basta uma task como citado. Por hardware, podemos utilizar o seguinte exemplo:

Repare que a função stopTimer foi criada apenas para demonstrar como interagir externamente com o timer, porque se você realmente quiser um single-shot, basta passar false no timerAttachInterrupt e ainda, se precisar mais de um ciclo, basta fazer um loop dentro da função cb_timer.

Interrupção com ESP32

Tem duas maneiras de verificar a ocorrência de um evento. A menos eficiente é fazendo polling. Além de o evento não ser pego no exato momento em que ocorreu, processamento é disperdiçado apenas para rodar um código que analisará se houve o evento. Assim como o timer, existe a interrupção por software e a interrupção por hardware. A interrupção por hardware acontece a partir de um evento externo, por exemplo, em um pino de GPIO.

Uma interrupção pode gerar o gatilho na borda alta ou na borda baixa do pino. para rising edge, quando o pino sai do estado lógico 0 para 1, temos o GPIO_INTR_POSEDGE. Já para falling edge, quando o pino sai do estado 1 para o estado 0, utilizamos o GPIO_NEGEDGE. Repare que a porção POS é para POSITIVE e a porção NEG é para NEGATIVE. Assim fica fácil decorar.

Para configurar um pino de interrupção, usa-se:

Os parâmetros são o pino de interrupção e o tipo de interrupção. Fácil ou não? – Não tanto quanto bom seria. No ESP32 você tem até 32 slots de interrupção para cada núcleo (!), com diferentes prioridades. Você vai conseguir criar uma interrupção sim, através desse artigo, sem sofrimentos. Mas na hora de programar um projeto, pode começar a complicar a coisa quando tiver que gerenciar interrupções, filas, núcleos e tasks. Por outro lado, é mais poder do que você normalmente usa em um desktop. É simplesmente delicioso!

Primeiro passo

Você deve instalar o servio que gerencia as interrupções para os pinos de GPIO:

Segundo passo

A partir daí você pode especificar para cada pino em qual núcleo sua ISR (Interrupt Service Routine) será executado. Lembre-se que cada núcleo tem 32 canais de interrupção. Além disso, você pode passar parâmetros para a função, o que dá ainda mais flexibilidade de uso:

Os parâmetros são o pinoa ISR (função para a interrupção), e um array de argumentos.

As interrupções bloqueiam o fluxo principal do programa, portanto faça com que sua interação seja a mais breve possível. Normalmente eu crio uma flag no fluxo principal e quando ocorre uma interrupção, mudo o valor dessa flag. Como estamos falando de ESP32, essa não seria a melhor forma de tratar interrupções, mas dependendo do que tem na task principal, não seria nada mal implementar dessa maneira. Mas você pode criar uma tarefa dedicada a atender a interrupção!

Terceiro passo

Vamos criar uma tarefa dedicada, oras. Mas para isso, precisamos ter um controle para que não sejam executadas múltiplas instâncias dessa tarefa. Nesse outro artigo vimos a respeito do mutex. Dessa vez vamos utilizar um semáforo binário.

Vamos criar uma ISR para um botão:

Se você leu o artigo sobre mutex, já deve ter imaginado que essa função apenas libera o semáforo. Desse modo, uma tarefa pode tomá-lo e seguir com sua execução.

A tarefa que nos dará feedback seria algo como:

Essa tarefa ficaria em um loop infinito, então um single-shot viria bem a calhar. O que seria melhor, um timer com single-shot ou uma task com vTaskDelete(NULL)?

O código de exemplo do timer está completo, em breve iniciaremos algumas brincadeiras práticas, como esse artigo para mostrar audio e visualmente o funcionamento da multitask. Acompanhe!

Inscreva-se no nosso newsletter, alí em cima à direita e receba novos posts por email.

Siga-nos no Do bit Ao Byte no Facebook.

Prefere twitter? @DobitAoByte.

Inscreva-se no nosso canal Do bit Ao Byte Brasil no YouTube.

Nossos grupos:

Arduino BR – https://www.facebook.com/groups/microcontroladorarduinobr/
Raspberry Pi BR – https://www.facebook.com/groups/raspberrybr/
Orange Pi BR – https://www.facebook.com/groups/OrangePiBR/
Odroid BR – https://www.facebook.com/groups/odroidBR/
Sistemas Embarcados BR – https://www.facebook.com/groups/SistemasEmbarcadosBR/
MIPS BR – https://www.facebook.com/groups/MIPSBR/
Do Bit ao Byte – https://www.facebook.com/groups/dobitaobyte/

Próximo post a caminho!