Implementação do Modo Ponto de Acesso WiFi no ESP32-C3

Princípios e Implementação do Modo AP WiFi no ESP32-C3

Construir uma rede local sem fio autônoma com o ESP32-C3 é uma capacidade fundamental em muitas aplicações de IoT. Quando configurado para operar como Ponto de Acesso (Access Point, AP), o chip assume o papel de um roteador leve, transmitindo sinais de beacon, gerenciando associações de clientes e distribuindo endereços IP. Esta funcionalidade é a base para configuração inicial via smartphone, painéis de controle locais e atualizações de firmware diretas.

Entender o modo AP requer olhar para o padrão IEEE 802.11. Ao iniciar o modo AP, o processador de baseband do ESP32-C3 estabelece um Basic Service Set (BSS) único, identificado por um SSID (nome da rede) e BSSID (geralmente o endereço MAC do AP). Dispositivos clientes podem escanear a rede, associar-se a ela e, após o handshake de segurança, receber um endereço IP a partir da pool DHCP gerenciada internamente (normalmente no intervalo 192.168.4.0/24). Este processo replica a operação de um ponto de acesso doméstico convencional, mas com recursos significativamente mais limitados.

Ambiente de Desenvolvimento e Configurações Essenciais

O desenvolvimento utiliza o framework ESP-IDF v5.1.2. O projeto segue a estrutura padrão, com a aplicação principal em main/app_main.c.

A configuração do modo AP através do menu menuconfig é crucial. Parâmetros como CONFIG_ESP_WIFI_SOFTAP_MAX_CONN (limitado a 4), CONFIG_LWIP_DHCP_SERVER (para habilitar o servidor DHCP) e CONFIG_ESP_WIFI_SOFTAP_BEACON_INTERVAL (intervalo de quadros de beacon, afeta a descoberta da rede) precisam ser definidos corretamente. O intervalo de beacon padrão de 100ms (100 TU) é recomendado, pois intervalos maiores atrasam a detecção pelos clientes.

Para fins de demonstração, utilizamos o GPIO7 para controlar um LED indicativo. Sua inicialização segue o padrão do ESP-IDF:


// Definição do pino do LED
#define STATUS_LED_PIN GPIO_NUM_7

void setup_status_led(void)
{
    gpio_config_t led_config = {};
    led_config.mode = GPIO_MODE_OUTPUT;
    led_config.pull_up_en = GPIO_PULLUP_DISABLE;
    led_config.pull_down_en = GPIO_PULLDOWN_DISABLE;
    led_config.intr_type = GPIO_INTR_DISABLE;
    led_config.pin_bit_mask = (1ULL << STATUS_LED_PIN);
    gpio_config(&led_config);
    
    // Estado inicial: LED apagado (assumindo circuito ativo em nível baixo)
    gpio_set_level(STATUS_LED_PIN, 1);
}

Domínio das APIs do Modo AP e Seu Uso Prático

Todas as operações relacionadas ao WiFi são controladas pelas APIs do ESP-IDF, com funções prefixadas por esp_wifi_.

1. Definição do Modo de Operação

A chamada esp_wifi_set_mode(wifi_mode_t mode) deve preceder o início do driver (esp_wifi_start()). O modo AP é selecionado com WIFI_MODE_AP. Alterar o modo após o início do driver requer uma reinicialização completa.

2. Configuração dos Parâmetros do AP

A estrutura wifi_ap_config_t define os detalhes da rede. Parâmetros críticos incluem:

  • ssid e password: Nome da rede e chave de segurança (WPA2 é o mínimo recomendado).
  • channel: Canal de operação (1-13). O valor 0 permite seleção automática pelo driver.
  • max_connection: Número máximo de clientes simultâneos (limitado a 4 pelo hardware).
  • ssid_hidden: Se definido como 1, a rede não é divulgada em broadcasts, aumentando a privacidade.

A configuração é aplicada com:


wifi_ap_config_t ap_settings = {
    .ssid = "ESP32_C3_CONFIG",
    .password = "senha_segura",
    .ssid_len = 0, // Calculado automaticamente
    .channel = 6,
    .authmode = WIFI_AUTH_WPA2_PSK,
    .max_connection = 4,
    .ssid_hidden = 0
};
ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_AP, &ap_settings));

3. Monitoramento do Estado em Tempo Real

Após o início, funções de consulta permitem acompanhar a rede:

  • esp_wifi_softap_get_station_num(): Retorna o número de clientes conectados.
  • tcpip_adapter_get_ip_info(TCPIP_ADAPTER_IF_AP, ...): Obtém as informações de IP (endereço, máscara, gateway) da interface AP.

Implementação Completa: Serviço AP com Gerenciamento de Timeout

O exemplo a seguir implementa um AP que se desliga automaticamnete após 30 segundos de inatividade (sem clientes conectados), economizando energia.

A lógica principal utiliza um temporizador de alta precisão (esp_timer) para evitar bloquear a execução com delays. O LED indica o estado: aceso quando o AP está ativo e com pelo menos um cliente conectado.


#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "esp_wifi.h"
#include "esp_event.h"
#include "esp_log.h"
#include "esp_timer.h"
#include "nvs_flash.h"
#include "tcpip_adapter.h"
#include "driver/gpio.h"

#define LOG_TAG "AP_SERVICE"
#define IDLE_TIMEOUT_US (30 * 1000000) // 30 segundos em microssegundos

static esp_timer_handle_t ap_shutdown_timer = NULL;
static esp_netif_t* ap_netif = NULL;

// Protótipos das funções
static void wifi_event_handler(void* arg, esp_event_base_t base, int32_t id, void* data);
static void shutdown_timer_callback(void* arg);
static void update_led_state(void);

