Перейти к содержанию

RMT ESP32: разрешение, символы и код ESP-IDF

Выберите чип, источник такта и разрешение — калькулятор повторит расчёт делителей драйвера ESP-IDF, переведёт времена WS2812 или ИК-кода NEC в такты RMT, сверит их с даташитом, посчитает несущую и выдаст код канала и кодировщика для ESP-IDF v5 и v6.

Исходные данные

Сигнал
Гц

resolution_hz, можно 10M или 1M

Времена бита

нс
нс
нс
нс
мкс

Результат

Разрешение канала
10 МГц
1 такт = 100 нс
Делители
÷ 8APB_CLK 80 МГц; у ESP32 нет делителя группы
Длительность в символе
100 нс … 3,2767 мсот 1 до 32 767 тактов на половину символа; 0 — маркер конца
Символы bit0 / bit1
0x00098003 / 0x00068007«0»: 3 + 9 такта, «1»: 7 + 6
Кадр ленты
2,152 мс60 × 24 бита по 1300 нс и сброс; не чаще 464,7 кадров/с
Пауза сброса
280 мксesp_rom_delay_us() после rmt_tx_wait_all_done(): линия остаётся низкой, символы на сброс не тратятся
Символов на кадр
1440блок 64: драйвер подкачивает по половине, ≈ 44 прерываний на кадр
ДлительностьТактовПолучитсяДопуск
T0H — единица «0»3300 нс220–380 нс
T0L — ноль «0»9900 нс580–1000 нс
T1H — единица «1»7700 нс580–1000 нс
T1L — ноль «1»6600 нс580–1000 нс

RMT ESP32

8 каналов, каждый на передачу или приём; блок памяти 64 символов по 4 байта, всего 512 слов; DMA нет.

Код ESP-IDF v5/v6

#include "driver/rmt_tx.h"
#include "driver/rmt_encoder.h"
#include "esp_rom_sys.h"

rmt_channel_handle_t tx_chan = NULL;
rmt_tx_channel_config_t tx_config = {
    .gpio_num = 18,
    .clk_src = RMT_CLK_SRC_APB,
    .resolution_hz = 10000000,   /* 1 tick = 100 ns */
    .mem_block_symbols = 64,   /* one block of ESP32 */
    .trans_queue_depth = 4,
};
ESP_ERROR_CHECK(rmt_new_tx_channel(&tx_config, &tx_chan));

rmt_encoder_handle_t led_encoder = NULL;
rmt_bytes_encoder_config_t bytes_config = {
    .bit0 = { .level0 = 1, .duration0 = 3, .level1 = 0, .duration1 = 9 },
    .bit1 = { .level0 = 1, .duration0 = 7, .level1 = 0, .duration1 = 6 },
    .flags.msb_first = 1,   /* G7…G0 R7…R0 B7…B0 */
};
ESP_ERROR_CHECK(rmt_new_bytes_encoder(&bytes_config, &led_encoder));
ESP_ERROR_CHECK(rmt_enable(tx_chan));

static uint8_t pixels[60 * 3];   /* G, R, B for each LED */
rmt_transmit_config_t tx = { .loop_count = 0 };   /* the line stays low after the frame */
ESP_ERROR_CHECK(rmt_transmit(tx_chan, led_encoder, pixels, sizeof(pixels), &tx));
ESP_ERROR_CHECK(rmt_tx_wait_all_done(tx_chan, portMAX_DELAY));
esp_rom_delay_us(280);   /* reset: low for the latch time before the next frame */

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

RMT (Remote Control Transceiver) — периферия ESP32, которая выдаёт на вывод заранее записанную последовательность импульсов или записывает принятую. Изначально она задумана для ИК-пультов, но так же удобно генерирует сигнал адресных светодиодов WS2812, DShot для регуляторов и любой другой протокол, где важны длительности. Калькулятор считает то, что драйвер ESP-IDF делает при создании канала, и переводит времена протокола в такты.

Каналы и память по чипам

Канал читает символы из своего блока памяти. Если передача длиннее блока, драйвер подкачивает данные по прерыванию половинами блока; у ESP32-S3 вместо этого можно включить DMA.

