Skip to content

LAB 03

Team

Yahir Gil Mendoza

Isaac Antonio Perez Aleman

Pablo Eduardo López Manzano

1) Activity Goals

  • Understand the Embedded Server: Set up and manage the lightweight esp_http_server within the ESP-IDF environment.

  • Configure URI Handlers: Register and map specific API routes for HTML interfaces and /api/led for JSON endpoints to their corresponding C functions.

  • Process HTTP Requests: Successfully read and parse incoming request bodie, particularly extracting JSON data from POST requests to control device hardware in this case a led.

  • Manage HTTP Headers: Assign appropriate Content-Type to server responses to ensure browsers correctly interpret them as text/html or application/json.

2) Materials

  • ESP32‑C6 with USB‑C cable (data-capable)
  • LED + 330 Ω resistor + jumper wires
  • protoboard
  • Motor DC

3) Procedure

  • First: we use the code given by the teacher, for follow how is the program, html and the IP.

Code 1: General code

/ * LAB 3 — ESP32-C6 Wi-Fi + HTTP LED Control * * Features: * - Wi-Fi STA connect + reconnect using events * - Wait for IP (WIFI_CONNECTED_BIT) * - Simple GPIO LED control (gpio_reset_pin + gpio_set_direction) * - HTTP server: * GET / -> HTML UI * GET /api/led -> JSON {"state":0|1} * POST /api/led -> JSON {"state":0|1} sets LED, returns {"ok":true} * / // String handling and standard libraries

include

include

include

// FreeRTOS and event groups

include "freertos/FreeRTOS.h"

include "freertos/event_groups.h"

// ESP-IDF Logging and error handling

include "esp_log.h"

include "esp_err.h"

// Wi-Fi and network

include "nvs_flash.h"

include "esp_netif.h"

include "esp_event.h"

include "esp_wifi.h"

// GPIO control

include "driver/gpio.h"

// HTTP server

include "esp_http_server.h"

/ ===================== User config ===================== /

define WIFI_SSID "SSID_HERE"

define WIFI_PASS "PASS_HERE"

/ LED pin /

define LED_GPIO 8

/ Reconnect policy /

define MAX_RETRY 10

/ ===================== Globals ===================== / static const char *TAG = "LAB_3";

// Wi-Fi event group and bit seen in Lab 2 static EventGroupHandle_t s_wifi_event_group;

define WIFI_CONNECTED_BIT BIT0

static int s_retry = 0;// Retry count for Wi-Fi reconnects

static int s_led_state = 0; // 0=OFF, 1=ON static httpd_handle_t s_server = NULL; // HTTP server handle

/ ===================== LED helpers ===================== / static void led_init(void) { gpio_reset_pin(LED_GPIO); gpio_set_direction(LED_GPIO, GPIO_MODE_OUTPUT);

s_led_state = 0;
gpio_set_level(LED_GPIO, s_led_state);

ESP_LOGI(TAG, "LED initialized on GPIO %d (state=%d)", LED_GPIO, s_led_state);

}

/Function to set the LED from the state/ static void led_set(int on) { s_led_state = (on != 0); gpio_set_level(LED_GPIO, s_led_state); ESP_LOGI(TAG, "LED set to %d", s_led_state); }

/ ===================== HTTP handlers ===================== / /Remember, handlers are special functions that process HTTP requests and generate responses/

static esp_err_t api_led_get(httpd_req_t req) { / resp is a buffer to hold the JSON response text in this case our jason is either {"state":0} or {"state":1} / char resp[32]; /sprintf is a normal printf for strings, snprintf is safer because it limits the number of characters written to the buffer

Here we build the JSON string with the current LED state. 
*/
snprintf(resp, sizeof(resp), "{\"state\":%d}", s_led_state);

/* Tell the client (browser/Postman/etc.) that the payload is JSON.
   This sets the HTTP header: Content-Type: application/json */
httpd_resp_set_type(req, "application/json");

/* Send the response body to the client.
   - 'resp' is the payload
   - HTTPD_RESP_USE_STRLEN tells ESP-IDF to compute the string length automatically
     (it treats resp as a null-terminated C string). */
httpd_resp_send(req, resp, HTTPD_RESP_USE_STRLEN);

/* Return ESP_OK so the HTTP server knows the request was handled correctly. */
return ESP_OK;

}

