Optical Channel / Gate Driver Tester — ESP32-C3 / ESP32-S3

Полностью рабочий Arduino IDE-проект для строгой проверки оптического цифрового канала. Устройство формирует PWM на выбранной частоте, последовательно уменьшает длительность импульса по заданному списку и проверяет ответ канала: частоту и длительность импульса. Поддерживаются роли SOLO, MASTER и SLAVE; роли выбираются только вручную.

Что реализовано

  • неблокирующий конечный автомат без pulseIn() и длинных delay();
  • общие для оптического и драйверного тестов частота PWM и диапазон импульсов;
  • четыре рабочих режима: SOLO OPTICAL, SOLO DRIVER (только S3), MASTER OPTICAL, SLAVE OPTICAL;
  • настраиваемый для теста драйвера код HH, HL, LH, LL; в тесте оптики полярность входного сигнала определяется автоматически;
  • аппаратные LEDC (C3) и MCPWM (S3) с расчётом реально получившихся частоты и длительности импульса;
  • Arduino-ESP32 3.3.10: на S3 два аппаратных канала MCPWM Capture из отдельной группы фиксируют RISING и FALLING в независимых регистрах общего 32-битного таймера 80 МГц;
  • безопасный fallback для старых Arduino-ESP32 3.x через GPIO edge ISR и аппаратный CPU cycle counter (верхний предел при этом автоматически ограничен 100 кГц);
  • отбрасывание ровно PWM_SETTLE_CYCLES полных периодов;
  • потоковая статистика без хранения всех периодов;
  • немедленный FAIL по первому отдельному импульсу или периоду вне допуска;
  • десять измерительных участков на каждой длительности импульса с промежуточным отображением результата;
  • ESP-NOW discovery, handshake, CRC, session/stage/sequence, ACK, повторы и защита от старых пакетов;
  • SSD1306 128×32: каждый экран всегда состоит ровно из двух строк;
  • две кнопки, debounce, long press и repeat; после long press ложный short click не создаётся;
  • Preferences/NVS с версией структуры, checksum, проверкой индексов и восстановлением defaults;
  • работа через Serial при отсутствующем OLED;
  • безопасное выключение PWM при PASS, FAIL, ABORT и потере связи.
  • полный журнал действий в Serial с временными метками; OLED необязателен.

Файлы

Arduino sketch находится в каталоге OpticalChannelTester:

  • OpticalChannelTester.ino — стандартная точка входа Arduino IDE;
  • Config.h — GPIO, тайм-ауты, пределы и все пользовательские массивы;
  • Core.* — последовательность длительностей, ALL, допуски, статистика;
  • Buttons.* — автомат двух кнопок;
  • SettingsStore.* — NVS;
  • Display.* — OLED и компактное форматирование;
  • Log.* — журнал действий и Serial-зеркало интерфейса;
  • Pwm.* — LEDC / MCPWM;
  • Receiver.* — MCPWM Capture на S3 / совместимый GPIO fallback;
  • Measurement.* — строгая проверка периодов;
  • Protocol.*, Radio.* — ESP-NOW;
  • App.* — общий конечный автомат SOLO/MASTER/SLAVE.

Требования Arduino IDE

Проверенная конфигурация:

  • Arduino IDE 2.x;
  • пакет плат esp32 by Espressif Systems 3.3.10;
  • Adafruit GFX Library 1.12.1;
  • Adafruit SSD1306 2.5.15;
  • Adafruit BusIO устанавливается Library Manager как зависимость.

В Arduino IDE откройте OpticalChannelTester/OpticalChannelTester.ino. Не переносите один .ino отдельно: остальные вкладки являются частью скетча.

Для C3 выберите подходящую плату ESP32-C3, например ESP32C3 Dev Module. Для S3 — ESP32S3 Dev Module. Затем выберите порт и нажмите Verify/Upload.

GPIO

Все назначения находятся в начале Config.h и могут быть изменены до сборки.

Сейчас в Config.h включён #define MAKETKA. В этом профиле используются следующие назначения:

Сигнал ESP32-C3 ESP32-S3
PWM output GPIO 3 GPIO 12
Optical RX input GPIO 4 GPIO 13
START GPIO 1 GPIO 10
MODE GPIO 0 GPIO 9
OLED SDA GPIO 6 GPIO 44
OLED SCL GPIO 7 GPIO 1

Если закомментировать #define MAKETKA, включается профиль производственной PCB:

Сигнал ESP32-C3 ESP32-S3
PWM output GPIO 3 GPIO 12
Optical RX input GPIO 4 GPIO 13
START GPIO 10 GPIO 4
MODE GPIO 20 GPIO 5
VBAT GPIO 2 GPIO 11
Analog RX GPIO 0 GPIO 9
OLED SDA GPIO 6 GPIO 44
OLED SCL GPIO 7 GPIO 1

Оба профиля рассчитаны на установку S3 с совмещением контактов 5V и GND с модулем C3. Номера GPIO S3 выбраны по тому же физическому ряду разъёма, а не по совпадению номера GPIO.

На ESP32-C3 PWM формируется через LEDC с аппаратным дробным делителем Q10.8. На ESP32-S3 используется отдельный MCPWM со счётчиком 20 МГц: это позволяет формировать 500 Гц в пределах 16-битного счётчика и сохраняет шаг импульса 50 нс. TX_LIGHT_ON_GPIO_LEVEL задаёт постоянное свойство схемы: какой физический уровень PIN_TX включает свет. Для приведённой схемы с SN75451 это HIGH. Пользовательский код света не изменяет это соответствие. При остановке PWM прошивка выдаёт TX_LIGHT_OFF_GPIO_LEVEL. Перед началом точки проверяется, что фактические частота и длительность укладываются в выбранную точность.

OLED

Подключите SSD1306 128×32: VCC → 3.3 V, GND → GND, SDA/SCL по таблице. Адрес по умолчанию 0x3C. Если OLED не отвечает, тест продолжает работать и пишет диагностику в Serial 115200.

Работа вообще без OLED

OLED можно не подключать. Откройте Serial Monitor на 115200 baud: каждый экран всегда дублируется одной строкой вида:

[      1250][UI      ] MODE: SOLO | START=RUN

Полоса прогресса учитывает номер длительности импульса и десять измерительных участков внутри неё.

В Serial также выводятся:

  • каждое распознанное нажатие START/MODE и текущее состояние автомата;
  • вход, изменение и сохранение каждого пункта меню;
  • загрузка, проверка и сохранение NVS;
  • запуск/остановка PWM и реальные параметры LEDC;
  • начало этапа, число отбрасываемых периодов и параметры измерительного окна;
  • все действия ESP-NOW, peer, session/stage/sequence, ACK и повторы;
  • статистика этапа, первый плохой период и итоговая причина завершения;
  • все строки, которые были бы показаны на OLED.

Во время строгого измерительного окна отдельные импульсы намеренно не печатаются: они проверяются потоково, а итоговая статистика выводится после окна. Это предотвращает влияние Serial на точность и переполнение очереди аппаратных фронтов. Журнал действий включён параметрами в Config.h:

constexpr bool SERIAL_ACTION_LOG = true;
constexpr bool SERIAL_LOG_TIMESTAMPS = true;

Кнопки

По умолчанию задано:

#define BUTTON_ACTIVE_LEVEL LOW

Поэтому каждая кнопка подключается между своим GPIO и GND, а прошивка автоматически включает INPUT_PULLUP.

Если установить BUTTON_ACTIVE_LEVEL HIGH, подключайте кнопку между GPIO и 3.3 V; автоматически будет использован INPUT_PULLDOWN. Других изменений логики не требуется.

Подключение сигнала

SOLO

ESP GPIO_PWM -> вход передатчика оптического канала
выход приёмника оптического канала -> ESP GPIO_RX
GND ESP -> GND входной/выходной электроники (если канал не гальванически развязан)

MASTER / SLAVE

MASTER GPIO_PWM -> вход передатчика проверяемого канала
выход приёмника проверяемого канала -> SLAVE GPIO_RX
MASTER <~~~~ ESP-NOW Wi-Fi channel 6 ~~~~> SLAVE

На обеих ESP должны совпадать ESPNOW_WIFI_CHANNEL и версия прошивки. Slave сначала переводится в SLAVE READY кнопкой START, затем START нажимается на Master.

Пока бодрствующий Slave находится в SLAVE READY, радиоприём работает периодически: окно 20 мс каждые 100 мс, а собственный оптический передатчик Slave выключен. При переходе Slave в light sleep ESP-NOW и Wi-Fi полностью отключаются, поэтому радиопакет не может его разбудить. Master во время поиска посылает серию DISCOVER каждые 20 мс и одновременно переключает реальный свет ON/OFF каждые OPTICAL_WAKE_HALF_PERIOD_MS. Изменение уровня на оптическом входе пробуждает Slave через GPIO; после этого Slave запускает ESP-NOW и принимает повторяемый DISCOVER.

