No tienes acceso a esta clase

¡Continúa aprendiendo! Únete y comienza a potenciar tu carrera

Dimmer LED via HTTP con ESP32

28/30
Recursos

Aportes 5

Preguntas 5

Ordenar por:

¿Quieres ver más aportes, preguntas y respuestas de la comunidad?

Buenos días comunidad!!
Quería contarles mi experiencia con este programa…

  1. Para que funcione con valores de RGB mayores de 99, tuve que cambiar en dimmer.c, param[3] por param[4].
  2. Con un osciloscopio puede observar que para alcanzar un duty-cicle de 100%, tengo que poner r, g o b en 256 y no en 255 como podría creerse, lo cual es curioso porque tenemos
    #define LEDC_DUTY_RES LEDC_TIMER_8_BIT
    y 256 son 9 bits.

El programa en el estudio, y el esp32 con bateria en la sala.

El codigo en c:
.
.

#include <stdio.h>
#include "string.h"
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/gpio.h"
#include "driver/ledc.h"
#include "esp_wifi.h"
#include "nvs_flash.h"
#include "protocol_examples_common.h"
#include "esp_http_server.h"
#include "paginaGet.h"


//******************** task refresh_led *****************************

#define          LED_PIN        25
bool             state_led    = false;
const TickType_t blink_delay  = 1000 / portTICK_PERIOD_MS;
TaskHandle_t     ledHandle;

void refresh_led(void *args)
{
    while (true)
    {
        state_led = !state_led;
        gpio_set_level(LED_PIN, state_led);
        vTaskDelay(blink_delay);
    }     
}

//***************** manejo del led RGB *************************************

#define LED_RED_PIN   4
#define LED_GREEN_PIN 0
#define LED_BLUE_PIN  12

#define LEDC_CHANNEL_RED   LEDC_CHANNEL_0
#define LEDC_CHANNEL_GREEN LEDC_CHANNEL_1
#define LEDC_CHANNEL_BLUE  LEDC_CHANNEL_2

void set_rgb_led(int32_t dutyRed, int32_t dutyGreen, int32_t dutyBlue)
{
    ESP_ERROR_CHECK(ledc_set_duty(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_RED, dutyRed));
    ESP_ERROR_CHECK(ledc_update_duty(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_RED));  
    
    ESP_ERROR_CHECK(ledc_set_duty(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_GREEN, dutyGreen));
    ESP_ERROR_CHECK(ledc_update_duty(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_GREEN));  

    ESP_ERROR_CHECK(ledc_set_duty(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_BLUE, dutyBlue));
    ESP_ERROR_CHECK(ledc_update_duty(LEDC_HIGH_SPEED_MODE, LEDC_CHANNEL_BLUE));  
}

//**************************manejo de wifi *************************************
esp_netif_ip_info_t ip_info;
esp_netif_t* netif = NULL;


//**************************manejo de web server ******************************

static esp_err_t home_get_handler(httpd_req_t *req)
{
    httpd_resp_send(req, resp, HTTPD_RESP_USE_STRLEN);
    return ESP_OK;
};

static const httpd_uri_t home = {
    .uri = "/",
    .method = HTTP_GET,
    .handler = home_get_handler
};

static esp_err_t setRGB_get_handler(httpd_req_t *req)
{
    int32_t dutyRed   = 0; 
    int32_t dutyGreen = 0; 
    int32_t dutyBlue  = 0;

    size_t buf_len;
    char* buf;
    buf_len = httpd_req_get_url_query_len(req) + 1;

    if (buf_len > 1)
    {
        buf = malloc(buf_len);
        if ( httpd_req_get_url_query_str(req, buf, buf_len) == ESP_OK )
        {
            printf("longitud : %d\n", buf_len);
            printf("contenido: %s\n", buf);

            char param[4];
            if (httpd_query_key_value(buf, "r", param, sizeof(param)) == ESP_OK)
            {
                printf("r param: %s\n", param);
                dutyRed = atoi(param);
            }
            if (httpd_query_key_value(buf, "g", param, sizeof(param)) == ESP_OK)
            {
                printf("g param: %s\n", param);
                dutyGreen = atoi(param);
            }
            if (httpd_query_key_value(buf, "b", param, sizeof(param)) == ESP_OK)
            {
                printf("b param: %s\n", param);
                dutyBlue = atoi(param);
            }
            free(buf);
            printf("r: %ld,  g: %ld,  b: %ld\n", dutyRed, dutyGreen, dutyBlue);
            set_rgb_led(dutyRed, dutyGreen, dutyBlue);

            httpd_resp_set_hdr(req, "Content-Type", "application/json");

            char resp1[30];
            sprintf(resp1,"{\"r\": %ld, \"g\": %ld, \"b\": %ld}", dutyRed, dutyGreen, dutyBlue);
            httpd_resp_send(req, resp1, HTTPD_RESP_USE_STRLEN);

        }    
    }    

    
    return ESP_OK;
};

