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.