static esp_err_t api_led_post(httpd_req_t *req) { // Basic safety: reject empty or very large payloads if (req->content_len <= 0 || req->content_len > 256) { httpd_resp_send_err(req, HTTPD_400_BAD_REQUEST, "Invalid Content-Length"); return ESP_FAIL; }

char buf[257] = {0}; // +1 for null terminator
int received = httpd_req_recv(req, buf, req->content_len);
if (received <= 0) {
    httpd_resp_send_err(req, HTTPD_400_BAD_REQUEST, "Empty body");
    return ESP_FAIL;
}
buf[received] = '\0';

// Minimal parse: find "state":<number>
int state = -1;
char *p = strstr(buf, "\"state\"");
if (p) {
    p = strchr(p, ':');
    if (p) state = atoi(p + 1);
}

if (state != 0 && state != 1) {
    httpd_resp_send_err(req, HTTPD_400_BAD_REQUEST, "state must be 0 or 1");
    return ESP_FAIL;
}

led_set(state);

httpd_resp_set_type(req, "application/json");
httpd_resp_sendstr(req, "{\"ok\":true}");
return ESP_OK;

}

static esp_err_t root_get_handler(httpd_req_t req) { // Readable inline HTML static const char INDEX_HTML = "<!doctype html>\n" "\n" "\n" " \n" " \n" " ESP32-C6 LED\n" "\n" "\n" "

ESP32-C6 LED Control

\n" " \n" " \n" "

State: ?

\n" "\n" " \n" "\n" "\n";

httpd_resp_set_type(req, "text/html");
httpd_resp_send(req, INDEX_HTML, HTTPD_RESP_USE_STRLEN);
return ESP_OK;

}

static void http_server_start(void) { httpd_config_t config = HTTPD_DEFAULT_CONFIG(); ESP_ERROR_CHECK(httpd_start(&s_server, &config)); ESP_LOGI(TAG, "HTTP server started");

httpd_uri_t root = {
    .uri      = "/",
    .method   = HTTP_GET,
    .handler  = root_get_handler,
    .user_ctx = NULL
};

httpd_uri_t led_get = {
    .uri      = "/api/led",
    .method   = HTTP_GET,
    .handler  = api_led_get,
    .user_ctx = NULL
};

httpd_uri_t led_post = {
    .uri      = "/api/led",
    .method   = HTTP_POST,
    .handler  = api_led_post,
    .user_ctx = NULL
};

ESP_ERROR_CHECK(httpd_register_uri_handler(s_server, &root));
ESP_ERROR_CHECK(httpd_register_uri_handler(s_server, &led_get));
ESP_ERROR_CHECK(httpd_register_uri_handler(s_server, &led_post));

ESP_LOGI(TAG, "Routes registered: /  ,  GET/POST /api/led");

}

/ ===================== Wi-Fi STA connect + events ===================== /

static void wifi_event_handler(void arg, esp_event_base_t event_base, int32_t event_id, void event_data) { if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START) { ESP_LOGI(TAG, "WIFI_EVENT_STA_START -> esp_wifi_connect()"); ESP_ERROR_CHECK(esp_wifi_connect()); return; }

if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED) {
    if (s_retry < MAX_RETRY) {
        s_retry++;
        ESP_LOGW(TAG, "Disconnected. Retrying (%d/%d)...", s_retry, MAX_RETRY);
        ESP_ERROR_CHECK(esp_wifi_connect());
    } else {
        ESP_LOGE(TAG, "Failed to connect after %d retries.", MAX_RETRY);
    }
    return;
}

if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) {
    ip_event_got_ip_t *event = (ip_event_got_ip_t *)event_data;
    ESP_LOGI(TAG, "Got IP: " IPSTR, IP2STR(&event->ip_info.ip));

    s_retry = 0;
    xEventGroupSetBits(s_wifi_event_group, WIFI_CONNECTED_BIT);
    return;
}

}

static void wifi_init_sta(void) { s_wifi_event_group = xEventGroupCreate();

ESP_ERROR_CHECK(esp_netif_init());
ESP_ERROR_CHECK(esp_event_loop_create_default());
esp_netif_create_default_wifi_sta();

wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT();
ESP_ERROR_CHECK(esp_wifi_init(&cfg));

ESP_ERROR_CHECK(esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &wifi_event_handler, NULL));
ESP_ERROR_CHECK(esp_event_handler_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &wifi_event_handler, NULL));

