Manual
do
Maker
.
com
Sem entrar no mérito da questão, utilizar o FreeRTOS no Arduino pode ser uma boa pedida para quem ainda não comprou um Blue Pill ou um ESP32. Dá pra fazer umas brincadeiras e se habituar com alguns conceitos.
O método tradicional em microcontroladores é normalmente um loop infinito e tudo acontece lá dentro da função main(). O Arduino não é diferente, só que a API dele abstrai um pouquinho mais, nos dando a função setup() para fazer a pré-configuração e loop(), que roda dentro de um loop infinito, como podemos observar no arquivo main.cpp do núcleo:
No artigo "A linguagem do Arduino é C ou C++?" eu esqueci de mostrar isso. Apenas o arquivo main.cpp já falaria tudo, mas vamos lá. Veja que dentro da função main() temos algumas chamadas internas, a chamada da função setup() e um loop for(;;) para manter o programa rodando continuamente, onde é chamada a função loop.
Temos algumas maneiras de chamar funções só em dados momentos. Por exemplo, utilizando interrupções. Ocorrendo uma interrupção, o programa pára o que estava fazendo, salta para a função de tratamento da interrupção e então volta ao exato ponto em que havia parado. Outra forma de executar uma função fora do loop é definir uma interrupção por software, utilizando a biblioteca timerOne, que ficará "dormindo" até chegar ao timeout da função, que então se inicia e se executa. A vantagem utilizar o método tradicional da API do Arduino é que a área de programa será menor, consumirá menos recursos e sobrará mais espaço para o programa.
Utilizar o FreeRTOS no Arduino é uma forma de ter mais liberdade para programar. Tarefas podem ser executadas de forma assíncrona. Um exemplo bacana é o artigo que escrevi próximo ao natal, utilizando um display OLED exibindo flocos de neve caindo, enquanto tocava a música "jingle bell" no buzzer. No Arduino seria bastante problemático fazê-lo com essa eficiência, mas em um sistema operacional de tempo real temos as chamdas "tasks" (se quiser dar uma boa estudada no tema, na seção ESP32 do site você encontra diversos artigos explicando a respeito). Uma task é, em outras palavras, uma thread; um processo assíncrono que pode rodar com uma prioridade especificada pelo usuário. Essa execução assíncrona é uma característica do sistema operacional, chamada multi-tasking. De verdade, elas não se executam ao mesmo tempo, mas o gerenciamento da execução no tempo é tratado pelo scheduler, que decide quando e qual parte do programa deve rodar, abstraindo esse tratamento que é dado pelo programador em um processo microcontrolado sem um RTOS (Real Time Operating System - ou, Sistema Operacional de Tempo Real).
Vá ao menu Library Manager (ou gerenciador de bibliotecas, se sua IDE estiver em português - eu deixo tudo em inglês no meu sistema). No "tipo", escolha "Contribuição" e no "tópico" escolha "Timing". Digite na pesquisa "FreeRTOS" e instale a versão mais atual.
Inclua a biblioteca em um sketch novo e faça o blink com esse código para testar:
#include <Arduino_FreeRTOS.h>
struct blk{
int stat : 1;
} blinker;
void vTaskBlink(void *pvParameters);
int delayMs(int value);
void setup() {
xTaskCreate(vTaskBlink, (const portCHAR*)"blink", 128, NULL, 1, NULL);
}
void loop() {
//nada aqui
}
void vTaskBlink(void *pvParameters){
pinMode(13, OUTPUT);
blinker.stat = 1;
while (true){
digitalWrite(13,blinker.stat);
vTaskDelay(delayMs(500));
blinker.stat += 1;
}
}
int delayMs(int value){
return value/portTICK_PERIOD_MS;
}
Esse sketch não prova o conceito de real time, mas foi escrito apenas para primeiro contato. Se quiser ver coisas elaboradas, mais uma vez, vá ao menu ESP32 e veja os artigos, todos escritos utilizando RTOS.
Repare que criei uma função pra o delay, porque o delay do FreeRTOS é em ticks, que vai dar 15ms por tick.
Em setup() apenas foi criada a task. A struct que criei para o blink é para sair do padrão chato "liga, delay, desliga, delay".
Quando tiver uma ocasião que propicie, escrevo outro artigo mostrando mais a respeito.
Além dos sistemas operacionais de tempo real, temos predominantemente o Linux rodando em plataformas embarcadas, seja MIPS, ARM, X86 etc. Não é o mesmo Linux que roda no desktop, a começar pelas arquiteturas citadas e seus tipos binários.
O Arduino não é uma microcontroladora projetada para um RTOS, por isso podemos tirar vantagem em relação à flexibilidade, mas considere que isso afetará o processamento.
Aproveito pra finalizar anunciando o lançamento do meu curso "Raspberry para hobistas e profissionais" na Udemy, onde abordo os temas mão-na-massa na ordem em que construo um projeto para meus clientes, por isso cobri os pontos necessários para sair do zero e finalizar com um backup replicável. Está uma pechincha, ainda mais com o cupom de desconto DOBITAOBYTE. Conto com seu apoio, valeu?
Inscreva-se no nosso canal Manual do Maker no YouTube.
Também estamos no Instagram.
Autor do blog "Do bit Ao Byte / Manual do Maker".
Viciado em embarcados desde 2006.
LinuxUser 158.760, desde 1997.