No tienes acceso a esta clase

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

Entrada Analógica con ESP32

20/30
Recursos

Aportes 10

Preguntas 4

Ordenar por:

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

Cambios en la versión 5.0

Hola trate de compilar el programa pero obtuve errores, cheque la documentación y en la versión 5.0 ya no están las funciones vistas en la clase, ahora el ADC tiene dos modos:

  • Oneshot mode
  • Converted continuous mode

En esta clase ocupamos el mode Oneshot y se configura por medio de estructuras y otras funciones, dejo el código abajo espero que les ayude.

La diferencia principal entre una señal analógica y una señal digital es que la primera se representa mediante una variación continua de voltaje o corriente respecto al tiempo, mientras que la digital se representa mediante niveles discretos de voltaje o corriente que representan bits digitales.

La librería “driver/adc.h” es una cabecera de la biblioteca de drivers de ESP-IDF (ESP32 IoT Development Framework) que proporciona funciones para controlar el convertidor analógico-digital (ADC) del ESP32.

Entre las funcionalidades que proporciona esta librería se incluyen:

Configuración del modo de trabajo del ADC (por ejemplo, modo de lectura de un solo canal o modo de lectura de múltiples canales).
Configuración de la precisión de la conversión ADC (por ejemplo, 9 bits, 10 bits, 11 bits o 12 bits).
Configuración de la fuente de referencia del ADC (por ejemplo, Vref o Vdd).
Configuración de la ganancia de amplificación del ADC.
Lectura del valor de la conversión ADC de uno o varios canales.
Inicio, parada y configuración del temporizador de muestreo.
En resumen, la librería “driver/adc.h” es una herramienta esencial para cualquier proyecto que requiera la lectura de señales analógicas en el ESP32, ya que proporciona funciones y macros para controlar el ADC y realizar conversiones ADC precisas y confiables en el ESP32.

Las señales lógicas son aquellas que solo tienen dos posibles valores: 0 y 1, también conocidos como “falso” y “verdadero” o “apagado” y “encendido”. Estas señales son utilizadas en sistemas digitales, como computadoras, y su valor se representa mediante voltajes específicos. Por ejemplo, un voltaje de 0 volts puede representar un valor “0” lógico, mientras que un voltaje de 5 voltios puede representar un valor “1” lógico. Las señales lógicas son muy precisas y fáciles de manipular mediante circuitos digitales como los que ya hemos armado.

Por otro lado, las señales analógicas son aquellas que pueden tener valores infinitos dentro de un rango determinado. Estas señales son comunes en sistemas de audio y video, y se representan mediante voltajes que varían continuamente. Por ejemplo, una señal de audio analógica puede tener un valor de voltaje de 0,5 volts para representar un sonido suave, y un valor de 2 volts para representar un sonido fuerte. Las señales analógicas son más complejas que las señales lógicas y pueden ser afectadas por la interferencia electromagnética y otros factores ambientales.

En definitiva, la principal diferencia entre señales lógicas y señales analógicas es que las primeras solo tienen dos posibles valores, mientras que las segundas pueden tener valores infinitos dentro de un rango determinado.

Dejo el código que realicé utilizando la librería "esp\_adc/adc\_oneshot.h", ya que "driver/adc.h" está deprecada. En mi caso, utilicé ADC1 (ADC\_UNIT\_1), canal 4 (ADC\_CHANNEL\_4). ```txt #include <stdio.h> #include "freertos/FreeRTOS.h" #include "freertos/task.h" #include "esp_adc/adc_oneshot.h" adc_oneshot_unit_handle_t handle; adc_oneshot_unit_init_cfg_t init_cfg = { .unit_id = ADC_UNIT_1, }; adc_oneshot_chan_cfg_t chan_cfg = { .bitwidth = ADC_BITWIDTH_12, .atten = ADC_ATTEN_DB_12, }; int raw_value; void app_main(void) { adc_oneshot_new_unit(&init_cfg, &handle); adc_oneshot_config_channel(handle, ADC_CHANNEL_4, &chan_cfg); while (1) { adc_oneshot_read(handle, ADC_CHANNEL_4, &raw_value); printf("ADC Raw Value: %d\n", raw_value); vTaskDelay(pdMS_TO_TICKS(250)); } adc_oneshot_del_unit(handle); } ```

El esp32 es un dispositivo que funciona a 3.3Voltios.
.
Si tratams de medir voltajes mayores podemos destruirlo. Por ejemplo, medir 5 voltios.
.
Para hacerlo correctamente hay que emplear un divisor de voltaje
.

.
El potenciometro puede ser considerado como un divisor de voltaje.
.

Un divisor de voltaje es un circuito eléctrico que divide el voltaje de una fuente de alimentación entre dos o más resistencias conectadas en serie. El voltaje de salida de un divisor de voltaje es proporcional a la resistencia total del circuito y a la resistencia del elemento donde se mide el voltaje. Un divisor de voltaje se utiliza para reducir el voltaje de una fuente a un nivel adecuado para otro dispositivo o componente.

Hola, trate de compilar el código compartido por Diana pero no me funciono, tras leer la documentación encontré que el parámetro de atenuación debe de ir a 11 para poder registrar el cambio de la señal analogica.

enumerator ADC_ATTEN_DB_11: The input voltage of ADC will be attenuated extending the range of measurement by about 11 dB (3.55 x)

Otro pequeño cambio es el código del puerto escucha, no utiliza el postfijo 2 en el ADC: enumerator ADC_CHANNEL_9

Les comparto mi código, esta compilado utilizando esp-idf-v5.0.2