GPIO ESP32 допускают только логические уровни 0…3.3 В. Не подавайте 5 В на GPIO_RX; применяйте согласование уровня. Полярность выхода оптического приёмника задаётся однозначно его активным уровнем:

Физический уровень выхода приёмника при включённом свете задаёт RX_LIGHT_ON_GPIO_LEVEL. Код HH/HL/LH/LL используется только тестом драйвера. В тесте оптики приёмник сравнивает первые интервалы с ожидаемой длительностью и автоматически выбирает фактически пришедшую полярность; при заполнении 50% выбор стороны не меняет измеренную длительность.

Управление

В ожидании на S3:

  • MODE short: SOLO ОПТИКА → SOLO ДРАЙВЕР → MASTER ОПТИКА → SLAVE ОПТИКА;
  • MODE long: открыть настройки;
  • START short: начать тест;
  • START long во время теста: ABORT, PWM немедленно выключается.

В настройках:

  • MODE short: следующий параметр;
  • MODE long: проверить диапазон, сохранить один раз в NVS и выйти;
  • START short: следующее значение;
  • START long: предыдущее значение, затем autorepeat при удержании.

Удержание обеих кнопок минимум 1.5 с при включении восстанавливает defaults.

Энергосбережение

В ожидании процессор работает на 80 МГц, во время теста и связанной MASTER/SLAVE-сессии — на 160 МГц. В тесте оптики активный импульс передатчика всегда соответствует свету ON и не зависит от настройки уровней. В SOLO ДРАЙВЕР, Slave, при остановленном PWM и во сне свет всегда принудительно выключен: драйвер не может остаться включённым после теста. После тайм-аута бездействия в IDLE, FINISHED или SLAVE READY OLED выключается, а ESP переходит в непрерывный light sleep без периодических таймерных пробуждений.

START и MODE будят устройство. Первое, пробуждающее нажатие не выполняет действие и полностью подавляется до отпускания кнопки; действие выполняет только следующее нажатие. Оптический wake-сигнал также немедленно выводит Slave из энергосбережения. Тайм-аут задаётся IDLE_POWER_SAVE_TIMEOUT_MS в Config.h.

Настройки теста

Меню содержит шесть общих параметров:

  1. частота ШИМ из PWM_FREQUENCY_OPTIONS_HZ;
  2. максимальная длительность импульса из отдельного MAX_PULSE_OPTIONS_NS;
  3. минимальная длительность импульса из отдельного MIN_PULSE_OPTIONS_NS;
  4. точность;
  5. время выборки.
  6. код света HH, HL, LH, LL — только для теста драйвера.

Экран активного уровня:

АКТ. УРОВЕНЬ:    HL
TX:H, RX:L

В тесте драйвера первая буква задаёт активное состояние света TX, вторая — активное состояние света RX. Буквы никогда не обозначают уровни GPIO. Для 1SP0635, у которого управление выполняется светом ON, а ACK передаётся светом OFF, типичен HL. В режимах оптики этот пункт показывает АВТО, кнопки не изменяют сохранённый код, а входная полярность определяется по принятому PWM.

Тест работает на одной выбранной частоте и проходит длительности из списка от максимальной к минимальной. Значения, равные периоду или превышающие его, автоматически исключаются при выборе частоты. На S3 минимальная длительность ограничивается расчётной точностью генератора и MCPWM Capture 80 МГц: длинная пауза не снижает точность короткого импульса. Меню не позволяет задать точку, которой аппаратно не хватает выбранного допуска. Сохранённые индексы и их сочетания проверяются и приводятся к допустимому диапазону.

MAX и MIN имеют независимые массивы и независимые индексы. Сам тест проходит отдельный полный список TEST_PULSE_WIDTHS_NS. Все пункты меню зациклены: после последнего допустимого значения выбирается первое, а при движении назад перед первым выбирается последнее.

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

max(TEST_TIME, periods / RX_PROCESSING_PERIODS_PER_SECOND)
+ PWM_SETTLE_CYCLES / actualFrequency × 10
+ OLED_PROGRESS_UPDATE_MS × 11

TEST TIME — это чистое время выборки сигнала, а не полная длительность этапа. На высоких частотах полная длительность заметно возрастает из-за проверки каждого периода. Расчёт использует консервативную производительность 300 тысяч периодов в секунду.