wifi_config_t wifi_config = {0};
strncpy((char *)wifi_config.sta.ssid, WIFI_SSID, sizeof(wifi_config.sta.ssid));
strncpy((char *)wifi_config.sta.password, WIFI_PASS, sizeof(wifi_config.sta.password));

ESP_LOGI(TAG, "Configuring Wi-Fi STA: SSID='%s'", WIFI_SSID);

ESP_ERROR_CHECK(esp_wifi_set_mode(WIFI_MODE_STA));
ESP_ERROR_CHECK(esp_wifi_set_config(WIFI_IF_STA, &wifi_config));
ESP_ERROR_CHECK(esp_wifi_start());

}

/ ===================== app_main ===================== /

void app_main(void) { ESP_LOGI(TAG, "Lab D start: Wi-Fi + HTTP + LED control.");

// NVS init (required by Wi-Fi)
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());
    ESP_ERROR_CHECK(nvs_flash_init());
} else {
    ESP_ERROR_CHECK(ret);
}

// Connect to Wi-Fi (STA)
wifi_init_sta();

// Wait for "got IP" (connected)
EventBits_t bits = xEventGroupWaitBits(
    s_wifi_event_group,
    WIFI_CONNECTED_BIT,
    pdFALSE,
    pdTRUE,
    pdMS_TO_TICKS(30000)
);

if (!(bits & WIFI_CONNECTED_BIT)) {
    ESP_LOGE(TAG, "Timeout waiting for Wi-Fi connection. Check SSID/PASS and 2.4 GHz.");
    return;
}

// Start peripherals + HTTP
led_init();
http_server_start();

ESP_LOGI(TAG, "Open: http://<ESP_IP>/ from a device on the same network.");

}

  • Second: We have to add in the code the second led and change the .html for add another button.

Code 2: With 2 buttons and 2 leds

/ * LAB 3 — ESP32-C6 Wi-Fi + HTTP LED Control /

include

include

include "freertos/FreeRTOS.h"

include "freertos/event_groups.h"

include "esp_log.h"

include "esp_err.h"

include "nvs_flash.h"

include "esp_netif.h"

include "esp_event.h"

include "esp_wifi.h"

include "driver/gpio.h"

include "esp_http_server.h"

/ ===================== User config ===================== /

define WIFI_SSID "iPhone"

define WIFI_PASS "12345678"

define LED_GPIO 8

define LED2_GPIO 1 // Segundo LED agregado en GPIO 01

define MAX_RETRY 10

/ ===================== Globals ===================== / static const char *TAG = "LAB_3";

static EventGroupHandle_t s_wifi_event_group;

define WIFI_CONNECTED_BIT BIT0

static int s_retry = 0; static int s_led_state = 0; // 0=OFF, 1=ON static int s_led2_state = 0; // Estado para el segundo LED static httpd_handle_t s_server = NULL;

/ ===================== LED helpers ===================== / static void led_init(void) { // Inicializar LED 1 gpio_reset_pin(LED_GPIO); gpio_set_direction(LED_GPIO, GPIO_MODE_OUTPUT); s_led_state = 0; gpio_set_level(LED_GPIO, s_led_state);

// Inicializar LED 2 (GPIO 01)
gpio_reset_pin(LED2_GPIO);
gpio_set_direction(LED2_GPIO, GPIO_MODE_OUTPUT);
s_led2_state = 0;
gpio_set_level(LED2_GPIO, s_led2_state);

ESP_LOGI(TAG, "LEDs initialized: GPIO %d and GPIO %d", LED_GPIO, LED2_GPIO);

}

static void led_set(int on) { s_led_state = (on != 0); gpio_set_level(LED_GPIO, s_led_state); }

static void led2_set(int on) { s_led2_state = (on != 0); gpio_set_level(LED2_GPIO, s_led2_state); }

/ ===================== HTTP Handlers ===================== /

static esp_err_t root_get_handler(httpd_req_t req) { static const char INDEX_HTML = "<!doctype html>\n" "\n" " \n" " \n" " ESP32-C6 LED Control\n" "\n" "

ESP32-C6 LED Control

\n" "

Control LED 1 :

\n" "

\n" " \n" " \n" "

\n" "

Control LED 2 :

\n" "

\n" " \n" " \n" "

\n" "\n";

httpd_resp_set_type(req, "text/html");
httpd_resp_send(req, INDEX_HTML, HTTPD_RESP_USE_STRLEN);
return ESP_OK;

}