#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/adc.h"

void app_main(void)
{
  int32_t raw_value;
  adc2_config_channel_atten(ADC_CHANNEL_9, ADC_ATTEN_DB_11);

  while(1) {
    adc2_get_raw(ADC_CHANNEL_9, ADC_WIDTH_BIT_12, &raw_value);
    printf("adc raw: %ld\n", raw_value);
    printf("voltaje: %.2f\n", (5.0*raw_value)/4095);
    vTaskDelay(1000 / portTICK_PERIOD_MS);
  }
}



Mientras compilaba me dio el siguiente error:

#warning "legacy adc driver is deprecated, please migrate to use esp_adc/adc_oneshot.h and esp_adc/adc_continuous.h for oneshot mode and continuous mode drivers respectively"

Trate de emtender la libreria adc_one_shot y no entendi bien la documentacion y no encontre ejemplos.
.
.
Hice el ejercicio con adc_driver para mi hardware que es un Lora32. Implemente varias tareas simultaneas en el core 1.
.
.

#include <stdio.h>
#include <stdio.h>
#include "freertos/FreeRTOS.h"
#include "freertos/task.h"
#include "driver/gpio.h"
#include "driver/adc.h"
#include "esp_adc_cal.h"


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

#define SW_KY040_PIN  34 

bool state_led   = false;
bool state_red   = false;
bool state_green = false;
bool state_blue  = false;


const TickType_t blink_delay    = 1000 / portTICK_PERIOD_MS;
const TickType_t debounce_delay =   50 / portTICK_PERIOD_MS;
const TickType_t digital_delay  =  100 / portTICK_PERIOD_MS;
const TickType_t battVolt_delay = 2000 / portTICK_PERIOD_MS;

TaskHandle_t ledHandle;
TaskHandle_t swky040Handle;
TaskHandle_t battVoltHandle;

uint32_t raw_value;
uint32_t milivolts;
static esp_adc_cal_characteristics_t adc1_chars;

//en el cado del gpio35 el divisor de voltaje esta compuesto por dos resistencias de 100k
// Esto quiere decir que llega mitad del voltaje de la bateria.
// Para obtener el valor correcto hay que multiplicar el valor medido por dos
// como el valor del voltaje medido es milivoltios  para obtener los voltios hay que
// dividir por 1000. De hay el factor de conversion de 0.002 
double voltage_divider_factor = 0.002;
double battery_volt;

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

void refresh_swky040(void *args) 
{
    while (true)
    {    
        //El switch esta conectado en pull up
        //su estado normal es alto
        //cuando se oprime su estado es bajo    
        state_red = gpio_get_level(SW_KY040_PIN);
        gpio_set_level(LED_RED_PIN, !state_red);
        if (!state_red) vTaskDelay(debounce_delay);
        vTaskDelay(digital_delay);
    }
}

void refresh_battVolt(void *args) 
{
    while (true)
    {    
        raw_value = adc1_get_raw(ADC1_CHANNEL_7);
        milivolts = esp_adc_cal_raw_to_voltage(raw_value, &adc1_chars);
        battery_volt = milivolts;
        battery_volt = battery_volt * voltage_divider_factor;
        printf("raw value: %ld milivolts: %ld battery: %f\n",raw_value, milivolts, battery_volt);
        vTaskDelay(battVolt_delay);
    }
}


void app_main(void)
{
    //reset pines de salida
    gpio_reset_pin(LED_PIN);

    gpio_reset_pin(LED_RED_PIN);
    gpio_reset_pin(LED_GREEN_PIN);
    gpio_reset_pin(LED_BLUE_PIN);
    
    // coloca los pines en estado de salida o entrada
    gpio_set_direction(LED_PIN, GPIO_MODE_OUTPUT);
    
    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);
    
    gpio_set_direction(SW_KY040_PIN, GPIO_MODE_INPUT);

    //coloca los leds rgb en apagado
    gpio_set_level(LED_RED_PIN,   state_red);
    gpio_set_level(LED_GREEN_PIN, state_green);
    gpio_set_level(LED_BLUE_PIN,  state_blue);


    //En el chip Lora32, esp32 con radio LORA, OLED Display, cargador bateria LIPO:
    //El gpio35 lee a traves de un divisor de 2 resistencias de 100k el voltaje de la
    //   bateria.
    //El gpio35 corresponde al ADC1_CHANNEL7

    //calibramos el adc1
    esp_adc_cal_characterize(
        ADC_UNIT_1,             //apuntamos al adc 1
        ADC_ATTEN_DB_11,        //Rango lineal entre 150-2450 mv
        ADC_WIDTH_BIT_12,       //0 a 4095
        0,                      //
        &adc1_chars);           //resultado de la calibracion 

    ESP_ERROR_CHECK(adc1_config_width(ADC_WIDTH_BIT_12));  
    ESP_ERROR_CHECK(adc1_config_channel_atten(ADC1_CHANNEL_7, ADC_ATTEN_DB_11));  
    


    //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
    );

    xTaskCreatePinnedToCore(
        refresh_swky040,   //Nombre de la funcion que implementa la tarea
        "refresh_swky040", //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
        10,                //Prioridad de la tarea un numero
        &swky040Handle,    //apuntador para referenciar la tarea. 
        1                  // core 0 y core 1
    );
    
    xTaskCreatePinnedToCore(
        refresh_battVolt,   //Nombre de la funcion que implementa la tarea
        "refresh_battVolt", //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
        &battVoltHandle,        //apuntador para referenciar la tarea. 
        1                  // core 0 y core 1
    );
   
}