ESP32-C3: сигма-дельта модуляция Печать
Добавил(а) microsin   

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

Обычно канал с ΔΣ-модуляцией можно использовать для следующих целей:

● Димминг LED (управление яркостью светодиодов).
● Простой ЦАП (DAC 8-bit), работающий месте с активным RC ФНЧ.
● Усилитель низкой частоты (УНЧ) класса D, построенный на основе полумоста и LC ФНЧ.

Блок сигма-дельта модуляции (SDM) есть во всех моделях кристаллов ESP32, и они управляются через API-функции драйвера одинаково, отличие только в количестве доступных каналов.

ESP32 SoC Количество каналов SigmaDelta
ESP32 8
ESP32-S2 8
ESP32-C3 4
ESP32-S3 8

В последующих секциях (перевод документации [1]) будут рассмотрены следующие шаги по настройке и запуску канала SDM (Sigma-Delta Modulation):

Выделение ресурсов - какие параметры должны быть подготовлены, чтобы получить дескриптор канала (channel handle), и как восстановить эти ресурсы после того, как завершена работа с каналом.

Разрешение и запрет канала - как запустить и остановить генерацию сигнала PDM (Pulse-Density Modulation).

Установка эквивалентной скважности - описывается, как устанавливается equivalent duty cycle импульсов PDM.

Управление питанием (Power Management) - как выбор различных источников тактирования может повлиять на энергопотребление.

IRAM Safe - перечислены функции, которые должны работать даже когда кэш запрещен.

Thread Safety - перечислены API-функции, которые гарантируют для драйвера безопасные вызовы из разных потоков.

Опции Kconfig - перечислены опции, поддерживаемые системой конфигурации проекта (idf.py menuconfig), которые по-разному влияют на поведение драйвера.

Выделение ресурсов. Канал SDM представлен структурой sdm_channel_handle_t. Каждый канал может выводить двоичный, аппаратно генерируемый сигнал ΔΣ-модуляции. Драйвер управляет всеми доступными каналы в пуле, так что пользователю не надо заботиться о назначении фиксированного канала на GPIO.

Для инсталляции канала SDM нужно вызвать sdm_new_channel() для получения дескриптора канала (channel handle). Специфичные для канала параметры конфигурации передаются в структуру sdm_config_t:

sdm_config_t::gpio_num установит порт GPIO на котором будут формироваться импульсы PDM.

sdm_config_t::clk_src выбирает источник тактирования для модуля SDM. Имейте в виду, что на всех каналах должен быть выбран один и тот же источник тактирования.

sdm_config_t::sample_rate_hz установит частоту выборок (sample rate) модуля SDM.

sdm_config_t::invert_out установит инверсию выходного сигнала.

sdm_config_t::io_loop_back предназначается только для отладки. Это разрешит функционал ввода и вывода GPIO через матрицу периферийных устройств (GPIO matrix peripheral).

Функция sdm_new_channel() может потерпеть неудачу из-за различных ошибок, таких как недостаток памяти, ошибки в аргументах и т. п. Особенно когда свободных каналов больше нет (например все аппаратные каналы SDM уже используются), тогда будет возвращен код ошибки.

Если ранее созданный канал SDM больше не нужен, то его (и связанные с ним ресурсы) надо освободить вызовом sdm_del_channel(). Это позволит использовать аппаратуру нижнего уровня для других целей. Перед удалением дескриптора канала SDM (channel handle) нужно его запретить вызовом sdm_channel_disable(), либо надо гарантировать, что он не был (и не будет) разрешен вызовом sdm_channel_enable().

Пример создания канала SDM с частотой дискретизации 1 МГц:

sdm_channel_handle_t chan = NULL;
sdm_config_t config = {
   .clk_src = SDM_CLK_SRC_DEFAULT,
   .sample_rate_hz = 1 * 1000 * 1000,
   .gpio_num = 0,
};
ESP_ERROR_CHECK(sdm_new_channel(&config, &chan));

Разрешение и запрет канала. Чтобы в будущем управлять выводом в канал SDM его нужно сначала разрешить вызовом sdm_channel_enable(). Внутри этой функции выполняется следующее:

● Переключить состояние канала из init в enable.
● Получить соответствующую блокировку управления питанием (power management lock), если выбран конкретный источник синхросигнала (например, синхросигнал APB). Дополнительные сведения см. далее в разделе "Управление питанием".

Вызов sdm_channel_disable() делает обратное, т. е. переводит канал обратно в начальное состояние (init state) и освобождает его блокировку по управлению питанием (power management lock).

