Blog
Como Usar o ESP32 Dual Core com o Arduino IDE
A maioria dos projetos que utilizam microcontroladores começa de forma muito básica, lendo sensores, ligando e desligando LEDs ou transmitindo dados via serial. Com o aumento do tamanho dos projetos, no entanto, atividades de sobrecarga, como comunicações sem fio, detecção em tempo real, interfaces de usuário e processamento de dados, começam a competir pelo tempo da CPU. Aqui, a arquitetura dual-core do ESP32 representa um enorme benefício.
O ESP32 possui dois núcleos de processamento independentes (comparado aos microcontroladores comuns de núcleo único), permitindo que duas tarefas sejam executadas simultaneamente. Isso deve permitir aos desenvolvedores criar sistemas mais responsivos, estáveis e escaláveis sem a necessidade de mudar para uma cadeia de ferramentas completamente nova, quando utilizado corretamente no ambiente Arduino.
Este artigo discute o dual core do ESP32 sob o Arduino IDE e dedica atenção especial a insights práticos, planos de implementação do mundo real e armadilhas, sem transformar o tópico em um manual de códigos de baixo nível do RTOS.
Compreendendo a Arquitetura Dual Core do ESP32
O ESP32 possui dois núcleos de processador Tensilica independentes, porém compartilháveis, com memória e periféricos. O sistema tem gerenciamento interno de multitarefa, escalonamento e coordenação entre núcleos utilizando o FreeRTOS.
Na maioria das configurações do ESP32:
- O Core 0 lida primariamente com operações de nível de sistema, como Wi-Fi, Bluetooth e serviços em segundo plano.
- O Core 1 é tipicamente utilizado para a lógica de aplicação do usuário.
Com o framework Arduino aplicado ao ESP32, grande parte dessa complexidade é removida. As funções padrão `setup` e `loop` já são utilizadas como parte das tarefas do FreeRTOS. Não obstante, os desenvolvedores podem adicionar mais tarefas e fixá-las a um núcleo particular quando for necessário ter um controle de ajuste fino.
Quando (e quando não) usar Dual Core
O processamento dual-core é poderoso, mas não é sempre necessário. Compreender quando utilizá-lo ajuda a evitar complexidade desnecessária.
Casos de uso adequados incluem:
- Execução da aquisição de sensores independentemente da comunicação Wi-Fi
- Gerenciamento de controle em tempo real durante a atualização de um visor
- Separar tarefas críticas de tempo do registro em plano de fundo
- Melhorando a responsividade em aplicações de IoT
Casos em que um processador dual-core pode não ser necessário:
- Projetos simples de leitura de sensores
- Registro de dados de baixa frequência
- Aplicações com restrições de tempo mínimas
O uso de dual-core deve ser uma decisão de design, não uma escolha padrão. O uso excessivo pode introduzir problemas de sincronização que não existem em projetos de loop único.
Configurando o ESP32 Dual Core na Arduino IDE
Primeiramente, é necessário instalar o pacote de placa ESP32 no ambiente Arduino. O ESP32 é compatível com o Arduino, pois o usuário pode utilizá-lo de maneira semelhante a uma placa Arduino.
O Arduino IDE é um programa que é automaticamente executado no ESP32 com o sistema FreeRTOS. O suporte a dual-core não necessita de nenhuma configuração especial para ser ativado.
Considerações importantes de configuração incluem:
- Seleção da variante correta de placa ESP32
- Utilizando as configurações padrão de flash e partição, a menos que o uso avançado de memória seja necessário
- Habilitando a saída serial para depuração precoce
Nesta fase, o sistema já é capaz de realizar multitarefas, mesmo que o esboço pareça simples.
Tarefas, Núcleos e o Loop do Arduino
No sketch clássico do Arduino, toda a lógica é executada dentro de loop(). E no ESP32, loop em si é uma tarefa FreeRTOS que está vinculada a um núcleo.
Para utilizar a capacidade de duplo núcleo, os desenvolvedores desenvolvem mais tarefas que:
- Executar independentemente do loop()
- Pode ser atribuído ao Core 0 ou ao Core 1
- Operar em diferentes prioridades
Existe uma pilha e um contexto de execução para cada tarefa, e é possível utilizá-los de forma verdadeiramente paralela. Agora é possível executar leituras de sensores continuamente enquanto comunicações ou atualizações de interface de usuário são executadas sem bloqueio.
Implementação de Tarefa Dual Core Passo a Passo (Exemplo DIY)
Como exemplo de prática de uso, pode-se utilizar um projeto DIY com ESP32 que possibilita a leitura de sensores e a transmissão de dados via rede Wi-Fi.
Definindo Tarefas Independentes
A aplicação é dividida em responsabilidades lógicas:
- Tarefa A: Lê dados do sensor em intervalos fixos
- Tarefa B: Gerencia a comunicação Wi-Fi e a transmissão de dados
Este isolamento impede que operações de rede lentas interrompam a sensoriamento sensível ao tempo.
Atribuindo Tarefas a Núcleos Específicos
A leitura do sensor normalmente é alocada no Core 1, enquanto a comunicação pode ser alocada no Core 0 ou no Core 1, dependendo da carga de trabalho do sistema. A seleção do tamanho da pilha e da prioridade é realizada para evitar falhas ou inanição.
Tal estratégia torna o sistema responsivo mesmo quando há um tráfego de comunicação significativo.
Gerenciando Recursos Compartilhados Entre Núcleos
A capacidade de utilizar recursos compartilhados de forma segura é um dos aspectos mais cruciais na programação de sistemas com múltiplos núcleos. Como ambos os núcleos têm permissão de acesso à memória, um design irresponsável pode resultar em comportamento imprevisível.
As considerações principais incluem:
- Protegendo variáveis compartilhadas
- Evitando acesso simultâneo a periféricos de hardware
- Gerenciando a saída serial para prevenir corrupção de mensagens
Condições de corrida podem ser removidas e a consistência dos dados pode ser garantida sem sobrecarga excessiva usando métodos simples de sincronização.
Problemas Comuns em Dual Core e Dicas de Depuração
Desenvolvedores iniciantes em projetos ESP32 dual-core frequentemente encontram problemas semelhantes:
- Reinicializações aleatórias causadas por tamanho de pilha insuficiente
- O watchdog timer é acionado devido a código bloqueante
- Tarefas com prioridades incorretas estão impedindo o avanço de outras
- Instabilidade de energia durante a transmissão Wi-Fi
Estas questões são isoladas com a ajuda de depuração sistemática. O registro serial, o isolamento de tarefas e os testes incrementais podem ser particularmente bem-sucedidos com múltiplos núcleos.
Otimização de Desempenho Melhores Práticas
Para obter o máximo benefício do dual core do ESP32:
- Atribua tarefas críticas de tempo ao seu próprio núcleo
- Evite longos atrasos de bloqueio
- Utilize multitarefa em vez de interrupções quando apropriado
- Monitore o consumo de energia sob carga
O uso do dual core também deve aprimorar a responsividade, em vez de apenas adicionar complexidade.
Estratégia de Testes e Validação
Sistemas dual-core devem ser testados além da funcionalidade básica. A validação inclui:
- Testes de longa duração de tempo de execução
- Teste de estresse com tráfego contínuo de Wi-Fi
- Medição da precisão do tempo do sensor
- Verificando a recuperação do sistema após interrupções na rede
Estes testes confirmam que as tarefas permanecem estáveis e sincronizadas ao longo do tempo.
Considerações ao Migrar para o Design de Placas de Circuito Impresso
No caso de um projeto ESP32 dual-coreMigrando para uma placa de circuito impresso (PCB), o design de hardware é diretamente impactado por decisões de firmware. O multitarefa deve ser considerado em termos de alocação dos GPIOs, roteamento de energia e acesso à depuração.
As considerações importantes da placa de circuito impresso (PCI) incluem:
- Projeto de Fonte de Alimentação Estável
- Desacoplamento adequado próximo ao ESP32
- Pontos de teste para depuração
- Separação clara de sinais sensíveis
Os aplicativos de núcleo duplo são mais propensos a exigir a integridade de potência e, portanto, a qualidade da PCB é muito significativa para eles.
Considerações Finais
A utilização bem-sucedida do dual core do ESP32 no ambiente Arduino permite que os desenvolvedores criem sistemas embarcados mais confiáveis, responsivos e escaláveis. Com o conhecimento do escalonamento de tarefas para os núcleos, os recursos compartilhados podem ser utilizados de forma eficiente, e testes rigorosos podem garantir que o processamento dual-core não seja uma ferramenta complexa.
O suporte dual-core do ESP32, disponível para usuários Arduino dispostos a sair de designs de loop único e migrar para designs mais potentes e capazes, representa um próximo passo eficaz com a organização correta do firmware e bons comportamentos de design de PCB.
Perguntas Frequentes (FAQ)
Sim. O loop do Arduino já é executado como uma tarefa FreeRTOS, portanto, multitarefa em um único núcleo é possível. O dual-core permite simplesmente um melhor isolamento de tarefas críticas em termos de tempo e de tarefas de segundo plano.
Utilize a função xTaskCreatePinnedToCore(). Ela permite fixar uma tarefa FreeRTOS na Core 0 ou na Core 1, controlando a localidade de execução e evitando contendas desnecessárias.
Executar tarefas de forma concorrente pode consumir mais energia, mas um design cuidadoso com modos de suspensão, loops eficientes e priorização de tarefas mantém o consumo gerenciável.
Utilize logging serial, mutexes e notificações de tarefa para rastrear a execução das tarefas. Evite conflitos de recursos compartilhados e teste uma tarefa de cada vez antes de combiná-las.
Algumas bibliotecas com operações de bloqueio ou acesso direto ao hardware podem causar condições de corrida. Verifique sempre a documentação da biblioteca e considere encapsular o acesso em tarefas protegidas por mutex.
O Core 0 geralmente lida com serviços do sistema, como Wi-Fi e Bluetooth. A execução de tarefas do usuário no Core 1 ajuda a evitar interrupções e garante comunicação sem fio estável, mesmo sob carga pesada.
Paul R é um engenheiro mecatrônico com especialização em eletrônica, projeto de PCB e sistemas embarcados. Ele possui experiência com KiCad, Altium Designer, EasyEDA e Eagle, e tem conhecimento prático em programação Arduino, prototipagem IoT e integração hardware-software.