static esp_err_t ledon_get_handler(httpd_req_t req) { led_set(1); static const char RESP = "<!doctype html>

LED 1 is now: ON

"; httpd_resp_set_type(req, "text/html"); httpd_resp_send(req, RESP, HTTPD_RESP_USE_STRLEN); return ESP_OK; }

static esp_err_t ledoff_get_handler(httpd_req_t req) { led_set(0); static const char RESP = "<!doctype html>

LED 1 is now: OFF

"; httpd_resp_set_type(req, "text/html"); httpd_resp_send(req, RESP, HTTPD_RESP_USE_STRLEN); return ESP_OK; }

static esp_err_t led2on_get_handler(httpd_req_t req) { led2_set(1); static const char RESP = "<!doctype html>

LED 2 is now: ON

"; httpd_resp_set_type(req, "text/html"); httpd_resp_send(req, RESP, HTTPD_RESP_USE_STRLEN); return ESP_OK; }

static esp_err_t led2off_get_handler(httpd_req_t req) { led2_set(0); static const char RESP = "<!doctype html>

LED 2 is now: OFF

"; httpd_resp_set_type(req, "text/html"); httpd_resp_send(req, RESP, HTTPD_RESP_USE_STRLEN); return ESP_OK; }

/ ===================== HTTP Server Start + Route Registration ===================== /

static void http_server_start(void) { httpd_config_t config = HTTPD_DEFAULT_CONFIG(); ESP_ERROR_CHECK(httpd_start(&s_server, &config));

httpd_uri_t root = { .uri = "/", .method = HTTP_GET, .handler = root_get_handler };
httpd_uri_t ledon = { .uri = "/ledon", .method = HTTP_GET, .handler = ledon_get_handler };
httpd_uri_t ledoff = { .uri = "/ledoff", .method = HTTP_GET, .handler = ledoff_get_handler };
httpd_uri_t led2on = { .uri = "/led2on", .method = HTTP_GET, .handler = led2on_get_handler };
httpd_uri_t led2off = { .uri = "/led2off", .method = HTTP_GET, .handler = led2off_get_handler };

ESP_ERROR_CHECK(httpd_register_uri_handler(s_server, &root));
ESP_ERROR_CHECK(httpd_register_uri_handler(s_server, &ledon));
ESP_ERROR_CHECK(httpd_register_uri_handler(s_server, &ledoff));
ESP_ERROR_CHECK(httpd_register_uri_handler(s_server, &led2on));
ESP_ERROR_CHECK(httpd_register_uri_handler(s_server, &led2off));

ESP_LOGI(TAG, "Routes registered: LED 1 and LED 2 controls available.");

}

/ ===================== Wi-Fi STA connect + events (Sin cambios) ===================== /

static void wifi_event_handler(void arg, esp_event_base_t event_base, int32_t event_id, void event_data) { if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START) { esp_wifi_connect(); } else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED) { if (s_retry < MAX_RETRY) { s_retry++; esp_wifi_connect(); } } else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) { s_retry = 0; xEventGroupSetBits(s_wifi_event_group, WIFI_CONNECTED_BIT); } }

static void wifi_init_sta(void) { s_wifi_event_group = xEventGroupCreate(); esp_netif_init(); esp_event_loop_create_default(); esp_netif_create_default_wifi_sta(); wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); esp_wifi_init(&cfg); esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &wifi_event_handler, NULL); esp_event_handler_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &wifi_event_handler, NULL); wifi_config_t wifi_config = {0}; strncpy((char )wifi_config.sta.ssid, WIFI_SSID, sizeof(wifi_config.sta.ssid)); strncpy((char )wifi_config.sta.password, WIFI_PASS, sizeof(wifi_config.sta.password)); esp_wifi_set_mode(WIFI_MODE_STA); esp_wifi_set_config(WIFI_IF_STA, &wifi_config); esp_wifi_start(); }

/ ===================== app_main ===================== /

void app_main(void) { 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()); ESP_ERROR_CHECK(nvs_flash_init()); } wifi_init_sta(); xEventGroupWaitBits(s_wifi_event_group, WIFI_CONNECTED_BIT, pdFALSE, pdTRUE, pdMS_TO_TICKS(30000));

led_init();
http_server_start();

}

  • Third: For this step, we hace to add a counter, this counter is for when we push on or off, the counter will go count each push.

Code 3: Add the counter.

