Salida Digital con ESP32

Clase 18 de 30 • Curso de IoT: Programación de Microcontroladores ESP32

Clase anteriorSiguiente clase
    Gabriel Obregón

    Gabriel Obregón

    student•
    hace 8 meses

    Ahora que ya hemos trabajado en la programación del chip, daremos el siguiente paso: comenzar a utilizar los diferentes periféricos de entrada y salida de nuestra tarjeta de desarrollo ESP32.

    Para ello, aprenderemos sobre entradas y salidas de propósito general (GPIO), lo que nos permitirá leer o enviar señales digitales.

    Aplicaciones de GPIO

    Podemos utilizar GPIO para:

    • Leer botones o sensores digitales.
    • Comunicaciones entre chips.
    • Controlar dispositivos, como encender o apagar un LED o manejar un motor.

    En términos computacionales, una señal digital representa 1 o 0, que en términos eléctricos equivalen a 5V o 0V.

    Para gestionar estas señales, utilizaremos la librería GPIO.

    Circuito a Utilizar

    El circuito utilizado es el mismo que en la práctica del "Hola Mundo". Dependiendo de tu tarjeta de desarrollo, debes revisar la hoja de datos para saber qué pines puedes usar.

    Si tu tarjeta ya cuenta con un LED incorporado, puedes usarlo sin necesidad de una protoboard. De lo contrario, deberás armar el circuito correctamente.

    Ejemplo de Código en Visual Studio Code

    Ya tenemos creado un proyecto en Visual Studio Code. A continuación, presentamos el código completo:

    #include <stdio.h>

    #include "freertos/FreeRTOS.h"

    #include "freertos/task.h"

    #include "driver/gpio.h"

    #define LED_PIN 4

    #define BLINK_TIME 1000

    void app_main(void)

    {

      int led_state = 0;

      gpio_reset_pin(LED_PIN);

      gpio_set_direction(LED_PIN, GPIO_MODE_OUTPUT);

      while (1)

      {

        gpio_set_level(LED_PIN, led_state);

        led_state = !led_state;

        vTaskDelay(BLINK_TIME / portTICK_PERIOD_MS);

      }

    }

    Explicación del Código

    1. Librerías Importadas

      • #include <stdio.h>: Entrada/salida estándar.
      • #include "freertos/FreeRTOS.h": Manejo de procesos.
      • #include "freertos/task.h": Uso de tareas y retardos.
      • #include "driver/gpio.h": Control de GPIO.
    2. Definiciones

      • #define LED_PIN 4: Define el pin donde está conectado el LED.
      • #define BLINK_TIME 1000: Establece el tiempo de parpadeo en milisegundos.
    3. Configuración del LED

      • Se inicializa el pin 4 como salida digital.
      • Se define led_state = 0, para que el LED comience apagado.
    4. Bucle Infinito

      • El LED cambia de estado en cada iteración.
      • Se usa vTaskDelay(BLINK_TIME / portTICK_PERIOD_MS); para generar el retardo adecuado.

    Explicación del Circuito

    Conexiones de Alimentación

    1. Fuente de alimentación: Se conecta mediante un cable USB adaptado para la protoboard.
    2. Líneas de alimentación:
      • Línea azul (GND): Representa el negativo (tierra).
      • Línea roja (+5V): Representa el positivo.

    Esquemático del Circuito

    • GND (línea azul) → GND de la tarjeta de desarrollo.
    • +5V (línea roja) → 5V de la tarjeta de desarrollo.
    • Resistencia entre GND y el LED.
    • LED conectado a un pin de salida digital (en este caso, el pin 12).

    Puedes elegir cualquier otro pin que permita salida digital.

    Aplicaciones Avanzadas

    El mismo principio utilizado para el LED puede aplicarse a otros dispositivos:

    1. Control de Motores

    • Con 2 pines: Controlar un motor en dos direcciones.
    • Con 4 pines: Controlar dos motores en cuatro direcciones.

    2. Motores a Pasos

    Los motores a pasos funcionan con un código binario. Cada señal eléctrica cambia el ángulo del motor de forma precisa.

    Aplicaciones avanzadas:

    • 🔍 Robótica de precisión
    • 🔧 Máquinas CNC
    • 🎨 Impresoras 3D

    Estos dispositivos manipulan señales eléctricas de manera controlada para generar movimientos exactos.

    Compilación y Flasheo del ESP32

    Tras escribir el código, procedemos a compilarlo. Si todo está correcto, no debería haber errores.

    Flasheo del Chip ESP32

    Para cargar el programa en la tarjeta de desarrollo, ejecutamos el comando de flasheo.

    Nota: El puerto de conexión puede variar. En mi caso, es COM3, pero en tu computadora podría ser diferente.

    Durante el flasheo, veremos en la terminal el progreso de la carga. Una vez finalizado, el código estará corriendo en el ESP32.

    Verificando el Funcionamiento

    Después de la carga del programa, el LED debería parpadear según lo programado. 🚀

    Julio Cardenas

    Julio Cardenas

    student•
    hace 2 años

    Este es mi codigo para un modulo con led RGB .

    #include <stdio.h> #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "driver/gpio.h" #define LED_RED_PIN 4 #define LED_GREEN_PIN 0 #define LED_BLUE_PIN 12 bool state_red = false; bool state_green = false; bool state_blue = false; const TickType_t blink_delay = 1000 / portTICK_PERIOD_MS; void app_main(void) { gpio_reset_pin(LED_RED_PIN); gpio_reset_pin(LED_GREEN_PIN); gpio_reset_pin(LED_BLUE_PIN); gpio_set_direction(LED_RED_PIN, GPIO_MODE_OUTPUT); gpio_set_direction(LED_GREEN_PIN, GPIO_MODE_OUTPUT); gpio_set_direction(LED_BLUE_PIN, GPIO_MODE_OUTPUT); while (true) { gpio_set_level(LED_RED_PIN, state_red); state_red = !state_red; vTaskDelay(blink_delay); gpio_set_level(LED_GREEN_PIN, state_green); state_green = !state_green; vTaskDelay(blink_delay); gpio_set_level(LED_BLUE_PIN, state_blue); state_blue = !state_blue; vTaskDelay(blink_delay); } }
    Carlos Andres Betancourt Perez

    Carlos Andres Betancourt Perez

    student•
    hace 2 años

    Les comparto mi código con unos cambios en los logs usando esp_log.h :

    //incluimos las librerias necesarias #include <stdio.h> #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "driver/gpio.h" #include "esp_log.h" //Privated defines #define LED1 19 #define LED_DELAY 500 //Global variables static const char* TAG = "ESP32"; uint8_t led_state = 0; uint8_t count = 0; //function prototypes static void esp_logs(esp_err_t* err, char* ok, char* fail); static esp_err_t led_init(void); static esp_err_t led_blink(void); //main function void app_main(void) { led_init(); while (true) { led_blink(); vTaskDelay(pdMS_TO_TICKS(LED_DELAY)); if (count > 30) { count = 0; } if (count < 10) { ESP_LOGI(TAG, "Value %u", count); } else if (count >= 10 && count < 20) { ESP_LOGW(TAG, "Value %u", count); } else if (count >= 20 && count < 30) { ESP_LOGE(TAG, "Value %u", count); } printf("LED state: %u\n", led_state); count++; } } //------------------------------ static void esp_logs(esp_err_t* err, char* ok, char* fail) { if (*err == ESP_OK) ESP_LOGI(TAG, "%s", ok); else ESP_LOGE(TAG, "%s", fail); } //-------------------------------- static esp_err_t led_init(void) { esp_err_t err; err = gpio_reset_pin(LED1); esp_logs(&err, "LED Reset Done", "LED Reset Failed!!"); err = gpio_set_direction(LED1, GPIO_MODE_OUTPUT); esp_logs(&err, "LED GPIO config Done", "LED GPIO config Failed!!"); return err; } //------------------------------ static esp_err_t led_blink(void) { led_state = !led_state; gpio_set_level(LED1, led_state); return ESP_OK; } //------------------------------ ```//incluimos las librerias necesarias#include \<stdio.h>#include "freertos/FreeRTOS.h"#include "freertos/task.h"#include "driver/gpio.h"#include "esp\_log.h" //Privated defines#define LED1         19#define LED\_DELAY    500 //Global variablesstatic const char\* TAG = "ESP32";*uint8\_t* led\_state = 0;*uint8\_t* count = 0; //function prototypesstatic void esp\_logs(*esp\_err\_t*\* *err*, char\* *ok*, char\* *fail*);static *esp\_err\_t* led\_init(void);static *esp\_err\_t* led\_blink(void); //main functionvoid app\_main(void) {   led\_init();    while (true) {      led\_blink();      vTaskDelay(pdMS\_TO\_TICKS(LED\_DELAY));      if (count > 30) {         count = 0;      }      if (count < 10) {         ESP\_LOGI(TAG, "Value %u", count);      }      else if (count >= 10 && count < 20) {         ESP\_LOGW(TAG, "Value %u", count);      }      else if (count >= 20 && count < 30) {         ESP\_LOGE(TAG, "Value %u", count);      }       printf("LED state: %u\n", led\_state);      count++;   }}//------------------------------ static void esp\_logs(*esp\_err\_t*\* *err*, char\* *ok*, char\* *fail*) {   if (\**err* == ESP\_OK) ESP\_LOGI(TAG, "%s", *ok*);   else ESP\_LOGE(TAG, "%s", *fail*);}//-------------------------------- static *esp\_err\_t* led\_init(void) {   *esp\_err\_t* err;   err = gpio\_reset\_pin(LED1);   esp\_logs(\&err, "LED Reset Done", "LED Reset Failed!!");   err = gpio\_set\_direction(LED1, GPIO\_MODE\_OUTPUT);   esp\_logs(\&err, "LED GPIO config Done", "LED GPIO config Failed!!");   return err;}//------------------------------ static *esp\_err\_t* led\_blink(void) {   led\_state = !led\_state;   gpio\_set\_level(LED1, led\_state);    return ESP\_OK;}//------------------------------
    Luis Alberto Vargas Méndez

    Luis Alberto Vargas Méndez

    student•
    hace 2 años

    Otra manera de visualizar el cambio para no tener que montar el circuito en la protoboard es midiendo el voltaje con un multímetro

    Oswaldo Díaz Ventura

    Oswaldo Díaz Ventura

    student•
    hace 2 años

    Comparto mi código que te ayuda a no escribir mucho al momento de poner un pin como salida.

    #include <stdio.h> #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "driver/gpio.h" #define LED_pin 2 #define blink_time 500 void app_main(void) { int led_state = 0; gpio_reset_pin(LED_pin); //gpio_set_direction(LED_pin, GPIO_MODE_OUTPUT); gpio_set_direction(LED_pin, 2);//otro modo de poner un gpio como salida while(1){ gpio_set_level(LED_pin, led_state); led_state = !led_state; vTaskDelay(blink_time / portTICK_PERIOD_MS); } }
    Mario Ruben Hernandez Carmona

    Mario Ruben Hernandez Carmona

    student•
    hace 2 años

    Les comparto mi código para 4 leds con efecto de va y ven.

    #include <stdio.h> #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "driver/gpio.h" #define LED_GPIO_23 23 #define LED_GPIO_22 22 #define LED_GPIO_21 21 #define LED_GPIO_05 05 #define BLINK_TIME 1000 void app_main(void) { // Declarar un array para almacenar los estados de los LEDs. char estadoLEDs[6][5] = { "1000", "0100", "0010", "0001", "0010", "0100" }; int estadoLED23 = 0; int estadoLED22 = 0; int estadoLED21 = 0; int estadoLED05 = 0; gpio_reset_pin(LED_GPIO_23); gpio_reset_pin(LED_GPIO_22); gpio_reset_pin(LED_GPIO_21); gpio_reset_pin(LED_GPIO_05); gpio_set_direction(LED_GPIO_23, GPIO_MODE_OUTPUT); gpio_set_direction(LED_GPIO_22, GPIO_MODE_OUTPUT); gpio_set_direction(LED_GPIO_21, GPIO_MODE_OUTPUT); gpio_set_direction(LED_GPIO_05, GPIO_MODE_OUTPUT); while (1) { int i; for ( i = 0; i < 6; i++) { estadoLED23 = estadoLEDs[i][0] - '0'; estadoLED22 = estadoLEDs[i][1] - '0'; estadoLED21 = estadoLEDs[i][2] - '0'; estadoLED05 = estadoLEDs[i][3] - '0'; printf("estadoLEDs[%d]: %s \n", i, estadoLEDs[i]); printf("estadoLED1: %d \n", estadoLED23); printf("estadoLED2: %d \n", estadoLED22); printf("estadoLED3: %d \n", estadoLED21); printf("estadoLED4: %d \n", estadoLED05); printf("\n"); gpio_set_level(LED_GPIO_23, estadoLED23); gpio_set_level(LED_GPIO_22, estadoLED22); gpio_set_level(LED_GPIO_21, estadoLED21); gpio_set_level(LED_GPIO_05, estadoLED05); vTaskDelay(BLINK_TIME / (portTICK_PERIOD_MS*16)); } } }
    Luis Ariel Torres

    Luis Ariel Torres

    student•
    hace 2 años

    Reemplazando "vTaskDelay(BLINK_TIME / portTICK_PERIOD_MS)"; por "vTaskDelay(1);" en digital-output.c, vamos a tener el LED prendido por un TICK y apagado otro TICK. De esta manera, con un osciliscopio podemos medir la duracion del TICK. Les dejo la captura de pantalla del osciloscopio. El resultado fué el LED prendiéndose 50 veces por segundo y la duración del TICK fué de 10ms.

    PlatziClase18.png

    En la captura de pantalla, la duracion del TICK Delta X que es 9.999610000ms

    Juan Felipe Rodriguez Valencia

    Juan Felipe Rodriguez Valencia

    student•
    hace 2 años

    les comparto mi código, que viene también con administración de errores, que se activa con un contador.

    /* Este codigo hace parpadear el led que esta conectado al puerto GPIO 02 de la tarjeta ESP32 wroom32 primero se importan las librerias que se usaran en el codigo se estara empleando el sistema operativo freeRTOS y una funcion del mismo llamada task.h */ #include <stdio.h> #include "driver/gpio.h" #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "esp_log.h" //se define el puerto que se usara (02) #define led1 2 static const char* tag = "MyModule"; uint8_t led_level =0; uint8_t count = 0; // se inicializan las funciones que inician el led y // la que lo hace parpadear esp_err_t init_led(void); esp_err_t blink_led(void); void app_main(void) { init_led(); while(1) { vTaskDelay(200 / portTICK_PERIOD_MS); // 200ms de periodo blink_led(); //llama la funcion de parpadeo count +=1; if (count >30) { count = 0; } if(count < 10) { ESP_LOGI(tag,"value: %u.",count); } if (count >= 10 && count < 20) { ESP_LOGW(tag,"value: %u.",count); } if (count >= 20) { ESP_LOGE(tag,"value: %u.",count); } //printf("led level: %u\n", led_level); //imprime la salida del puerto 2 } } // funcion para inicializar el puerto 2 esp_err_t init_led(void) { gpio_reset_pin(led1); gpio_set_direction(led1, GPIO_MODE_DEF_OUTPUT); return ESP_OK; } //funcion para intermitencia entre on/off del GPIO 02 esp_err_t blink_led(void) { led_level = !led_level; gpio_set_level(led1,led_level); return ESP_OK; }
    Jesús Ramon

    Jesús Ramon

    student•
    hace 3 años

    Esta línea de código está escrita en el lenguaje de programación C para programar microcontroladores ESP32 utilizando el FreeRTOS, un sistema operativo en tiempo real para sistemas embebidos.

    La función vTaskDelay() es una función proporcionada por FreeRTOS que suspende la tarea actual durante un período de tiempo determinado. En este caso, la tarea se suspenderá durante un tiempo determinado por BLINK_TIME dividido por portTICK_PERIOD_MS.

    BLINK_TIME es una constante que representa el tiempo que debe permanecer encendido o apagado un LED, por ejemplo, mientras que portTICK_PERIOD_MS es una constante que representa el tiempo base de FreeRTOS en milisegundos. Esta constante se utiliza para convertir el tiempo de espera deseado en ticks de reloj, que es la unidad de tiempo utilizada por FreeRTOS.

    En resumen, esta línea de código suspende la tarea actual durante un tiempo determinado para controlar el parpadeo de un LED conectado a un microcontrolador ESP32 utilizando FreeRTOS.

    Claudio Palmieri

    Claudio Palmieri

    student•
    hace 3 años

    Hola Diana. No comprendí como se conecta la protoboard a conector USB con cables de donde obtiene la alimentación. Gracias por tu respuesta.

      Diana Martinez

      Diana Martinez

      student•
      hace 3 años

      Las tarjetas traen un puerto USB como el de los celulares, simplemente ahí lo conectas y con eso ya pasa energía y datos, como un USB normal.

    Vanessa Corredor

    Vanessa Corredor

    student•
    hace 3 años

    Me quede esperando como hacer la conexión del circuito y ver la prueba del mismo funcionando. Yo entendí en una de las clases pasadas como funciona la protoboard, pero lo que no se es como conectar el ESP32CAM a la protoboard.

      Diana Martinez

      Diana Martinez

      student•
      hace 3 años

      Tienes razón, se pasó esa escena en la edición, pediré que se arregle. Muchas gracias. La ESP32-CAM tiene ya la forma para colocarla sobre la protoboard, del resto solo hay que conectarle los componentes respecto al diagrama, usando su pinout. Pero es que además, especialmente la ESP32-CAM, en esta práctica, no es necesario conectarle nada, esta tarjeta en específico ya trae un LED ultrabrillante, el que usamos en clases, así que solo es cuestión de configurar en el código el Pin al que está conectado. Si usas el mismo modelo que yo en el curso, es el pin 4, el código de la clase está en github, en los recursos de la clase, ese debería servirte.

      Rodrigo Josue Goitia Quiroga

      Rodrigo Josue Goitia Quiroga

      student•
      hace 3 años

      ¡Hola Vanessa! Ya hemos actualizado esta clase. Puedes revisarla para ver como funciona el circuito.

    Harrison Malagon

    Harrison Malagon

    student•
    hace 3 años

    Comparto mi codigo para 2 LED's:

    #include <stdio.h> #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "driver/gpio.h" #define LED_PIN 2 #define LED2_PIN 12 #define BLINK_TIME 1000 void app_main(void) { int led_state = 0; // Configurar los pines de los LED gpio_pad_select_gpio(LED_PIN); gpio_pad_select_gpio(LED2_PIN); gpio_set_direction(LED_PIN, GPIO_MODE_OUTPUT); gpio_set_direction(LED2_PIN, GPIO_MODE_OUTPUT); while (1) { // Encender y apagar los LED gpio_set_level(LED_PIN, led_state); gpio_set_level(LED2_PIN, led_state); led_state = !led_state; // Retrasar la ejecución del bucle para crear un patrón de parpadeo vTaskDelay(BLINK_TIME / portTICK_PERIOD_MS); } }