📚 NÍVEL 2 - INTERMEDIÁRIO (Semanas 7-10)

Progresso: [ ] Semana 7-8 [ ] Semana 9 [ ] Semana 10 [ ] Projeto Final

📑 Índice

Semana 7-8: Timers e Interrupts

Semana 9: I2C e Display OLED

Semana 10: WiFi Básico

🎯 Projeto Final: Monitor de Temperatura WiFi

⚠️ Problemas Comuns e Soluções

🔗 Próximos Passos


Semana 7-8: Timers e Interrupts

📊 Metadados:

📖 Fundamentos - Timers e Interrupções

O que são Hardware Timers?

Vantagens sobre vTaskDelay:

Interrupções (Interrupts):

Tipos de Interrupções no ESP32:

Regras Importantes para ISR:

APIs Principais:

1
2
3
4
5
6
7
8
9
10
11
// Timers
gptimer_new_timer()              // Cria timer
gptimer_set_alarm_action()       // Configura alarme
gptimer_register_event_callbacks() // Registra callback
gptimer_enable()                 // Habilita timer
gptimer_start()                  // Inicia contagem

// Interrupções GPIO
gpio_install_isr_service()       // Instala serviço ISR
gpio_isr_handler_add()           // Adiciona handler
gpio_set_intr_type()             // Define tipo de trigger

Exercício 9: Timer Preciso

Objetivo: Usar hardware timer ao invés de vTaskDelay para temporização precisa

Componentes Necessários:

Conceitos:

Código Básico pro Exercício
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
#include "driver/gptimer.h"

gptimer_handle_t gptimer = NULL;
bool led_state = false;

bool IRAM_ATTR timer_callback(gptimer_handle_t timer, 
                                const gptimer_alarm_event_data_t *edata,
                                void *user_data)
{
    led_state = !led_state;
    gpio_set_level(LED_PIN, led_state);
    return false;  // não precisa retornar high priority task woken
}

void app_main(void)
{
    gpio_reset_pin(LED_PIN);
    gpio_set_direction(LED_PIN, GPIO_MODE_OUTPUT);
    
    // Configurar timer
    gptimer_config_t timer_config = {
        .clk_src = GPTIMER_CLK_SRC_DEFAULT,
        .direction = GPTIMER_COUNT_UP,
        .resolution_hz = 1000000,  // 1MHz = 1us
    };
    gptimer_new_timer(&timer_config, &gptimer);
    
    // Configurar alarme
    gptimer_alarm_config_t alarm_config = {
        .alarm_count = 1000000,  // 1 segundo
        .reload_count = 0,
        .flags.auto_reload_on_alarm = true,
    };
    gptimer_set_alarm_action(gptimer, &alarm_config);
    
    // Registrar callback
    gptimer_event_callbacks_t cbs = {
        .on_alarm = timer_callback,
    };
    gptimer_register_event_callbacks(gptimer, &cbs, NULL);
    
    gptimer_enable(gptimer);
    gptimer_start(gptimer);
    
    while(1) {
        vTaskDelay(1000 / portTICK_PERIOD_MS);
    }
}

Desafios:

  1. 🟢 Fácil: Mudar frequência do blink para 500ms (mais rápido)
  2. 🟡 Médio: Usar 2 timers para controlar 2 LEDs em frequências diferentes
  3. 🔴 Difícil: Criar cronômetro preciso (minutos:segundos:milissegundos) com display

Exercício 10: Interrupt de GPIO

Objetivo: Responder imediatamente a eventos de botão usando interrupções

Componentes Necessários:

Conceitos:

Código Básico pro Exercício
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
#define BUTTON_PIN GPIO_NUM_0

volatile int button_presses = 0;

void IRAM_ATTR button_isr_handler(void *arg)
{
    button_presses++;
}