ЧипКаналыБлокВся памятьИсточники такта
ESP328, каждый на передачу или приём64 символа512 словAPB 80 МГц, REF_TICK 1 МГц
ESP32-S24, каждый на передачу или приём64 символа256 словAPB 80 МГц, REF_TICK 1 МГц
ESP32-S34 передающих и 4 приёмных48 символов384 словаAPB 80 МГц, RC_FAST ≈ 17,5 МГц, XTAL 40 МГц
ESP32-C32 передающих и 2 приёмных48 символов192 словаAPB 80 МГц, RC_FAST ≈ 17,5 МГц, XTAL 40 МГц
ESP32-C62 передающих и 2 приёмных48 символов192 словаPLL_F80M 80 МГц, RC_FAST ≈ 17,5 МГц, XTAL 40 МГц
ESP32-H22 передающих и 2 приёмных48 символов192 словаXTAL 32 МГц, RC_FAST ≈ 8,5 МГц

Число каналов и объём памяти — из технических руководств (TRM), размер блока и источники такта — из заголовков ESP-IDF v6.1 soc_caps.h и clk_tree_defs.h. Первый источник в каждой строке — RMT_CLK_SRC_DEFAULT. Частота RC_FAST в заголовке приблизительная: это внутренний RC-генератор, и драйвер берёт её откалиброванное значение. Для WS2812 и ИК надёжнее кварц или APB.

Разрешение и делители

Поле resolution_hz задаёт частоту счёта тактов канала. У ESP32 и ESP32-S2 каждый канал делит частоту источника сам, делителем от 1 до 256. У S3, C3, C6 и H2 перед каналами стоит ещё общий делитель группы. Драйвер перебирает его от 1 до 256 и берёт первое значение, при котором округлённый делитель канала помещается в 1…256 — так такт группы остаётся наибольшим:

fканал=⌊fгруппаNканал⌋,Nканал=round⁡fгруппаfзапрошено,fгруппа=⌊fисточникNгруппа⌋.f_\text{канал} = \left\lfloor \frac{f_\text{группа}}{N_\text{канал}} \right\rfloor, \qquad N_\text{канал} = \operatorname{round}\frac{f_\text{группа}}{f_\text{запрошено}}, \qquad f_\text{группа} = \left\lfloor \frac{f_\text{источник}}{N_\text{группа}} \right\rfloor.

Например, 100 кГц у ESP32-C3: при делителе группы 1, 2 и 3 делитель канала получается 800, 400 и 267 — больше 256, при 4 такт группы 20 МГц, а делитель канала 200. У ESP32 делителя группы нет, и 100 кГц от APB не получить: нужен REF_TICK. Если частота не делится нацело, драйвер пишет в журнал предупреждение «channel resolution loss» и работает с фактическим разрешением — длительности считайте от него.

Символ RMT

Символ — 32-битное слово rmt_symbol_word_t из двух половин: 15 бит длительности в тактах и бит уровня. Сначала выводится level0 на duration0 тактов, затем level1 на duration1:

Биты0–141516–3031
Полеduration0level0duration1level1

Длительность — от 1 до 32 767 тактов, ноль передатчик понимает как маркер конца передачи. Отсюда два ограничения: время, которое при округлении даёт 0 тактов, обрывает передачу, а время дольше 32 767 тактов не помещается в поле. Длинную паузу разбивают на несколько символов, а разрешение выбирают так, чтобы самое длинное время протокола поместилось. У S3, C3, C6 и H2 есть и нижняя граница: по TRM ненулевой период должен быть больше 5TAPB+6Trmt_sclk5 T_\text{APB} + 6 T_\text{rmt\_sclk} — при APB 80 МГц и такте группы 80 МГц это 137,5 нс. Период прямо перед маркером конца по TRM должен быть ещё длиннее — больше 10TAPB+19Trmt_sclk10 T_\text{APB} + 19 T_\text{rmt\_sclk}, 362,5 нс при тех же частотах. Это правило дано в разделе о непрерывной передаче (loop_count); при разовой передаче линия после последнего бита и так остаётся низкой.

WS2812

Для лент кодировщик байтов rmt_new_bytes_encoder превращает каждый бит в символ bit0 или bit1: единица на время T0H или T1H, затем ноль. WS2812 принимает цвета в порядке G, R, B старшим битом вперёд, поэтому msb_first = 1. Калькулятор округляет времена до тактов и сверяет результат с таблицей даташита WS2812B-V5/W — той же, что в калькуляторе WS2812.