/ * LAB 3 — ESP32-C6 Wi-Fi + HTTP LED Control + Auto-Refresh Counter /

include

include

include "freertos/FreeRTOS.h"

include "freertos/task.h"

include "freertos/event_groups.h"

include "esp_log.h"

include "esp_err.h"

include "nvs_flash.h"

include "esp_netif.h"

include "esp_event.h"

include "esp_wifi.h"

include "driver/gpio.h"

include "esp_http_server.h"

/ ===================== User config ===================== /

define WIFI_SSID "Xr Yahir"

define WIFI_PASS "12345678"

define LED_GPIO 8

define LED2_GPIO 1

define BTN_GPIO 4

define MAX_RETRY 10

/ ===================== Globals ===================== / static const char *TAG = "LAB_3";

static EventGroupHandle_t s_wifi_event_group;

define WIFI_CONNECTED_BIT BIT0

static int s_retry = 0; static int s_led_state = 0;
static int s_led2_state = 0;
static int s_btn_counter = 0;
static httpd_handle_t s_server = NULL;

/ ===================== Peripherals helpers ===================== / static void led_init(void) { gpio_reset_pin(LED_GPIO); gpio_set_direction(LED_GPIO, GPIO_MODE_OUTPUT); s_led_state = 0; gpio_set_level(LED_GPIO, s_led_state);

gpio_reset_pin(LED2_GPIO);
gpio_set_direction(LED2_GPIO, GPIO_MODE_OUTPUT);
s_led2_state = 0;
gpio_set_level(LED2_GPIO, s_led2_state);

gpio_reset_pin(BTN_GPIO);
gpio_set_direction(BTN_GPIO, GPIO_MODE_INPUT);
gpio_pullup_en(BTN_GPIO);

ESP_LOGI(TAG, "LEDs and Button initialized.");

}

void button_task(void *pvParameter) { int last_state = 1; while(1) { int current_state = gpio_get_level(BTN_GPIO); if (last_state == 1 && current_state == 0) { s_btn_counter++; vTaskDelay(pdMS_TO_TICKS(200)); } last_state = current_state; vTaskDelay(pdMS_TO_TICKS(50)); } }

static void led_set(int on) { s_led_state = (on != 0); gpio_set_level(LED_GPIO, s_led_state); }

static void led2_set(int on) { s_led2_state = (on != 0); gpio_set_level(LED2_GPIO, s_led2_state); }

/ ===================== HTTP Handlers ===================== /

static esp_err_t status_get_handler(httpd_req_t *req) { char resp[16]; snprintf(resp, sizeof(resp), "%d", s_btn_counter); httpd_resp_send(req, resp, HTTPD_RESP_USE_STRLEN); return ESP_OK; }

static esp_err_t root_get_handler(httpd_req_t req) { static const char INDEX_HTML = "<!doctype html>\n" "\n" " \n" " \n" " ESP32-C6 LED Control\n" "\n" "

ESP32-C6 LED Control

\n"

    "  <p><strong>Control LED 1 :</strong></p>\n"
    "  <p>\n"
    "    <a href='/ledon'><button>LED 1 ON</button></a>\n"
    "    <a href='/ledoff'><button>LED 1 OFF</button></a>\n"
    "  </p>\n"
    "  <p><strong>Control LED 2 :</strong></p>\n"
    "  <p>\n"
    "    <a href='/led2on'><button>LED 2 ON</button></a>\n"
    "    <a href='/led2off'><button>LED 2 OFF</button></a>\n"
    "  <p><strong>Contador: <span id='v'>0</span></strong></p>\n"

    "  </p>\n"
    "  <script>\n"
    "    function refresh() {\n"
    "      fetch('/status').then(r => r.text()).then(d => {\n"
    "        document.getElementById('v').innerText = d;\n"
    "      });\n"
    "    }\n"
    "    setInterval(refresh, 1000);\n"
    "    refresh();\n"
    "  </script>\n"
    "</body></html>\n";

httpd_resp_set_type(req, "text/html");
httpd_resp_send(req, INDEX_HTML, HTTPD_RESP_USE_STRLEN);
return ESP_OK;

}