void app_main(void)
{
    gpio_config_t io_conf = {
        .pin_bit_mask = (1ULL << BUTTON_PIN),
        .mode = GPIO_MODE_INPUT,
        .pull_up_en = GPIO_PULLUP_ENABLE,
        .pull_down_en = GPIO_PULLDOWN_DISABLE,
        .intr_type = GPIO_INTR_NEGEDGE,  // Falling edge
    };
    gpio_config(&io_conf);
    
    gpio_install_isr_service(0);
    gpio_isr_handler_add(BUTTON_PIN, button_isr_handler, NULL);
    
    while(1) {
        printf("Botão pressionado %d vezes\n", button_presses);
        vTaskDelay(1000 / portTICK_PERIOD_MS);
    }
}

Desafios:

  1. 🟢 Fácil: Mudar para detectar rising edge (quando solta o botão)
  2. 🟡 Médio: Implementar debounce na ISR usando timestamp
  3. 🔴 Difícil: Usar queue (FreeRTOS) para comunicar ISR com task principal

Semana 9: I2C e Display OLED

📊 Metadados:

📖 Fundamentos - I2C (Inter-Integrated Circuit)

O que é I2C?

Características:

Dispositivos Comuns I2C:

Pinos ESP32:

APIs Principais:

1
2
3
4
i2c_param_config()        // Configura parâmetros
i2c_driver_install()      // Instala driver
i2c_master_write_to_device() // Envia dados
i2c_master_read_from_device() // Lê dados

Exercício 11: OLED SSD1306

Objetivo: Controlar display OLED via I2C

Componentes Necessários:

Conceitos:

Código Básico pro Exercício
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
#include "driver/i2c.h"

#define I2C_MASTER_SCL_IO GPIO_NUM_22
#define I2C_MASTER_SDA_IO GPIO_NUM_21
#define I2C_MASTER_FREQ_HZ 400000

void i2c_master_init(void)
{
    i2c_config_t conf = {
        .mode = I2C_MODE_MASTER,
        .sda_io_num = I2C_MASTER_SDA_IO,
        .scl_io_num = I2C_MASTER_SCL_IO,
        .sda_pullup_en = GPIO_PULLUP_ENABLE,
        .scl_pullup_en = GPIO_PULLUP_ENABLE,
        .master.clk_speed = I2C_MASTER_FREQ_HZ,
    };
    
    i2c_param_config(I2C_NUM_0, &conf);
    i2c_driver_install(I2C_NUM_0, conf.mode, 0, 0, 0);
}

// Use biblioteca como SSD1306 driver
// Exemplo: https://github.com/nopnop2002/esp-idf-ssd1306

Desafios:

  1. 🟢 Fácil: Exibir “Hello ESP32!” centralizado na tela
  2. 🟡 Médio: Criar animação simples (texto deslizando)
  3. 🔴 Difícil: Exibir gráfico de barras com leituras de ADC em tempo real

Semana 10: WiFi Básico

📊 Metadados:

📖 Fundamentos - WiFi no ESP32

Modos WiFi:

Processo de Conexão:

  1. Inicializar NVS (armazenamento não-volátil)
  2. Inicializar netif e event loop
  3. Configurar WiFi (SSID, senha)
  4. Iniciar WiFi e conectar
  5. Aguardar evento de IP obtido

HTTP Server:

NVS (Non-Volatile Storage):

APIs Principais:

1
2
3
4
5
6
7
8
esp_netif_init()          // Inicializa interface de rede
esp_wifi_init()           // Inicializa WiFi
esp_wifi_set_mode()       // Define modo (STA/AP)
esp_wifi_set_config()     // Configura credenciais
esp_wifi_start()          // Inicia WiFi
esp_wifi_connect()        // Conecta ao AP
httpd_start()             // Inicia servidor HTTP
httpd_register_uri_handler() // Registra endpoint

Exercício 12: Conectar WiFi e Servidor Web

Objetivo: Controlar LED através de página web

Componentes Necessários:

Conceitos:

Código Básico pro Exercício
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
#include "esp_wifi.h"
#include "esp_http_server.h"
#include "nvs_flash.h"

#define WIFI_SSID "SeuWiFi"
#define WIFI_PASS "SuaSenha"

esp_err_t led_on_handler(httpd_req_t *req)
{
    gpio_set_level(LED_PIN, 1);
    httpd_resp_send(req, "LED Ligado!", HTTPD_RESP_USE_STRLEN);
    return ESP_OK;
}