Установка эквивалентной скважности. Известно, что сигнал ΔΣ не имеет фиксированной частоты импульсов. Это сделано специально, чтобы уменьшить частоту переключения силовых ключей и соответственно снизить потери мощности [2]. Поэтому для сигналов ΔΣ существует такое понятие, как эквивалентная скважность. PDM скважность периода (duty cycle) относится к процентному соотношению периодов высокого уровня к среднестатистическому периоду сигнала. Среднее выходное напряжение, генерируемое каналом, вычисляется по формуле Vout = VDD_IO / 256 * duty + VDD_IO / 2. Таким образом, диапазон входного параметра скважности функции sdm_channel_set_duty() будет в диапазоне от -128 до 127 (8-битное целое число со знаком). Например, если установлено значение 0, то скважность выходного сигнала составит около 50%.

Управление питанием (Power Management). Когда разрешено управление питанием (например включена опция CONFIG_PM_ENABLE), система будет подстраивать частоту APB (сокращение от Advanced Peripherial Bus) перед переходом в режим пониженного энергопотребления light sleep, что потенциально поменяет частоту выборок (sample rate) ΔΣ-модулятора.

Однако драйвер может предотвращать изменение системой частоты APB получением блокировки управления питанием (power management lock) типа ESP_PM_APB_FREQ_MAX. Всякий раз, когда драйвер создает экземпляр канала SDM, у которого выбран источник тактов SDM_CLK_SRC_APB, драйвер будет гарантировать, что при вызове sdm_channel_enable() для разрешения канала захватывается соответствующая блокировка управления питанием. Соответственно драйвер освободит эту блокировку, когда для этого канала будет вызвана функция sdm_channel_disable().

IRAM Safe. Существует Kconfig-опция CONFIG_SDM_CTRL_FUNC_IN_IRAM, которая переведет часто используемые функции управления ввода/вывода в область ОЗУ (IRAM). Таким образом, эти функции могут выполняться также когда кэш запрещен. К таким функциям управления относится sdm_channel_set_duty().

Thread Safety. Заводская функция sdm_new_channel() гарантирована драйвером для безопасного вызова из потока (thread safe). Это означает, что пользователь может вызвать эту функцию из различных потоков (RTOS tasks) без дополнительных защитных блокировок. Также функцию sdm_channel_set_duty() можно безопасно вызывать из контекста прерывания (код ISR), для этого драйвер использует критическую секцию для предотвращения ситуации, когда эта функция одновременно вызвана и из основного кода (т. е. обычного потока), и из ISR.

Другие функции, которые принимают в качестве первого параметра дескриптор канала sdm_channel_handle_t, не являются потокобезопасными (not thread safe). Это означает, что пользователь должен избегать вызывать их из нескольких потоков.

Опции Kconfig. Предусмотрены следующие опции, которые можно менять в утилитой idf.py menuconfig:

CONFIG_SDM_CTRL_FUNC_IN_IRAM управляет тем, куда будут помещены функции управления каналом SDM (IRAM или Flash, см. выше IRAM Safe).

CONFIG_SDM_ENABLE_DEBUG_LOG используется для разрешения вывода в лог отладки. Разрешение этой опции увеличит размер двоичного кода firmware приложения.

[Преобразование PDM в аналоговую форму]

Обычно если ΔΣ-сигнал подключен к LED, то не нужен никакой фильтр между ними (потому что наши глаза не замечают быстрых мерцаний, и работают как усредняющий ФНЧ). Однако если вы хотите сформировать реальный аналоговый сигнал (например для использования в лабораторном блоке питания, или для вывода звукового сигнала), то может понадобиться разработать фильтр низкой частоты (ФНЧ), пассивный или активный. Активный фильтр обеспечивает лучшую фильтрацию полезного сигнала и может обеспечить больший выходной уровень сигнала.

В качестве примера ниже показана схема ФНЧ с топологией Sallen-Key.

SallenKey LP filter example

Примеры приложений см. в каталоге peripherals/sigma_delta среди других примеров кода в ESP-IDF (также см. репозиторий GitHub [5, 6]).

● Синусоидальный сигнал 100 Гц, модулированный Sigma-Delta: peripherals/sigma_delta/sdm_dac.
● Пример, который управляет яркостью светодиодов через Sigma-Delta: peripherals/sigma_delta/sdm_led.

SDM output example

[API-функции драйвера Sigma-Delta модулятора]

Заголовочный файл API-функций: components/driver/include/driver/sdm.h.

Функция Описание
sdm_new_channel Создание нового канала Sigma Delta.
sdm_del_channel Удаление канала Sigma Delta.
sdm_channel_enable Разрешение канала Sigma Delta.
sdm_channel_disable Запрет канала Sigma Delta.
sdm_channel_set_duty Установит скважность периода выходного сигнала PDM.

Подробное описание параметров функций, структур, определений и констант см. в документации [1].

[Ссылки]

1. ESP32-C3 Sigma-Delta Modulation site:docs.espressif.com.
2. Дельта-сигма модуляция.
3. XPS Delta-Sigma ЦАП.
4. Что такое PWM (ШИМ)?
5. Sigma Delta Modulation LED Example site:github.com.
6. Sigma Delta Modulation DAC Example site:github.com.