static esp_err_t ledon_get_handler(httpd_req_t req) { led_set(1); static const char RESP = "<!doctype html>

LED 1 is now: ON

"; httpd_resp_send(req, RESP, HTTPD_RESP_USE_STRLEN); return ESP_OK; }

static esp_err_t ledoff_get_handler(httpd_req_t req) { led_set(0); static const char RESP = "<!doctype html>

LED 1 is now: OFF

"; httpd_resp_send(req, RESP, HTTPD_RESP_USE_STRLEN); return ESP_OK; }

static esp_err_t led2on_get_handler(httpd_req_t req) { led2_set(1); static const char RESP = "<!doctype html>

LED 2 is now: ON

"; httpd_resp_send(req, RESP, HTTPD_RESP_USE_STRLEN); return ESP_OK; }

static esp_err_t led2off_get_handler(httpd_req_t req) { led2_set(0); static const char RESP = "<!doctype html>

LED 2 is now: OFF

"; httpd_resp_send(req, RESP, HTTPD_RESP_USE_STRLEN); return ESP_OK; }

/ ===================== HTTP Server Start ===================== /

static void http_server_start(void) { httpd_config_t config = HTTPD_DEFAULT_CONFIG(); ESP_ERROR_CHECK(httpd_start(&s_server, &config));

httpd_uri_t root = { .uri = "/", .method = HTTP_GET, .handler = root_get_handler };
httpd_uri_t stat = { .uri = "/status", .method = HTTP_GET, .handler = status_get_handler };
httpd_uri_t ledon = { .uri = "/ledon", .method = HTTP_GET, .handler = ledon_get_handler };
httpd_uri_t ledoff = { .uri = "/ledoff", .method = HTTP_GET, .handler = ledoff_get_handler };
httpd_uri_t led2on = { .uri = "/led2on", .method = HTTP_GET, .handler = led2on_get_handler };
httpd_uri_t led2off = { .uri = "/led2off", .method = HTTP_GET, .handler = led2off_get_handler };

httpd_register_uri_handler(s_server, &root);
httpd_register_uri_handler(s_server, &stat);
httpd_register_uri_handler(s_server, &ledon);
httpd_register_uri_handler(s_server, &ledoff);
httpd_register_uri_handler(s_server, &led2on);
httpd_register_uri_handler(s_server, &led2off);

}

/ ===================== Wi-Fi STA (Sin cambios) ===================== /

static void wifi_event_handler(void arg, esp_event_base_t event_base, int32_t event_id, void event_data) { if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START) esp_wifi_connect(); else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED) { if (s_retry < MAX_RETRY) { s_retry++; esp_wifi_connect(); } } else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) { s_retry = 0; xEventGroupSetBits(s_wifi_event_group, WIFI_CONNECTED_BIT); } }

static void wifi_init_sta(void) { s_wifi_event_group = xEventGroupCreate(); esp_netif_init(); esp_event_loop_create_default(); esp_netif_create_default_wifi_sta(); wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); esp_wifi_init(&cfg); esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &wifi_event_handler, NULL); esp_event_handler_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &wifi_event_handler, NULL); 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(); }

void app_main(void) { 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()); ESP_ERROR_CHECK(nvs_flash_init()); } wifi_init_sta(); xEventGroupWaitBits(s_wifi_event_group, WIFI_CONNECTED_BIT, pdFALSE, pdTRUE, portMAX_DELAY);

led_init();
xTaskCreate(button_task, "button_task", 2048, NULL, 5, NULL);
http_server_start();

}

  • Fourth: Finally we add to the code the slider for control a dc motor.

Code 4: Slider for control DC motor

include

include

include

include "freertos/FreeRTOS.h"

include "freertos/task.h"

include "freertos/event_groups.h"

include "esp_log.h"

include "esp_err.h"

include "nvs_flash.h"

include "esp_netif.h"

include "esp_event.h"

include "esp_wifi.h"

include "driver/gpio.h"

include "driver/ledc.h" // Librería para PWM (Motor)

include "esp_http_server.h"

/ ===================== User config ===================== /

define WIFI_SSID "Xr Yahir"

define WIFI_PASS "12345678"

define LED_GPIO 8

define LED2_GPIO 1

define BTN_GPIO 4

define MOTOR_GPIO 6 // Motor en GPIO 06

define MAX_RETRY 10

// Configuración PWM Motor

define LEDC_TIMER LEDC_TIMER_0

define LEDC_MODE LEDC_LOW_SPEED_MODE

define LEDC_CHANNEL LEDC_CHANNEL_0

define LEDC_DUTY_RES LEDC_TIMER_10_BIT // Resolución de 0 a 1023

