No artigo anterior, criamos um novo projeto no Microsoft Visual Code via Espressif ESP-IDF.
Agora, com o projeto criado, vamos mudar o template basico para o nosso projeto BLINK otimizado: Substitua o conteúdo do main.c para o código abaixo:
#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "driver/gpio.h"
#include "esp_log.h"
#define BLINK_GPIO 2
static const char *TAG = "PISCA";
void app_main(void)
{
gpio_reset_pin(BLINK_GPIO);
gpio_set_direction(BLINK_GPIO, GPIO_MODE_OUTPUT);
while (1) {
ESP_LOGI(TAG, "LED 2 LIGADO");
gpio_set_level(BLINK_GPIO, 1);
vTaskDelay(pdMS_TO_TICKS(1000)); 
ESP_LOGI(TAG, "LED 2 DESLIGADO");
gpio_set_level(BLINK_GPIO, 0);
vTaskDelay(pdMS_TO_TICKS(1000));
}
}
Faça o build, o flash e o monitor e veremos o led piscar na placa. sua IDE deverá estar mais ou menos assim:
Com o código rodando, vamos estudar o que as linhas dizem:
Entendendo o novo código
as primeiras linhas
#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "driver/gpio.h"
#include "esp_log.h"
#define BLINK_GPIO 2
static const char *TAG = "PISCA";
vamos separar em dois blocos:
O primeiro bloco: temos as linhas iniciando com
#include
estas linhas são diretivas de importação de bibliotecas, uma Biblioteca nada mais é que um arquivo
.h e arquivo
.c ou
.cpp com as funções agrupadas para uma certa funcionalidade.
stdio.h é uma biblioteca padrão da linguagem C. Note que ela esta sob os caracteres "<" e ">" Esse caractere diz ao compilador que é uma biblioteca padrão do sistema. O compilador sabe onde encontrar.
Em seguida, temos o
#include "freertos/freertos.h"
que esta sob áspas. Essas aspas dizem que o arquivo fica na pasta
components dentro da pasta esp-idf, onde reside o compilador:
~/.espressif/v6.0.1/esp-idf/components/
freertos.h contém funções para o programa possa interagir com o sistema operacional freertos que esta rodando por baixo da aplicação. O freertos é um sistema de tempo real para diversos dispositivos.
Em seguida, temos o
#include "driver/gpio.h"
Contém funções para controle do GPIO, como colocar o pino como, entrada, saida, habilitar ou não o resistor de pullup, colocar o estado do pino em zero (Baixo) ou um (alto) entre outras funções.
Os programadores de Arduino choram ao ver o proximo include, no ESP-IDF não usamos Serial.print para mensagens de debug. Em seu lugar, a lib
"esp_log.h" fornece por exemplo
ESP_LOGI entre outras para mostrar mensagens no console. Falemos mais sobre ele, mais tarde, eu prometo!
O Segundo bloco, temos uma diretiva
#define BLINK_GPIO 2
Esta diretiva do pré-processador em C que serve para definir macros, que se o compilador encontrar
BLINK_GPIO ele o substitua pelo número
2. Para quê? Estamos definindo que
BLINK_GPIO será uma constante que diz qual o número do pino do led. Se precisar mudar o número do pino no futuro, só precisa mudar o valor na diretiva citada define. Isso evita muita confusão futura.
por último, temos a misteriosa linha:
static const char *TAG = "BLINK";
Ela define uma constante chamada TAG que vamos usar mais tarde.
Temos agora o procedimento mais importante do código: app_main(void)
void app_main(void)
{
gpio_reset_pin(BLINK_GPIO);
gpio_set_direction(BLINK_GPIO, GPIO_MODE_OUTPUT);
while (1) {
ESP_LOGI(TAG, "LED 2 LIGADO");
gpio_set_level(BLINK_GPIO, 1);
vTaskDelay(pdMS_TO_TICKS(1000));
ESP_LOGI(TAG, "LED 2 DESLIGADO");
gpio_set_level(BLINK_GPIO, 0);
vTaskDelay(pdMS_TO_TICKS(1000));
}
}
Uma função ou procedimento em c possuem a mesma estrutura, iniciam com o tipo de retorno (no nosso caso um void) que significa: Nada, ou seja, esta é um procedimento pelo contrário é uma função, que possui um tipo de retorno, um int, etc. O procedimento app_main é onde reside o nosso código principal, o conteúdo da função ou procedimento ficam dentro das chaves "{" e "}", o compilador procura esse ponto para executar o programa e vamos conhecer agora o que ela faz.
gpio_reset_pin é uma função que reseta o estado do pino para um padrão, (parando o cursor sobre a função, ele mostra dados de como a função trabalha e seu tipo de retorno). Neste caso, estamos resetando o estado do pino BLINK_GPIO (que é o GPIO 2) para seu estado padrão.
em seguida temos: gpio_set_direction(BLINK_GPIO, GPIO_MODE_OUTPUT); Esta linha faz o pino de GPIO 2 como pino de saída, ou seja, qualquer valor (zero ou um) que o software definir, o pino terá o valor GND (baixo) ou 3v3 (alto).
temos agora uma nova estrutura (a turma do Arduino fica receosa aqui) o temido while(1) ele faz o programa ficar rodando as instruções dentro do bloco indefinidamente. Quem vem do arduino, digamos que as instruções antes do while, seriam as instruções que rodam no procedimento setup() e o procedimento loop() do Arduino nada mais é que um bloco while (1) { loop(); }
Vamos ver o que esta dentro deste bloco while(1):
while (1) {
ESP_LOGI(TAG, "LED 2 LIGADO");
gpio_set_level(BLINK_GPIO, 1);
vTaskDelay(pdMS_TO_TICKS(1000));
ESP_LOGI(TAG, "LED 2 DESLIGADO");
gpio_set_level(BLINK_GPIO, 0);
vTaskDelay(pdMS_TO_TICKS(1000));
}
Aqui temos dois blocos bem parecidos:
ESP_LOGI (é a mensagem verde no monitor serial, TAG é aquele static const char do inicio do código e em seguida a mensagem de informação (LOGI = log_Information) Num outro artigo vamos falar mais do poderoso log do IDF que é muito melhor que usar Serial.println do arduino. No monitor de código, vemos assim a execução desta função:
I (370) BLINK: LED 2 LIGADO
A instrução seguinte é bem explicativa:
gpio_set_level(BLINK_GPIO, 1);
Esta linha coloca o pino 2 no nĩvel alto. no código da ide Arduino equivale a digitalPin(2,HIGH);
a proxima linha é importante; ela substituir a instrução delay(1000) do Arduino:
vTaskDelay(pdMS_TO_TICKS(1000));
Ela atrasa a task atual por um numero de TICKS como o TICK é um valor muito pequeno, usamos pdMS_TO_TICKS para transformar o numero 1000 ms (equivalente a 1 segundo) em TICKS do relógio do ESP32. Este varia dependendo da velocidade do clock, por isso a função pdMS_TO_TICKS
o Bloco seguinte, é identico ao primeiro bloco, suas mudanças são: a mensagem do LOGI e o gpio_set_level para 0 ou Baixo(GND), temos ainda a mesma função vTaskDelay com o mesmo tempo de pausa. brinque mudando estes valores para ver o led piscar numa frequencia diferente.
Apesar de ser bem diferente do mesmo código do Arduino, temos um controle muito maior do que fazemos. Iremos evoluir este código colocando uma task! Aguardem!