ВремяПример ESP-IDFПри 10 МГцДаташит WS2812B-V5/W
T0H0,3 мкс3 такта220–380 нс
T0L0,9 мкс9 тактов580–1000 нс
T1H0,9 мкс9 тактов580–1000 нс
T1L0,3 мкс3 такта580–1000 нс
Сброс50 мкс250 + 250 тактовбольше 280 мкс

В примере ESP-IDF T1L и пауза сброса короче, чем требует даташит V5: светодиод различает 0 и 1 по длительности единицы, поэтому многие ленты такие времена принимают, но гарантии уже нет. Кнопка «В допусках даташита» ставит времена, которые укладываются в таблицу при 10 МГц. Калькулятор округляет до ближайшего такта, а пример отбрасывает дробную часть; при 10 МГц результат одинаковый. Паузу сброса код калькулятора не передаёт символами, а выдерживает задержкой после окончания передачи.

Сложнее всего с ESP32-H2: у него APB не быстрее 32 МГц, и минимальный период по TRM — 343,75 нс при любом разрешении, ведь слагаемое 5TAPB от разрешения не зависит. Даташит WS2812B допускает T0H не больше 380 нс, поэтому на H2 годится только 350–380 нс. Ещё строже правило перед маркером конца — 906,25 нс, так что для непрерывной передачи низкие участки бита на H2 нужны около 950 нс. Кнопка «В допусках даташита» на H2 ставит 350/950/700/950 нс при 8 МГц.

ИК-код NEC и несущая

Кадр NEC — начальная пачка 9 мс и пауза 4,5 мс, 32 бита и завершающая пачка; единица и ноль различаются длиной паузы. Длительности калькулятор берёт из модуля калькулятора NEC — кратные 562,5 мкс, округлённые до тактов; пример ESP-IDF вместо них берёт 560 и 1690 мкс, на 3 мкс короче, — и собирает 34 символа для кодировщика копирования. При 1 МГц они помещаются в один блок памяти.

Несущую 38 кГц формирует отдельный генератор канала, он считает такты группы. Драйвер делит их целочисленно: при такте 80 МГц период несущей — 2105 тактов, из них 694 — высокий уровень при скважности 33 %, а фактическая частота 38 004 Гц. От REF_TICK 1 МГц получится лишь 26 тактов на период и 38 461 Гц. По описанию регистров в TRM S2, S3, C3, C6 и H2 каждая половина периода несущей на такт длиннее записанного числа; на 38 кГц от 80 МГц это меньше 0,1 %, для ИК-приёмника несущественно. В TRM ESP32 текст главы 30.2.4 говорит, что несущая считает делённый такт канала, а описание регистра 30.7 — что такты APB или REF_TICK; калькулятор, как и драйвер, считает от частоты источника.

Код, который выдаёт калькулятор, рассчитан на драйвер driver/rmt_tx.h и driver/rmt_encoder.h из руководства ESP-IDF v6.1, тот же API есть в ESP-IDF v5. Как устроены сами ИК-пульты и коды, разобрано в калькуляторе NEC, а ШИМ для яркости и моторов на ESP32 — в калькуляторе LEDC.

Частые вопросы

Какое разрешение RMT выбрать для WS2812?

10 МГц, то есть такт 100 нс, как в примере ESP-IDF: допуск T0H у WS2812B — 220–380 нс, и при более грубом такте длительность после округления легко выходит за него. При 4 МГц 350 нс превращаются в 250 нс, а 600 нс — в 500 нс, что уже меньше 580 нс по даташиту. Наибольшая длительность при 10 МГц — 32 767 тактов, 3,28 мс, сброс 280 мкс помещается с запасом. У ESP32-H2 источник — кварц 32 МГц, и 10 МГц точно не получить: делитель 3 даёт 10,67 МГц, и T1L 600 нс превращается в 562,5 нс. Для H2 берите 8 или 16 МГц.

Что значит предупреждение «channel resolution loss» драйвера RMT?

Драйвер делит частоту источника целым делителем от 1 до 256, и запрошенное разрешение не получилось точно. Например, 3 МГц от APB 80 МГц дают делитель 27 и 2 962 962 Гц. Длительности тогда считайте от фактического разрешения — калькулятор показывает именно его — или выберите разрешение, на которое частота источника делится нацело.

Почему NEC с разрешением 10 МГц не работает?

Половина символа RMT — не больше 32 767 тактов, а начальная пачка NEC длится 9 мс: при 10 МГц это 90 000 тактов. Наибольшее разрешение, при котором 9 мс помещаются в одно поле, — около 3,64 МГц. Для ИК берут 1 МГц, такт 1 мкс, как в примере ESP-IDF: этого хватает с большим запасом, а несущую 38 кГц формирует отдельный генератор от такта группы.

