Опубликован: 19.01.2025 | Доступ: свободный | Студентов: 0 / 0 | Длительность: 05:57:00
Лекция 16:

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

< Лекция 15 || Лекция 16 || Лекция 17 >

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

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

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

Презентация к блоку "Микроконтроллеры RISC-V"

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

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

  1. АЦП1 допускает подключение 5 каналов: GPIO0 - GPIO4
  2. АЦП2 допускает подключение 1 канала: GPIO5.

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

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

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

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

Для настройки непрерывного сканирования, нужно выполнить следующие действия:

  1. Установить APB_SARADC_TIMER_TARGET для выбора DIG АЦП в качестве цели для запуска таймера.
  2. Установить APB_SARADC_TIMER_EN для запуска таймера.
  3. Когда время таймера истекает, он заставляет DIG ADC FSM начать измерения в соответствии с таблицей шаблонов.
  4. Значения автоматически помещаются в память с помощью DMA (прямой доступ в память). Прерывание генерируется после завершения считывания.

В контроллер ESP32-C3 встроен датчик температуры, позволяющий отслеживать изменения температуры внутри чипа. К нему можно обратиться программно для получения текущих значений. В зависимости от температуры окружающей среды настраивается диапазон измерений и смещение, которое позволяет повысить точность датчика.

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

  1. Установить APB_SARADC_TSENS_PU, чтобы запустить XPD_SAR, а затем включить датчик температуры.
  2. Установить SYSTEM_TSENS_CLK_EN, чтобы запустить тактовый сигнал датчика.
  3. Ждать тактов APB_SARADC_TSENS_XPD_WAIT, пока не будет выполнен сброс датчика температуры. После этого начнется измерение температуры;
  4. Через некоторое время данные можно будет считать из APB_SARADC_TSENS_OUT. Для получения значений в градусах Цельсия, нужно использовать формулу T(°C) = 0.4386 ? VALUE-27.88 ? offset-20.52, где значение offset определяется по таблице 15.1.
Таблица 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.

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

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

15.3 Задания к лабораторной работе

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

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

15.3.1 Описание последовательности выполнения работы

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

  1. Изучить настройки портов GPIO для подключения аналогового сигнала.
  2. Для выполнения работы рекомендуется воспользоваться шаблоном проекта ADC. Подготовить текст основной программы в соответствии с заданием, используя шаблон, приведенный в п.15.2.3. Доработать программу шаблона таким образом, чтобы входной аналоговый сигнал преобразовывался в цифровой эквивалент, который, в свою очередь, использовался для управления внешним элементом (зуммером, светодиодом).
  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 Вопросы для контроля

  1. Поясните порядок настройки аналого-цифрового преобразователя.
  2. Поясните режимы работы АЦП, для каких задач они могут быть использованы?
  3. С помощью каких настроек можно регулировать разрешающую способность АЦП?
< Лекция 15 || Лекция 16 || Лекция 17 >