Строгая проверка

В тесте оптики после каждой перенастройки PWM приёмник:

  1. автоматически определяет фактически пришедшую полярность Rx; отдельные каналы MCPWM Capture S3 фиксируют RISING и FALLING в независимых регистрах общего 32-битного таймера 80 МГц;
  2. отбрасывает ровно PWM_SETTLE_CYCLES полных периодов;
  3. очищает статистику;
  4. непрерывно держит MCPWM Capture включённым на всём измерительном этапе, проверяет каждый полный импульс ровно один раз и на десяти границах TEST TIME показывает промежуточный результат; границы прогресса не останавливают capture и не выбрасывают пересекающий их импульс. Между длительностями сначала останавливается PWM, затем capture, поэтому очистка очереди не пересекается с ISR.

Каждый полный период и каждый активный импульс проверяются отдельно с выбранным относительным допуском 1%, 2%, 5% или 10%. Поэтому единичное искажение не растворяется в среднем остальных импульсов. После трёх начальных фронтов приёмник работает как простой автомат чередующихся интервалов «импульс — пауза»: тип последующих фронтов не используется, а лишний или потерянный фронт превращается в конкретный PULSE OUT или PERIOD OUT, не в абстрактный GLITCH. Для одного измерения допускается только коррекция на один такт приёмного таймера в сторону заданного значения — это неизбежная неопределённость фиксации фронта. Если после неё конкретная частота или длительность остаётся вне допуска, тест немедленно завершается ошибкой. Накопленное среднее используется только для строк F:..., P:... и итогового журнала. Переполнение очереди фронтов немедленно даёт DATA LOSS ERROR.

Во время этапа OLED показывает заданную точку и измеренный ответ, например:

TEST: 2kHz, 2us
F:2.000k, P:2.00u

При ошибке сохраняется прежний двухстрочный стиль с конкретным значением, вышедшим за допуск:

СБОЙ: 2kHz, 200us
ИМПУЛЬС: 300.01u

В MASTER/SLAVE передаются выбранная и фактическая длительность импульса и измеренный результат. На принимающей стороне полярность Rx определяется автоматически.

Незавершённый период в начале и конце временного участка не учитывается. Общая статистика и отображаемое среднее по всем принятым полным периодам этапа сохраняются, но решение PASS/FAIL принимается по каждому импульсу отдельно.

Причины: NO SIGNAL, PERIOD OUT, DUTY OUT (в интерфейсе — ошибка длительности импульса), EXTRA EDGE, GLITCH, LOST EDGE, DATA LOSS ERROR, LINK LOST, UNSUPPORTED, RESOLUTION, ABORTED.

Тест драйвера — только ESP32-S3

В SOLO ДРАЙВЕР используются те же частота, MAX/MIN, точность и время точки. Для драйверного теста минимальная выбираемая длительность входного импульса — 2 мкс. При переключении из оптического режима сохранённое значение меньше 2 мкс автоматически заменяется на 2 мкс. Частота, MAX, MIN и время точки остаются общими настраиваемыми параметрами.

Фронты PIN_RX и конец каждого импульса PIN_TX фиксируются аппаратным MCPWM Capture по общему 80-МГц таймеру с шагом 12,5 нс. Начало TX восстанавливается от аппаратно захваченного конца и фактической длительности, запрограммированной в MCPWM. Период выдаётся анализатору с задержкой в один цикл: следующий захваченный TX гарантирует, что оба 700-нс фронта предыдущего ACK уже находятся в аппаратном буфере.

Для каждого фронта TX ожидается активный ответ RX. Паспортные 250 нс до начала ACK и 700 нс его длительности используются как справочные величины, но не как условие PASS/FAIL: задержки тестовой передающей и принимающей оптики могут их сдвигать. Если полный импульс ответа присутствует, ACK считается принятым. Каждый RX сопоставляется с ближайшим предшествующим фронтом TX. Поэтому при пропуске одного ответа ACK следующего фронта не может быть ошибочно приписан пропущенному фронту с задержкой, равной длительности входного импульса плюс D. На OLED в режиме драйвера первая строка показывает параметры текущей точки ТЕСТ: частота, импульс, а вторая — измеренную задержку от фронта TX до начала ответа и длительность ответа в формате D: ..., P: .... Отсутствие начала ответа до предела 2 мкс даёт НЕТ ОТВЕТА ACK; проверка выполняется сразу для первого пропущенного фронта, без ожидания конца всей выборки. Отдельный импульс статуса драйвера и ответ, остающийся активным дольше 1,5 мкс, считаются АВАРИЯ ДРАЙВЕРА.