define LEDC_FREQUENCY (5000) // 5 kHz

/ ===================== Globals ===================== / static const char *TAG = "LAB_3"; static EventGroupHandle_t s_wifi_event_group;

define WIFI_CONNECTED_BIT BIT0

static int s_retry = 0; static int s_led_state = 0;
static int s_led2_state = 0;
static int s_btn_counter = 0;
static httpd_handle_t s_server = NULL;

/ ===================== Peripherals helpers ===================== / static void peripherals_init(void) { // LEDs gpio_reset_pin(LED_GPIO); gpio_set_direction(LED_GPIO, GPIO_MODE_OUTPUT); gpio_set_level(LED_GPIO, 0);

gpio_reset_pin(LED2_GPIO);
gpio_set_direction(LED2_GPIO, GPIO_MODE_OUTPUT);
gpio_set_level(LED2_GPIO, 0);

// Botón
gpio_reset_pin(BTN_GPIO);
gpio_set_direction(BTN_GPIO, GPIO_MODE_INPUT);
gpio_pullup_en(BTN_GPIO);

// Configuración PWM para el Motor (GPIO 06)
ledc_timer_config_t ledc_timer = {
    .speed_mode       = LEDC_MODE,
    .timer_num        = LEDC_TIMER,
    .duty_resolution  = LEDC_DUTY_RES,
    .freq_hz          = LEDC_FREQUENCY,
    .clk_cfg          = LEDC_AUTO_CLK
};
ledc_timer_config(&ledc_timer);

ledc_channel_config_t ledc_channel = {
    .speed_mode     = LEDC_MODE,
    .channel        = LEDC_CHANNEL,
    .timer_sel      = LEDC_TIMER,
    .intr_type      = LEDC_INTR_DISABLE,
    .gpio_num       = MOTOR_GPIO,
    .duty           = 0, // Inicia apagado
    .hpoint         = 0
};
ledc_channel_config(&ledc_channel);

ESP_LOGI(TAG, "Peripherals (LEDs, Button, Motor PWM) initialized.");

}

void button_task(void *pvParameter) { int last_state = 1; while(1) { int current_state = gpio_get_level(BTN_GPIO); if (last_state == 1 && current_state == 0) { s_btn_counter++; vTaskDelay(pdMS_TO_TICKS(200)); } last_state = current_state; vTaskDelay(pdMS_TO_TICKS(50)); } }

static void led_set(int on) { s_led_state = (on != 0); gpio_set_level(LED_GPIO, s_led_state); }

static void led2_set(int on) { s_led2_state = (on != 0); gpio_set_level(LED2_GPIO, s_led2_state); }

/ ===================== HTTP Handlers ===================== /

static esp_err_t status_get_handler(httpd_req_t *req) { char resp[16]; snprintf(resp, sizeof(resp), "%d", s_btn_counter); httpd_resp_send(req, resp, HTTPD_RESP_USE_STRLEN); return ESP_OK; }

// Handler para la velocidad del motor static esp_err_t motor_set_handler(httpd_req_t *req) { char buf[10]; int ret = httpd_req_get_url_query_str(req, buf, sizeof(buf)); if (ret == ESP_OK) { char val_str[10]; if (httpd_query_key_value(buf, "v", val_str, sizeof(val_str)) == ESP_OK) { int speed = atoi(val_str); // Valor de 0 a 100 uint32_t duty = (speed * 1023) / 100; // Mapeo a resolución de 10 bits ledc_set_duty(LEDC_MODE, LEDC_CHANNEL, duty); ledc_update_duty(LEDC_MODE, LEDC_CHANNEL); } } httpd_resp_send(req, NULL, 0); return ESP_OK; }

static esp_err_t root_get_handler(httpd_req_t req) { static const char INDEX_HTML = "<!doctype html>\n" "\n" " \n" " \n" " ESP32-C6 Control\n" "\n" "

ESP32-C6 LED Control

\n" "

Control LED 1 :

\n" "

\n" " \n" " \n" "

\n" "

Control LED 2 :

\n" "

\n" " \n" " \n" "

\n" "

Contador: 0

\n" "
\n" "

Velocidad del Motor

\n" " \n" " \n" "\n";

httpd_resp_set_type(req, "text/html");
httpd_resp_send(req, INDEX_HTML, HTTPD_RESP_USE_STRLEN);
return ESP_OK;

}