static const httpd_uri_t setRGB = {
    .uri = "/RGB",
    .method = HTTP_GET,
    .handler = setRGB_get_handler
};


void web_server_init()
{
    httpd_handle_t server = NULL;
    httpd_config_t config = HTTPD_DEFAULT_CONFIG();
    
    if (httpd_start(&server, &config) == ESP_OK)
    {
        httpd_register_uri_handler(server, &home);
        httpd_register_uri_handler(server, &setRGB);
        return;
    } 
    else 
    {
        printf("Error al iniciar el servidor\n");
    };

};


void app_main(void)

{
    
    // ********************Creacion de la tarea para refrescar el led *****************************************
    //reset pines de salida
    gpio_reset_pin(LED_PIN);

    // coloca los pines en estado de salida o entrada
    gpio_set_direction(LED_PIN, GPIO_MODE_OUTPUT);

    //creamos la tarea asociandola al segundo core
    xTaskCreatePinnedToCore(
        refresh_led,    //Nombre de la funcion que implementa la tarea
        "refresh_led",  //Nombre descriptivo de la tarea con fines de debugging
        2048,           //El tamaño del task stack en bytes
        NULL,           //pointer a un parametro cuando la tarea esta siendo creada
        5,              //Prioridad de la tarea un numero
        &ledHandle,     //apuntador para referenciar la tarea. 
        1               // core 0 y core 1
    );

    // **************** manejo de LED RGB con LedC ***********************
    //pwm timer config 
    ledc_timer_config_t ledc_timer = {
        .speed_mode       = LEDC_HIGH_SPEED_MODE,
        .duty_resolution  = LEDC_TIMER_8_BIT,
        .timer_num        = LEDC_TIMER_0,
        .freq_hz          = 4000,  // Set output frequency at 4 kHz
        .clk_cfg          = LEDC_AUTO_CLK
    };
    ESP_ERROR_CHECK(ledc_timer_config(&ledc_timer));

    // Prepare and then apply the LEDC PWM channel configuration
    ledc_channel_config_t ledc_channel_red = {
        .speed_mode     = LEDC_HIGH_SPEED_MODE,
        .channel        = LEDC_CHANNEL_RED,
        .timer_sel      = LEDC_TIMER_0,
        .intr_type      = LEDC_INTR_DISABLE,
        .gpio_num       = LED_RED_PIN,
        .duty           = 0, // Set duty to 0%
        .hpoint         = 0
    };
    ESP_ERROR_CHECK(ledc_channel_config(&ledc_channel_red));

    ledc_channel_config_t ledc_channel_green = {
        .speed_mode     = LEDC_HIGH_SPEED_MODE,
        .channel        = LEDC_CHANNEL_GREEN,
        .timer_sel      = LEDC_TIMER_0,
        .intr_type      = LEDC_INTR_DISABLE,
        .gpio_num       = LED_GREEN_PIN,
        .duty           = 0, // Set duty to 0%
        .hpoint         = 0
    };
    ESP_ERROR_CHECK(ledc_channel_config(&ledc_channel_green));

    ledc_channel_config_t ledc_channel_blue = {
        .speed_mode     = LEDC_HIGH_SPEED_MODE,
        .channel        = LEDC_CHANNEL_BLUE,
        .timer_sel      = LEDC_TIMER_0,
        .intr_type      = LEDC_INTR_DISABLE,
        .gpio_num       = LED_BLUE_PIN,
        .duty           = 0, // Set duty to 0%
        .hpoint         = 0
    };
    ESP_ERROR_CHECK(ledc_channel_config(&ledc_channel_blue));


    //************************ manejo del wifi y arranque web server******************************

    nvs_flash_init();

    esp_netif_init();

    esp_event_loop_create_default();
 
    example_connect();

    netif = esp_netif_get_handle_from_ifkey("WIFI_STA_DEF");

    if (netif == NULL)
    {
        printf("No hay interfaz\n");
    }
    else 
    {
        esp_netif_get_ip_info(netif, &ip_info);
        printf("************************************************************\n");
        printf("IP       : %d.%d.%d.%d\n", IP2STR(&ip_info.ip));
        printf("Net mask : %d.%d.%d.%d\n", IP2STR(&ip_info.netmask));
        printf("Gateway  : %d.%d.%d.%d\n", IP2STR(&ip_info.gw));

         web_server_init();
    };
     
}

.
.
El codigo en html. sin la parte del svg, para evitar su publicacion contiene enlace a sitios no seguros
.
.

char resp[] = R"=====(
<!DOCTYPE html>
<html lang="sp">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Document</title>
    <style>
        body {
            background-color: #98CA3F;
        }
        h1 {
            text-align: center;
        }
        .container {
            display: flex;
            justify-content: center;
            padding-bottom: 50px;
        }
        .vertContainer {
            display:flex;
            flex-direction: column;
            justify-content: center;
        }
        .slider_container {
            display:flex;
            flex-direction: row;
            flex-wrap: wrap;
            justify-content: space-around;
        }
        .redSlider {
            accent-color: red;
        }
        .greenSlider {
            accent-color: green;
        }
        .bluelider {
            accent-color: blue;
        }
        table {
            background-color: whitesmoke;
        }
                    
    </style>
