Suponha que estamos usando uma placa eletrônica do tipo ESP32 e queremos executar uma rotina de controle proporcional na qual o algoritmo de controle (controle proporcional) deve ser executada obedecendo um período de amostragem de 100 Hz. Esta rotina deve ler dados de um sensor (algum canal de conversor Analógico para Digital (ADC) disponível na placa ESP32), deve calcular a lei de controle e deve enviar o sinal de controle para fora usando alguma canal livre de um conversor de Digital para Analógico (DAC) disponível na placa ESP32. Suponha que no tempo livre, esta placa poderia estar enviando via porta serial, 3 colunas de dados, onde a primeira coluna seria o valor atual da referência ou set-point, a segunda coluna seria o valor atual lido via ADC e a terceira coluna, o valor do sinal de controle gerado e enviado para o DAC.
Para implementar um controle proporcional em um ESP32 utilizando FreeRTOS, com um período de amostragem de 100 Hz, precisamos configurar uma tarefa periódica que lê os dados de um sensor via ADC, calcula o controle proporcional, envia o sinal de controle para o DAC e, no tempo livre, envia os dados via porta serial. A seguir, descrevo como essa implementação pode ser feita.
A seguir, um exemplo de código em C/C++ para ser usado no ambiente Arduino IDE ou similar, utilizando a biblioteca do FreeRTOS disponível para o ESP32.
Defina os pinos utilizados para ADC e DAC:
xxxxxxxxxx
// Exemplo de pino ADC
// Exemplo de pino DAC
Configure o FreeRTOS para criar uma tarefa de controle proporcional e a tarefa de envio de dados via serial:
x
// Protótipos das funções das tarefas
void TaskControl(void *pvParameters);
void TaskSerial(void *pvParameters);
// Variáveis globais
volatile float setPoint = 1.0; // Exemplo de set-point
volatile float adcValue = 0.0;
volatile float controlSignal = 0.0;
// Parâmetro de controle proporcional
const float Kp = 2.0;
void setup() {
// Configurações iniciais
Serial.begin(115200);
analogReadResolution(12); // Configurar a resolução do ADC
analogSetPinAttenuation(ADC_PIN, ADC_11db); // Configurar a atenuação do ADC
// Criação das tarefas
xTaskCreatePinnedToCore(TaskControl, "TaskControl", 2048, NULL, 1, NULL, 0);
xTaskCreatePinnedToCore(TaskSerial, "TaskSerial", 2048, NULL, 1, NULL, 1);
}
void loop() {
// O loop do Arduino fica vazio, pois usamos o FreeRTOS
}
// Tarefa de Controle Proporcional
void TaskControl(void *pvParameters) {
const TickType_t xFrequency = pdMS_TO_TICKS(10); // 10 ms (100 Hz)
TickType_t xLastWakeTime = xTaskGetTickCount();
while (true) {
// Ler o valor do ADC
adcValue = analogRead(ADC_PIN) * (3.3 / 4095.0); // Converter para tensão
// Calcular o sinal de controle (Controle Proporcional)
controlSignal = Kp * (setPoint - adcValue);
// Enviar o sinal de controle para o DAC
dacWrite(DAC_PIN, (int)(controlSignal * 255.0 / 3.3));
// Aguardar até a próxima execução
vTaskDelayUntil(&xLastWakeTime, xFrequency);
}
}
// Tarefa de Envio Serial
void TaskSerial(void *pvParameters) {
while (true) {
// Enviar os dados via porta serial
Serial.print("Set-Point: ");
Serial.print(setPoint);
Serial.print("\tADC Value: ");
Serial.print(adcValue);
Serial.print("\tControl Signal: ");
Serial.println(controlSignal);
// Aguardar 100 ms antes de enviar novamente
vTaskDelay(pdMS_TO_TICKS(100));
}
}
Configuração do Hardware:
ADC_PIN
e DAC_PIN
são definidos para os pinos usados no ADC e DAC, respectivamente.analogReadResolution(12)
define a resolução do ADC para 12 bits.analogSetPinAttenuation(ADC_PIN, ADC_11db)
ajusta a atenuação do ADC para o pino especificado, permitindo leituras de até 3.3V.Inicialização do FreeRTOS:
xTaskCreatePinnedToCore
cria duas tarefas: TaskControl
para o controle proporcional e TaskSerial
para o envio de dados via serial. As tarefas são atribuídas a diferentes núcleos do ESP32 para melhor desempenho.Tarefa de Controle Proporcional:
TaskControl
lê o valor do ADC, calcula o sinal de controle proporcional e envia esse sinal para o DAC.vTaskDelayUntil(&xLastWakeTime, xFrequency)
garante que a tarefa será executada a cada 10 ms, proporcionando uma frequência de 100 Hz.Tarefa de Envio Serial:
TaskSerial
envia os dados do set-point, valor do ADC e sinal de controle via UART a cada 100 ms.Esse exemplo de código demonstra como usar o FreeRTOS para criar tarefas que executam controle em tempo real e comunicação serial no ESP32. As tarefas são executadas de maneira determinística, garantindo que o controle proporcional ocorra com precisão a cada 10 ms.