- Vantagens do processador multi-core
- ESP32 e FreeRTOS
- Encontrar o ID principal do ESP32
- ESP32 Dual Core Programming
Os módulos ESP são populares por suas funcionalidades Wi-Fi, como ESP8266, ESP-12E, etc. Todos são módulos de microcontroladores poderosos com funcionalidades Wi-Fi. Há mais um módulo ESP que é mais poderoso e versátil do que os módulos ESP anteriores - seu nome é ESP32. Ele tem conectividade Bluetooth e Wi-Fi e já explicamos os recursos BLE do ESP32 e usamos o ESP32 em muitos projetos de IoT. Mas muito poucas pessoas sabem que o ESP32 é um microcontrolador Dual-core.
O ESP32 tem dois microprocessadores Tensilica Xtensa LX6 de 32 bits, o que o torna um microcontrolador de núcleo duplo (core0 e core1) poderoso. Está disponível em duas variantes single-core e dual-core. Mas a variante dual-core é mais popular porque não há diferença significativa de preço.
ESP32 pode ser programado usando Arduino IDE, Espressif IDF, Lua RTOS, etc. Durante a programação com Arduino IDE, o código só roda no Core1 porque o Core0 já está programado para comunicação RF. Mas aqui está este tutorial, vamos mostrar como usar os dois núcleos do ESP32 para realizar duas operações simultaneamente. Aqui, a primeira tarefa será piscar o LED integrado e a segunda tarefa será buscar os dados de temperatura do sensor DHT11.
Vamos primeiro ver as vantagens de um processador de vários núcleos em relação a um único núcleo.
Vantagens do processador multi-core
- Os processadores multi-core são úteis quando há mais de 2 processos para trabalhar simultaneamente.
- À medida que o trabalho é distribuído entre diferentes núcleos, sua velocidade aumenta e vários processos podem ser concluídos ao mesmo tempo.
- O consumo de energia pode ser reduzido porque quando qualquer núcleo está no modo ocioso, ele pode ser usado para desligar os periféricos que não estão em uso naquele momento.
- Os processadores dual-core têm que alternar entre threads diferentes com menos frequência do que os processadores single-core porque podem lidar com dois de uma vez em vez de um de cada vez.
ESP32 e FreeRTOS
A placa ESP32 já possui o firmware FreeRTOS instalado. O FreeRTOS é um sistema operacional em tempo real de código aberto muito útil em multitarefa. RTOS ajuda a gerenciar os recursos e maximizar o desempenho do sistema. FreeRTOS tem muitas funções de API para diferentes propósitos e usando essas APIs, podemos criar tarefas e fazê-las rodar em diferentes núcleos.
A documentação completa das APIs do FreeRTOS pode ser encontrada aqui. Tentaremos usar algumas APIs em nosso código para construir um aplicativo multitarefa que será executado em ambos os núcleos.
Encontrar o ID principal do ESP32
Aqui, usaremos o IDE do Arduino para fazer upload do código no ESP32. Para saber o ID do núcleo no qual o código está sendo executado, existe uma função API
xPortGetCoreID ()
Esta função pode ser chamada a partir da função void setup () e void loop () para saber o ID do núcleo no qual essas funções estão sendo executadas.
Você pode testar esta API carregando o esboço abaixo:
configuração vazia () { Serial.begin (115200); Serial.print ("função setup () em execução no núcleo:"); Serial.println (xPortGetCoreID ()); } void loop () { Serial.print ("função loop () em execução no núcleo:"); Serial.println (xPortGetCoreID ()); }
Após fazer o upload do esboço acima, abra o monitor serial e você verá que ambas as funções estão sendo executadas no core1 conforme mostrado abaixo.
A partir das observações acima, pode-se concluir que o esboço padrão do Arduino sempre roda no core1.
ESP32 Dual Core Programming
O Arduino IDE oferece suporte para FreeRTOS for ESP32 e APIs FreeRTOS nos permitem criar tarefas que podem ser executadas independentemente em ambos os núcleos. A tarefa é o trecho de código que realiza alguma operação na placa, como led piscando, envio de temperatura, etc.
A função abaixo é usada para criar tarefas que podem ser executadas em ambos os núcleos. Nesta função, temos que fornecer alguns argumentos como uma prioridade, ID do núcleo, etc.
Agora, siga as etapas abaixo para criar tarefas e funções de tarefas.
1. Primeiro, crie tarefas na função de configuração de vazio . Aqui, criaremos duas tarefas, uma para LED piscando a cada 0,5 segundos e a outra tarefa é obter a leitura da temperatura a cada 2 segundos.
A função xTaskCreatePinnedToCore () leva 7 argumentos:
- Nome da função para implementar a tarefa (tarefa1)
- Qualquer nome dado à tarefa (“tarefa1”, etc)
- Tamanho da pilha atribuído à tarefa em palavras (1 palavra = 2 bytes)
- Parâmetro de entrada da tarefa (pode ser NULL)
- Prioridade da tarefa (0 é a prioridade mais baixa)
- Identificador de tarefa (pode ser NULL)
- ID do núcleo onde a tarefa será executada (0 ou 1)
Agora, crie Task1 para piscar o led dando todos os argumentos na função xTaskCreatePinnedToCore ().
xTaskCreatePinnedToCore (Task1code, "Task1", 10000, NULL, 1, NULL, 0);
Da mesma forma, crie Task2 para Task2 e faça o ID do núcleo 1 no 7º argumento.
xTaskCreatePinnedToCore (Task2code, "Task2", 10000, NULL, 1, NULL, 1);
Você pode alterar a prioridade e o tamanho da pilha dependendo da complexidade da tarefa.
2. Agora, vamos implementar Task1code e Task2code função. Essas funções contêm o código para a tarefa necessária. No nosso caso, a primeira tarefa irá piscar o led e outra tarefa irá buscar a temperatura. Portanto, crie duas funções separadas para cada tarefa fora da função de configuração de vazio.
A função Task1code para piscar o led integrado após 0,5 segundos é implementada conforme mostrado abaixo.
Void Task1code (void * parameter) { Serial.print ("Task1 running on core"); Serial.println (xPortGetCoreID ()); for (;;) {// loop infinito digitalWrite (led, HIGH); atraso (500); digitalWrite (led, LOW); atraso (500); } }
Da mesma forma, implemente a função Task2code para obter a temperatura.
void Task2code (void * pvParameters) { Serial.print ("Task2 running on core"); Serial.println (xPortGetCoreID ()); para (;;) { float t = dht.readTemperature (); Serial.print ("Temperatura:"); Serial.print (t); atraso (2000); } }
3. Aqui, a função de loop vazio permanecerá vazia. Como já sabemos, esse loop e a função de configuração são executados no core1, portanto, você também pode implementar a tarefa core1 na função void loop .
Agora que a parte de codificação acabou, basta fazer o upload do código usando o Arduino IDE, escolhendo a placa ESP32 no menu Ferramentas. Certifique-se de ter conectado o sensor DHT11 ao pino D13 do ESP32.
Agora os resultados podem ser monitorados no Serial Monitor ou Arduino IDE conforme mostrado abaixo:
Aplicativos complexos como o sistema em tempo real podem ser construídos executando várias tarefas simultaneamente usando núcleos duplos do ESP32.
O código completo junto com um vídeo de demonstração é fornecido abaixo.