static void init_ap_service(void)
{
    // Inicialização do NVS
    esp_err_t ret = nvs_flash_init();
    if (ret == ESP_ERR_NVS_NO_FREE_PAGES || ret == ESP_ERR_NVS_NEW_VERSION_FOUND) {
        ESP_ERROR_CHECK(nvs_flash_erase());
        ret = nvs_flash_init();
    }
    ESP_ERROR_CHECK(ret);

    // Inicialização da rede e do loop de eventos
    ESP_ERROR_CHECK(esp_netif_init());
    ESP_ERROR_CHECK(esp_event_loop_create_default());
    
    // Cria a interface de rede AP
    ap_netif = esp_netif_create_default_wifi_ap();
    assert(ap_netif != NULL);

    // Inicializa o driver WiFi
    wifi_init_config_t wifi_cfg = WIFI_INIT_CONFIG_DEFAULT();
    ESP_ERROR_CHECK(esp_wifi_init(&wifi_cfg));

    // Registra handlers para eventos do AP
    ESP_ERROR_CHECK(esp_event_handler_instance_register(
        WIFI_EVENT, WIFI_EVENT_AP_STACONNECTED, &wifi_event_handler, NULL, NULL));
    ESP_ERROR_CHECK(esp_event_handler_instance_register(
        WIFI_EVENT, WIFI_EVENT_AP_STADISCONNECTED, &wifi_event_handler, NULL, NULL));

    // Configura o modo e os parâmetros do AP
    ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_AP));
    
    wifi_ap_config_t ap_config = {
        .ssid = "Device_Config",
        .password = "config123",
        .ssid_len = strlen("Device_Config"),
        .channel = 1,
        .authmode = WIFI_AUTH_WPA2_PSK,
        .max_connection = 4,
        .ssid_hidden = 0
    };
    ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_AP, &ap_config));
    
    // Cria o temporizador de desligamento automático
    esp_timer_create_args_t timer_args = {
        .callback = &shutdown_timer_callback,
        .name = "ap_idle_timer"
    };
    esp_timer_create(&timer_args, &ap_shutdown_timer);
    
    // Inicia o AP
    ESP_ERROR_CHECK(esp_wifi_start());
    ESP_LOGI(LOG_TAG, "Ponto de Acesso inicializado.");
}

static void wifi_event_handler(void* arg, esp_event_base_t base, int32_t id, void* data)
{
    if (id == WIFI_EVENT_AP_STACONNECTED) {
        // Cliente conectou. Cancela o desligamento e acende o LED.
        esp_timer_stop(ap_shutdown_timer);
        update_led_state();
        ESP_LOGI(LOG_TAG, "Novo cliente conectado.");
    } else if (id == WIFI_EVENT_AP_STADISCONNECTED) {
        // Cliente desconectou. Verifica se a rede ficou vazia.
        update_led_state();
    }
}

static void shutdown_timer_callback(void* arg)
{
    // Verifica novamente o número de clientes antes de desligar
    wifi_sta_list_t client_list;
    if (esp_wifi_ap_get_sta_list(&client_list) == ESP_OK && client_list.num == 0) {
        ESP_LOGI(LOG_TAG, "Rede ociosa. Desligando o AP...");
        ESP_ERROR_CHECK(esp_wifi_stop());
        gpio_set_level(STATUS_LED_PIN, 1); // Apaga o LED
    }
}

static void update_led_state(void)
{
    wifi_sta_list_t client_list;
    if (esp_wifi_ap_get_sta_list(&client_list) == ESP_OK) {
        if (client_list.num > 0) {
            // Há clientes conectados: LED aceso, temporizador parado
            gpio_set_level(STATUS_LED_PIN, 0);
            esp_timer_stop(ap_shutdown_timer);
        } else {
            // Nenhum cliente: LED apagado, inicia temporizador de desligamento
            gpio_set_level(STATUS_LED_PIN, 1);
            esp_timer_start_once(ap_shutdown_timer, IDLE_TIMEOUT_US);
        }
    }
}

void app_main(void)
{
    setup_status_led();
    init_ap_service();
    
    // O loop principal pode entrar em sono leve para economizar energia
    // enquanto o AP é gerenciado por eventos e timers.
    while(1) {
        vTaskDelay(pdMS_TO_TICKS(1000));
    }
}

Solução de Problemas Comuns e Otimização

A rede AP não aparece no scan: Verifique se ssid_hidden está como 0. Certifique-se de que o canal (channel) está dentro da faixa permitida na sua região (ex: 1-13). Use um analisador WiFi para confirmar a transmissão de quadros de beacon.

Número limitado de conexões: O hardware do ESP32-C3 limita a 4 conexões AP simultâneas. Se mais forem necessárias, considere um design que alterne entre AP e STA ou utilize um chip mais capaz.

Alto consumo de energia no modo AP: O AP mantém rádio e processador ativos. Para aplicações alimentadas por bateria, implemente rigorosamente a estratégia de desligamento automático por inatividade, como demonstrado no código. O uso do esp_light_sleep_start() após esp_wifi_stop() pode reduzir drasticamente o consumo.

Problemas de IP/DHCP com clientes: Assegure-se de que CONFIG_LWIP_DHCP_SERVER esteja habilitado. Se os clientes não obtêm IP, verifique se a pool de endereços DHCP (configurada via CONFIG_LWIP_DHCP_MAX_LEASES) não está esgotada.

Tags: ESP32-C3 WiFi AP ESP-IDF SoftAP IoT

Publicado em 6-13 02:12 por Thomas