Источники

  1. Espressif. ESP-IDF Programming Guide v6.1: Remote Control Transceiver (RMT) — символ RMT — два 15-битных периода и два бита уровня; поля rmt_tx_channel_config_t (clk_src, resolution_hz, mem_block_symbols не меньше 64 у ESP32 и S2 и не меньше 48 у S3, C3, C6, H2); rmt_bytes_encoder_config_t (bit0, bit1, msb_first); rmt_carrier_config_t (frequency_hz, duty_cycle); пример несущей 38 кГц, 33 %; страницы для каждого чипа
  2. Espressif. ESP-IDF v6.1, исходный код драйвера и HAL RMT — rmt_common.c — подбор делителя группы и канала (rmt_select_periph_clock, rmt_set_group_prescale), сообщение «channel resolution loss»; rmt_tx.c — несущая из такта группы целочисленным делением; esp_hal_rmt/<чип>/rmt_ll.h — число каналов TX и RX, делители до 256; soc/<чип>/soc_caps.h и clk_tree_defs.h — размер блока, источники такта, RC_FAST ≈ 17,5 и 8,5 МГц; hal/rmt_types.h — rmt_symbol_word_t (эталон тестов)
  3. Espressif. ESP32 Technical Reference Manual, версия 5.8 — глава 30: 8 каналов, ОЗУ 512 × 32 бит блоками по 64 слова, нулевой период — маркер конца, такт APB 80 МГц или REF_TICK через 8-битный делитель
  4. Espressif. Technical Reference Manuals ESP32-S2 v1.3, S3 v1.8, C3 v1.4, C6 v1.2, H2 v1.2 — главы RMT: S2 — 4 канала и 256 слов блоками по 64; S3 — 4 TX и 4 RX, 384 слова блоками по 48; C3, C6, H2 — 2 TX и 2 RX, 192 слова; делитель канала, 0 означает 256; правило 5·T_apb + 6·T_rmt_sclk < период у S3, C3, C6, H2; половина периода несущей — значение регистра плюс один такт
  5. Espressif. ESP-IDF v6.1, примеры peripherals/rmt/led_strip и ir_nec_transceiver — WS2812 на 10 МГц: T0H 0,3 мкс, T0L 0,9 мкс, T1H 0,9 мкс, T1L 0,3 мкс, сброс 50 мкс; NEC на 1 МГц: 9000/4500, 560/560, 560/1690 мкс, завершающий символ с хвостом 0x7FFF, несущая 38 кГц, 33 %
  6. Worldsemi. WS2812B-V5/W Intelligent control LED integrated light source, datasheet V6.1 — T0H 220–380 нс, T1H, T0L и T1L 580 нс – 1 мкс, сброс дольше 280 мкс, порядок G, R, B старшим битом вперёд — те же значения, что у калькулятора WS2812

Где пригодится

Встроить калькулятор на свой сайт

Скопируйте код и вставьте его в HTML страницы, статьи или вики. Виджет бесплатный, без рекламы, счётчиков и cookie. Условие одно — ссылка на GAW под рамкой остаётся на месте. Подробнее о виджетах

<iframe src="https://gaw.ru/embed/esp32-rmt/" title="RMT ESP32: разрешение, символы и код ESP-IDF" width="100%" height="640" style="border:1px solid #e3e5e9;border-radius:8px" loading="lazy" allow="clipboard-write"></iframe>
<p style="margin:6px 0 0;font-size:14px">Калькулятор: <a href="https://gaw.ru/tools/esp32-rmt/">RMT ESP32: разрешение, символы и код ESP-IDF</a> — GAW.ru</p>
Автоподстройка высоты рамки

Если сайт разрешает скрипты, добавьте этот код один раз в любом месте страницы: рамка будет менять высоту вместе с результатом расчёта.

<script>window.addEventListener("message",function(e){if(e.origin!=="https://gaw.ru"||!e.data||e.data.type!=="gaw:embed-height")return;var f=document.querySelectorAll('iframe[src^="https://gaw.ru/embed/"]');for(var i=0;i<f.length;i++)if(f[i].contentWindow===e.source)f[i].style.height=e.data.height+"px"})</script>

Обновлено .

Нашли ошибку в расчёте?