esp_err_t led_off_handler(httpd_req_t *req)
{
    gpio_set_level(LED_PIN, 0);
    httpd_resp_send(req, "LED Desligado!", HTTPD_RESP_USE_STRLEN);
    return ESP_OK;
}

void wifi_init(void)
{
    nvs_flash_init();
    esp_netif_init();
    esp_event_loop_create_default();
    
    wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
    esp_wifi_init(&cfg);
    
    wifi_config_t wifi_config = {
        .sta = {
            .ssid = WIFI_SSID,
            .password = WIFI_PASS,
        },
    };
    
    esp_wifi_set_mode(WIFI_MODE_STA);
    esp_wifi_set_config(WIFI_IF_STA, &wifi_config);
    esp_wifi_start();
    esp_wifi_connect();
}

void start_webserver(void)
{
    httpd_handle_t server = NULL;
    httpd_config_t config = HTTPD_DEFAULT_CONFIG();
    
    httpd_uri_t led_on = {
        .uri = "/led/on",
        .method = HTTP_GET,
        .handler = led_on_handler,
    };
    
    httpd_uri_t led_off = {
        .uri = "/led/off",
        .method = HTTP_GET,
        .handler = led_off_handler,
    };
    
    httpd_start(&server, &config);
    httpd_register_uri_handler(server, &led_on);
    httpd_register_uri_handler(server, &led_off);
}

Desafios:

  1. 🟢 Fácil: Adicionar endpoint para toggle LED (/led/toggle)
  2. 🟡 Médio: Criar página HTML com botões visuais
  3. 🔴 Difícil: Implementar controle de brilho PWM via slider web

🎯 Projeto Final: Monitor de Temperatura WiFi

📊 Metadados do Projeto:

Descrição: Sistema completo de monitoramento de temperatura com display local OLED e interface web para visualização remota, incluindo histórico e alertas.

Componentes Necessários:

Funcionalidades Obrigatórias:

  1. ✅ Ler temperatura/umidade a cada 5 segundos
  2. ✅ Exibir dados no OLED (temperatura, umidade, status WiFi)
  3. ✅ Servidor web mostra leitura atual e histórico das últimas 20 leituras
  4. ✅ LED de alerta acende se temperatura > 30°C
  5. ✅ Endpoint API JSON com dados atuais

Critérios de Avaliação:

Extensões Opcionais (🌟 Desafios Extras):

  1. 🟡 Adicionar gráfico SVG dinâmico na página web
  2. 🟡 Salvar histórico em NVS (persiste após reboot)
  3. 🔴 Implementar modo AP para configuração inicial (WiFi provisioning)
  4. 🔴 Adicionar notificações push em alertas
  5. 🔴 Criar dashboard com Chart.js para visualização profissional

⚠️ Problemas Comuns e Soluções

Timer não dispara callback

Sintoma: LED não pisca ou callback nunca é chamado

Soluções:

ISR causa crash/reset

Sintoma: ESP32 reinicia quando interrupção dispara

Soluções:

I2C não encontra dispositivo

Sintoma: Erro “timeout” ou “no ACK”

Soluções:

Display OLED não mostra nada

Sintoma: Tela permanece apagada

Soluções:

WiFi não conecta

Sintoma: ESP32 não obtém IP

Soluções:

HTTP server retorna erro 404

Sintoma: Página não encontrada ao acessar

Soluções:

Leitura do sensor I2C retorna valores absurdos

Sintoma: Temperatura -40°C ou 85°C constante

Soluções:


🔗 Próximos Passos

🎉 Parabéns por completar o Nível 2!

Você agora domina:

Pré-requisitos atendidos para Nível 3:

Próximo Nível: 🔼 [Nível 3 - Avançado]

O que você vai aprender:

Recomendações antes de avançar:

  1. 📝 Revisar conceitos de ISR e timers
  2. 🛠️ Experimentar com diferentes sensores I2C
  3. 📚 Ler sobre FreeRTOS: FreeRTOS Guide
  4. 🔍 Estudar exemplos WiFi: ESP-IDF WiFi Examples

Recursos de Referência:


Última atualização: 15/01/2026