</head>
<body onload="colorChange()">
    <h1>Sliders - curso de microcontroladores ESP32</h1>
    <div class="container">
        <svg></svg>
    </div>
    <div class="slider_container">
        <table>
            <tr>
                <th>Led</td>
                <th>Control</td>
                <th>Valor</td>
                <th>Color</td>
                <th>Resultado</td>
            </tr> 
            <tbody>   
            <tr>
                <td>Red </td> 
                <td><input type="range" min="0" max="255" value="127" class="redSlider"   id="redRange" oninput="colorChange()"></td>
                <td id="redValue">127</td>
                <td id="redColor"></td>
                <td id="resColor" rowspan="3"></td>
            </tr>
            <tr>
                <td>Green</td>
                <td><input type="range" min="0" max="255" value="127" class="greenSlider" id="greenRange" oninput="colorChange()"></td>
                <td id="greenValue">127</td>
                <td id="greenColor"></td>
            </tr>
                <tr>
                    <td>Blue</td>
                    <td><input type="range" min="0" max="255" value="127" class="blueSlider"  id="blueRange" oninput="colorChange()"></td>
                    <td id="blueValue">127</td>
                    <td id="blueColor"></td>
                </tr>
            </tbody>
        </table>
        <div class="vertContainer"><input type="button" value="Enviar al ESP32" class="boton" onclick="setRGB()"></div>
        <textarea name="respuesta" id="respuesta" cols="30" rows="10"></textarea>
    </div>
    <script>
        function colorChange() {
            let rC, gC, bC;
            rC = document.getElementById("redRange").value; 
            gC = document.getElementById("greenRange").value; 
            bC = document.getElementById("blueRange").value;
            document.getElementById("redValue").innerHTML   = rC;
            document.getElementById("greenValue").innerHTML = gC;
            document.getElementById("blueValue").innerHTML  = bC
            document.getElementById("redColor").style.backgroundColor = 'rgb(' + rC + ',' + 0 + ',' + 0 + ')';
            document.getElementById("greenColor").style.backgroundColor = 'rgb(' + 0 + ',' + gC + ',' + 0 + ')';
            document.getElementById("blueColor").style.backgroundColor = 'rgb(' + 0 + ',' + 0 + ',' + bC + ')';
            document.getElementById("resColor").style.backgroundColor = 'rgb(' + rC + ',' + gC + ',' + bC + ')';
        }
        function setRGB() {
            let rC, gC, bC;
         
            rC = document.getElementById("redRange").value; 
            gC = document.getElementById("greenRange").value; 
            bC = document.getElementById("blueRange").value;
            
            let url;
            url = "/RGB?r=" + rC + "&g=" + gC + "&b=" + bC;
               
            let xhr = new XMLHttpRequest();
            xhr.open("GET", url, true);
            xhr.setRequestHeader("Content-Type", "application/json");
            xhr.onreadystatechange = function () {
                if (xhr.readyState === 4 && xhr.status === 200) {
                    document.getElementById("respuesta").innerHTML = xhr.responseText;
                }  
            };
            xhr.send();   
        }
    </script>
</body>
</html>    
)=====";    
En caso de que a alguien le sirva: Tengan en cuenta que existen dos tipos de LEDs RGB: de ánodo común y de cátodo común. Según entiendo, en el curso se utiliza uno de cátodo común. En mi caso, poseo uno de ánodo común. Esto quiere decir que el pin más largo debe ir a positivo en vez de a negativo, el resto queda todo igual. Además de eso, luego me di cuenta que los colores no funcionaban como esperaba. Esto es porque funciona "al revés", al llevarlo a 255 pasa a apagado, y en 0 está a su máxima potencia. También, como dijo otra persona en los comentarios, en vez de 255 hay que usar 256 como máximo valor, en mi caso para alcanzar realmente ese estado de 100% apagado. Dejo un snippet de mi método para actualizar los colores, donde abstraigo todo esto en un único lugar para no afectar al resto del código. ```java void update_leds() { // workaround for common anode RGB LED uint32_t inverted_duty_r = 256 - led_r; uint32_t inverted_duty_g = 256 - led_g; uint32_t inverted_duty_b = 256 - led_b; ledc_set_duty(LEDC_MODE, LEDC_CHANNEL_R, inverted_duty_r); ledc_update_duty(LEDC_MODE, LEDC_CHANNEL_R); ledc_set_duty(LEDC_MODE, LEDC_CHANNEL_G, inverted_duty_g); ledc_update_duty(LEDC_MODE, LEDC_CHANNEL_G); ledc_set_duty(LEDC_MODE, LEDC_CHANNEL_B, inverted_duty_b); ledc_update_duty(LEDC_MODE, LEDC_CHANNEL_B); } ```

Esta clase estuvo demasiado buena, me va a dar migraña de ver el led x.x pero muy buena jajajajaja