Сетевые технологии

Лабораторная работа №15. Настройка GPIO для ввода аналогового

Показывать лекцию целиком

15.1 Цель и задачи

Цель работы: изучить правила настройки портов ввода-вывода микроконтроллера ESP32-C3 на реализацию альтернативных функций. Задачи:

  • Освоить прием аналогового сигнала и его оцифровку с использованием встроенного аналого-цифрового преобразователя.
  • Получить навыки подключения встроенного температурного сенсора
  • Презентация к блоку "Микроконтроллеры RISC-V"

    15.2 Краткие теоретические сведения

    ESP32-C3 включает в себя 2 АЦП последовательного приближения, поддерживающие в общей сложности 6 каналов измерения, которые обеспечиваются следующим образом:

  • АЦП1 допускает подключение 5 каналов: GPIO0 - GPIO4
  • АЦП2 допускает подключение 1 канала: GPIO5.
  • АЦП ESP32 оцифровывают напряжения в диапазоне от 0 В до Vref. Vref - это опорное напряжение, у разных микросхем Vref различается, среднее значение составляет 1,1 В. Чтобы преобразовать напряжения, превышающие Vref, входные напряжения можно ослабить перед подачей на АЦП. Доступны 4 варианта затухания: чем выше затухание, тем выше может быть измеряемое входное напряжение.

    Контроллер поддерживает частоту дискретизации до 12 бит, однократное считывание (single read mode), запускаемое с помощью ПО и непрерывное сканирование (continuous read mode), запускаемое по таймеру. Режим однократного чтения подходит для низкочастотных измерений. Режим непрерывного чтения подходит для постоянно повторяющихся с высокой частотой измерений.

    Для настройки однократного считывания с помощью ПО, необходимо:

  • Выбрать АЦП1 или АЦП2:
  • если установлен APB_SARADC1_ONETIME_SAMPLE, выбран АЦП1;
  • если установлен APB_SARADC2_ONETIME_SAMPLE, выбран АЦП2;
  • Настроить APB_SARADC_ONETIME_CHANNEL, чтобы выбрать один канал.
  • Настроить APB_SARADC_ONETIME_ATTEN, чтобы установить затухание.
  • Установить APB_SARADC_ONETIME_START, чтобы начать считывание.
  • По окончанию считывания, генерируется прерывание APB_SARADC_ADCX_DONE_INT_RAW, которое может использоваться для считывания данных из APB_SARADC_ADCX_DATA. X может принимать значение 1:(АЦП1), или 2:(АЦП2).
  • Для настройки непрерывного сканирования, нужно выполнить следующие действия:

  • Установить APB_SARADC_TIMER_TARGET для выбора DIG АЦП в качестве цели для запуска таймера.
  • Установить APB_SARADC_TIMER_EN для запуска таймера.
  • Когда время таймера истекает, он заставляет DIG ADC FSM начать измерения в соответствии с таблицей шаблонов.
  • Значения автоматически помещаются в память с помощью DMA (прямой доступ в память). Прерывание генерируется после завершения считывания.
  • В контроллер ESP32-C3 встроен датчик температуры, позволяющий отслеживать изменения температуры внутри чипа. К нему можно обратиться программно для получения текущих значений. В зависимости от температуры окружающей среды настраивается диапазон измерений и смещение, которое позволяет повысить точность датчика.

    Получить данные с датчика температуры можно следующим образом:

  • Установить APB_SARADC_TSENS_PU, чтобы запустить XPD_SAR, а затем включить датчик температуры.
  • Установить SYSTEM_TSENS_CLK_EN, чтобы запустить тактовый сигнал датчика.
  • Ждать тактов APB_SARADC_TSENS_XPD_WAIT, пока не будет выполнен сброс датчика температуры. После этого начнется измерение температуры;
  • Через некоторое время данные можно будет считать из APB_SARADC_TSENS_OUT. Для получения значений в градусах Цельсия, нужно использовать формулу T(°C) = 0.4386 ? VALUE-27.88 ? offset-20.52, где значение offset определяется по таблице 15.1.
  • Смещения для датчика температуры
    Диапазон измерений, °C Смещение, °C
    50 ~ 125 -2
    20 ~ 100 -1
    10 ~ 80 0
    -30 ~ 50 1
    -40 ~ 20 2

    Настройка регистров осуществляется с использованием функций API.

    Для подключения контакта к АЦП1 последовательно вызываются две функции:

  • adc1_config_width (adc_bits_width_t width_bit) - настройка разрешения канала, width_bit - число бит. Для ESP32-C3 доступно 12-ти битное разрешение.
  • adc1_config_channel_atten (adc1_channel_t channel, adc_atten_t atten) - выбор канала (channel) и уровня ослабления (atten). Благодаря этому можно изменять верхнюю границу измеряемого диапазона для увеличения точности значений.
  • Доступные значения adc_atten_t:

  • ADC_ATTEN_DB_0 (или значение 0) 0 mV ~ 750 mV
  • ADC_ATTEN_DB_2_5 (1) 0 mV ~ 1050 mV
  • ADC_ATTEN_DB_6 (2) 0 mV ~ 1300 mV
  • ADC_ATTEN_DB_11 (3) 0 mV ~ 2500 mV
  • Для одиночного считывания данных вызывается следующая функция adc1_get_raw(adc1_channel_t channel), в которой указывается номер канала, выбранный в предыдущей функции. На выходе получаем целое значение val в диапазоне от 0 до (2**width_bit-1)

    При необходимости получить значение напряжения можно использовать формулу mVolts = val*(Vref/4095), Vref - верхнее значение выбранного диапазона adc_atten.

    Для получения данных со встроенного датчика температуры выполняются следующие действия:

  • После создания пустого объекта типа temperature_sensor_handle_t необходимо определить, в каких условиях датчик будет работать, и задать их верхнюю и нижнюю температурные границы.
  • Структуру temperature_sensor_config_t можно задать функцией TEMPERATURE_SENSOR_CONFIG_DEFAULT (min, max), где min и max - границы температуры. Ссылка на эту структуру вместе с указателем на объект передается в функцию temperature_sensor_install(). Далее для начала работы с датчиком вызывается temperature_sensor_enable(), в которую также нужно передать указатель на созданный temperature_sensor_handle_t.
  • Для получения значений температуры используется функция temperature_sensor_get_celsius(temperature_sensor_handle_t tsens, float *out_celsius) , в out_celsius будет храниться значение в градусах Цельсия.
  • 15.3 Задания к лабораторной работе

    Подготовить программу, обеспечивающую прием аналогового сигнала, его оцифровку и использование полученного цифрового кода для управления внешним элементом. С использованием беспаечной макетной платы собрать схему, подключив к аналоговому входу переменный резистор, а к цифровому выходу - элемент, управляемый цифровым сигналом.

  • Реализовать плавное изменение яркости светодиода в зависимости от значения сопротивления переменного резистора.
  • Реализовать плавное изменение частоты звучания зуммера в зависимости от значения сопротивления переменного резистора.
  • Реализовать вывод на экран компьютера оцифрованных значений сигнала, получаемого от переменного резистора.
  • 15.3.1 Описание последовательности выполнения работы

    Для выполнения работы необходимо иметь беспаечную макетную плату для многократного макетирования; одножильные провода-перемычки с контактами, допускающими коммутацию с установленными на макетной плате элементами; светодиоды; зуммер.

  • Изучить настройки портов GPIO для подключения аналогового сигнала.
  • Для выполнения работы рекомендуется воспользоваться шаблоном проекта ADC. Подготовить текст основной программы в соответствии с заданием, используя шаблон, приведенный в п.15.2.3. Доработать программу шаблона таким образом, чтобы входной аналоговый сигнал преобразовывался в цифровой эквивалент, который, в свою очередь, использовался для управления внешним элементом (зуммером, светодиодом).
  • Используя беспаечную макетную плату, подключить к аналоговому входу резистор с переменным напряжением, а к цифровому выходу элемент, управляемый от цифрового выхода.
  • 15.3.2 Пример выполнения задания на защиту

    #include <stdio.h>
    #include "freertos/FreeRTOS.h"
    #include "freertos/task.h"
    #include "driver/adc.h"
    #include "esp_adc_cal.h"
    #include "driver/temperature_sensor.h"
    
    void app_main(void){
    //подключаемся к каналу АЦП
    adc1_config_width(12);
    adc1_config_channel_atten(ADC1_CHANNEL_2, ADC_ATTEN_DB_11);
    //подключаем встроенный датчик температуры
    temperature_sensor_handle_t temp_sensor = NULL;
    temperature_sensor_config_t temp_sensor_config = TEMPERATURE_SENSOR_CONFIG_DEFAULT(10, 50);
    ESP_ERROR_CHECK(temperature_sensor_install(temp_sensor_config, temp_sensor));
    ESP_ERROR_CHECK(temperature_sensor_enable(temp_sensor));
    float tsens_value;
    while(1){
    //получение значений температуры с внешнего датчика
    int val = adc1_get_raw(ADC1_CHANNEL_2);
    float voltage = val*(2500.0/4096.0);
    float temp = (voltage-500)/10.0; //для датчика TMP36
    printf("Temperature in the room is %.02f ? \n", temp);
    //получение значений температуры со встроенного датчика
    ESP_ERROR_CHECK(temperature_sensor_get_celsius(temp_sensor, tsens_value));
    printf("Temperature value inside the chip is %.02f ?\n\n", tsens_value);
    vTaskDelay(2000/portTICK_PERIOD_MS);
    }
    }
    

    15.4 Вопросы для контроля

  • Поясните порядок настройки аналого-цифрового преобразователя.
  • Поясните режимы работы АЦП, для каких задач они могут быть использованы?
  • С помощью каких настроек можно регулировать разрешающую способность АЦП?
  • Вернуться к учебному плану