static esp_err_t ledon_get_handler(httpd_req_t req) { led_set(1); static const char RESP = "<!doctype html>

LED 1 is now: ON

"; httpd_resp_send(req, RESP, HTTPD_RESP_USE_STRLEN); return ESP_OK; }

static esp_err_t ledoff_get_handler(httpd_req_t req) { led_set(0); static const char RESP = "<!doctype html>

LED 1 is now: OFF

"; httpd_resp_send(req, RESP, HTTPD_RESP_USE_STRLEN); return ESP_OK; }

static esp_err_t led2on_get_handler(httpd_req_t req) { led2_set(1); static const char RESP = "<!doctype html>

LED 2 is now: ON

"; httpd_resp_send(req, RESP, HTTPD_RESP_USE_STRLEN); return ESP_OK; }

static esp_err_t led2off_get_handler(httpd_req_t req) { led2_set(0); static const char RESP = "<!doctype html>

LED 2 is now: OFF

"; httpd_resp_send(req, RESP, HTTPD_RESP_USE_STRLEN); return ESP_OK; }

/ ===================== HTTP Server Start ===================== /

static void http_server_start(void) { httpd_config_t config = HTTPD_DEFAULT_CONFIG(); ESP_ERROR_CHECK(httpd_start(&s_server, &config));

httpd_uri_t root = { .uri = "/", .method = HTTP_GET, .handler = root_get_handler };
httpd_uri_t stat = { .uri = "/status", .method = HTTP_GET, .handler = status_get_handler };
httpd_uri_t mtr  = { .uri = "/motor",  .method = HTTP_GET, .handler = motor_set_handler };
httpd_uri_t ledon = { .uri = "/ledon", .method = HTTP_GET, .handler = ledon_get_handler };
httpd_uri_t ledoff = { .uri = "/ledoff", .method = HTTP_GET, .handler = ledoff_get_handler };
httpd_uri_t led2on = { .uri = "/led2on", .method = HTTP_GET, .handler = led2on_get_handler };
httpd_uri_t led2off = { .uri = "/led2off", .method = HTTP_GET, .handler = led2off_get_handler };

httpd_register_uri_handler(s_server, &root);
httpd_register_uri_handler(s_server, &stat);
httpd_register_uri_handler(s_server, &mtr);
httpd_register_uri_handler(s_server, &ledon);
httpd_register_uri_handler(s_server, &ledoff);
httpd_register_uri_handler(s_server, &led2on);
httpd_register_uri_handler(s_server, &led2off);

}

/ ===================== Wi-Fi STA ===================== /

static void wifi_event_handler(void arg, esp_event_base_t event_base, int32_t event_id, void event_data) { if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_START) esp_wifi_connect(); else if (event_base == WIFI_EVENT && event_id == WIFI_EVENT_STA_DISCONNECTED) { if (s_retry < MAX_RETRY) { s_retry++; esp_wifi_connect(); } } else if (event_base == IP_EVENT && event_id == IP_EVENT_STA_GOT_IP) { s_retry = 0; xEventGroupSetBits(s_wifi_event_group, WIFI_CONNECTED_BIT); } }

static void wifi_init_sta(void) { s_wifi_event_group = xEventGroupCreate(); esp_netif_init(); esp_event_loop_create_default(); esp_netif_create_default_wifi_sta(); wifi_init_config_t cfg = WIFI_INIT_CONFIG_DEFAULT(); esp_wifi_init(&cfg); esp_event_handler_register(WIFI_EVENT, ESP_EVENT_ANY_ID, &wifi_event_handler, NULL); esp_event_handler_register(IP_EVENT, IP_EVENT_STA_GOT_IP, &wifi_event_handler, NULL); 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(); }

void app_main(void) { 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()); ESP_ERROR_CHECK(nvs_flash_init()); } wifi_init_sta(); xEventGroupWaitBits(s_wifi_event_group, WIFI_CONNECTED_BIT, pdFALSE, pdTRUE, portMAX_DELAY);

peripherals_init();
xTaskCreate(button_task, "button_task", 2048, NULL, 5, NULL);
http_server_start();

}

Results

  • 2 leds and 2 buttons in the page

Diagrama del sistema

  • The 2 buttons in the page

Diagrama del sistema

  • 2 buttons, 2 leds and the button for counter

Diagrama del sistema

  • Page

Diagrama del sistema

  • Motor DC and the slider

Diagrama del sistema

  • Motor DC run

Video motor DC]