Для каждого проверяемого фронта TX всегда требуется отдельный полный ACK. При включении MCPWM Capture первый TX-импульс может уже идти: его конец будет захвачен, но начало ACK могло произойти раньше включения периферии. Поэтому два первых восстановленных периода используются только для синхронизации и освобождения отложенных событий независимых каналов фронтов. Проверка начинается с третьего периода; при 500 Гц это добавляет 4 мс, а не ожидание общего тайм-аута.

Время каждой точки делится на 10 равных подвыборок. Во время подвыборки OLED и Serial не обновляются. После каждой подвыборки захват и PWM останавливаются, на OLED выводятся накопленные D и P и прогресс, затем та же точка автоматически продолжается. Это исключает потерю короткого RX-фронта из-за I2C-обновления дисплея.

После успешного завершения последней точки OLED показывает ТЕСТ ПРОЙДЕН, а во второй строке сохраняет итоговые накопленные значения D и P.

При ошибке русская локализация не использует английские фразы FAIL AT, TEST, FREQ OUT или PULSE OUT. Первая строка показывает причину по-русски, вторая — T (время от вызвавшего аварию фронта TX до начала аварийного RX-импульса), D (задержку ошибочного ответа, если она определима) и P (длительность ошибочного RX-импульса). Для отсутствующего ACK значение P выводится как ---. Точные значения в наносекундах дополнительно записываются в Serial-журнал.

Подключение ESP32-S3 к работающему USB-хосту запрещает переход в light sleep, даже если COM-порт закрыт и обмена Serial нет. Краткие пропадания USB SOF фильтруются в течение 5 секунд. Кабель или зарядник только с питанием, без линий D+/D, программно определить невозможно без отдельного входа контроля VBUS. Тест идёт от MAX к MIN и останавливается на первой длительности, при которой драйвер перестал отвечать корректно. Это определяет границу распознавания входа, но не доказывает, что напряжение VGE успело полностью открыть IGBT.

Пределы

  • C3 и S3: настраиваемый строгий предел до 1 МГц;
  • выше строгого аппаратного предела выдаётся UNSUPPORTED, ослабленной проверки нет;
  • комбинации, для которых PWM или аппаратный capture не дают выбранную точность, отсекаются ещё в меню; повторная проверка перед стартом остаётся защитой от аппаратного сбоя.

Реальный предел зависит от конкретной платы, разводки, формы фронтов, Wi-Fi нагрузки и оптического оборудования. Начинайте проверку с 2 кГц и импульсов 200…2 мкс.

Первый запуск SOLO

  1. Соберите схему SOLO и ещё раз убедитесь, что на GPIO_RX не бывает напряжения выше 3.3 В.
  2. Откройте Serial Monitor на 115200 baud.
  3. Включите плату. На OLED должно быть MODE: SOLO / START=RUN.
  4. Если выбран другой режим, коротко нажимайте MODE до SOLO.
  5. Для первого опыта оставьте defaults: 2 кГц, импульсы 200…2 мкс, accuracy 5%. Полярность Rx определяется автоматически.
  6. Коротко нажмите START.
  7. Serial покажет запрошенные и фактические параметры PWM, список длительностей, ALL и статистику каждой точки.
  8. Успех: ТЕСТ ПРОЙДЕН. Ошибка: русская причина и строка таймингов.

Проверка проекта

Целевая версия проекта — Arduino-ESP32 3.3.10. В доступной среде исходный код собран Arduino CLI с этой версией:

Target Arduino-ESP32 Flash RAM Результат
ESP32-C3 3.3.10 1,045,075 B (79%) 41,012 B (12%) PASS
ESP32-S3 3.3.10 976,233 B (74%) 49,812 B (15%) PASS

Физическое оборудование в этой среде недоступно, поэтому реальные оптические фронты, MCPWM Capture под длительной нагрузкой, дальность ESP-NOW и электрическая совместимость должны быть проверены на ваших платах. Сборка и программные тесты не выдаются за аппаратный тест.

Description
Прога на ESP32 для тестирования оптики
Readme 32 MiB
Languages
C++ 85.7%
Pascal 10.7%
Python 1.9%
C 1.7%