ESP32

Tratar interrupções na UART com ESP32

interrupções na uart

Anteriormente, escrevi um artigo mostrando como utilizar a UART do ESP32 para não utilizar mais o recurso Serial do Arduino. Esse artigo é um complemento, para mostrar o tratamento de interrupções na UART com ESP32 invés de ficar fazendo polling em um loop.

Recursos: Queue

No menu ESP32 você vai encontrar detalhes da utilização de diversos recursos, como semáforo e mutex (que também é um tipo de semáforo). Já discorri sobre filas também e para tratar as interrupções da UART, a utilização de queue é o recurso ideal, porque não queremos perder nada do que ocorrer e eventos podem ocorrer em sequência. Colocando-os em uma fila, trataremos todos na ordem que chegarem.

Interrupções na uart – UART a utilizar



Como explicado no artigo mencionado no primeiro parágrafo, temos diversas UARTs no ESP32 e vamos utilizar a UART0, que é a equivalente à Serial padrão utilizada na IDE do Arduino. No código você encontrará um define indicando-a:

Também precisamos definir o tamanho do buffer. Normalmente, 1024 Bytes, mas vamos fazer um buffer minúsculo aqui:

Precisaremos criar uma queue para enfileirar os evetos da UART:

Task

Escrevi diversos artigos relacionados à task no ESP32. A task é o equivalente a uma thread, que roda de forma assíncrona. Além disso, o ESP32 nos dá o poder de selecionar o núcleo que essa task deve rodar, podendo ser o núcleo 0 (que está sempre livre) ou o núcleo 1 (que é o núcleo utilzado pela IDE do Arduino para rodar a função loop() setup() ). Além disso, podemos definir a prioridade das tarefas; uma prioridade inferior só permitirá a execução da task quando o núcleo em que ela será executada esteja livre para sua execução. Uma prioridade superior prioriza sua execução sobre qualquer outra tarefa. Uma prioridade idêntica fará execução paralela das tarefas em round-robin.

Sugiro que leia os artigos relacionados às tasks para ver os detalhes. Para a execução da tarefa de gerenciamento da UART, definimos previamente uma função. Essa função tratará os tipos de eventos que ocorrerem na UART. No código abaixo deixei comentado o máximo que pude para tentar tornas mais claras as atuações.

setup()

Não era o pretendido, mas ainda estou escrevendo artigos utilizando a IDE do Arduino. Desse modo, ainda precisamos respeitar uma determinada ordem no código. Primeiramente, a configuração da UART (explicada nesse artigo):

Não se incomode com essa estrutura. Como ela será um padrão, você pode simplesmente guardá-la em algum sketch para quando precisar configurar a UART do ESP32.

O segundo passo é executar a configuração da UART:

Daí definimos os pinos da UART e instalamos o driver. As UARTs já tem uma configuração inicial de seus pinos padrão, de modo que não precisamos fazer nada além de passar como parâmetros os valores UART_PIN_NO_CHANGE.

Aqui já é diferente da configuração básica da UART, pois está relacionado à ISR:

Agora criamos uma tarefa para manipular evento da UART via ISR. Podemos fazer isso de diversos modos, escolhendo o núcleo a executar, por exemplo. Se chamarmos a função como abaixo, ela será executada no núcleo 1, onde estará a função loop() da IDE do Arduino. A função loop() é ininterrupta, mas a prioridade dessa task é maior. Desse modo, sempre que ocorrer um evento na UART, seu tratamento será priorizado:

Globalmente (lá no header do arquivo, fora do setup) reservamos um buffer para tratamento dos dados entrantes:

loop()

Na função loop() fazemos a leitura e simplesmente imprimimos o dado de volta, quando houver:

Wemos ESP32 com OLED onboard

Fica mais legal jogar alguma informação em um display do que simplesmente na UART, hum? Para isso, vamos utilizar o ESP32 com OLED onboard que você encontra na CurtoCircuito.

Já mostrei no artigo anterior a esse como utilizá-lo, agora daremos a ele essa divertida aplicação. Invés de detalhar por partes, vou incluir abaixo o código completo, basta fazer a modificação da biblioteca do display como mostrado no artigo supracitado e subir esse código pela IDE do Arduino:

Repare que nesse código deixei uma variável para utilizar com strcpy, para imprimir todo o texto diretamente no momento do evento, mas não quis implementar agora porque é necessário saber se a variável foi alimentada (o que só ocorre depois do evento) e precisa colocar um mutex pra controlar o acesso à variável, daí eu iria deixar o código maior. Invés disso, preferi algo ineficiente, que é a utilização de delay no loop, mas serve muito bem para exemplificar o tipo de evento e os dados de entrada. E já que utilizei delay, deixei a função que limpa o display também no loop. Não é nada bonito esparramar um controle específico, mas outra vez, é apenas para exemplificar.

Para testar outro tipo de evento que não seja UART_DATA, troque case UART_DATA por 12345. Como esse valor não casa com nenhuma macro, esse switch irá cair diretamente no default, que é “erro desconhecido” e isso mudará a mensagem do evento no display. Já na linha de baixo, como não tem erro e o loop analisa por dado entrante na UART, o que for digitado na serial sempre será exibido.

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!