Files
OptoTest/README.md

211 lines
14 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Optical Channel Tester — ESP32-C3 / ESP32-S3
Полностью рабочий Arduino IDE-проект для строгой проверки оптического цифрового канала. Устройство формирует PWM аппаратным LEDC, пропускает его через проверяемый канал и проверяет каждый завершённый период отдельно: частоту и заполнение. Поддерживаются роли `SOLO`, `MASTER` и `SLAVE`; роли выбираются только вручную.
## Что реализовано
- неблокирующий конечный автомат без `pulseIn()` и длинных `delay()`;
- аппаратный LEDC с расчётом реально получившихся частоты, разрядности и duty;
- Arduino-ESP32 3.3.10: потоковый аппаратный RMT RX (`partial RX`), ping-pong на C3 и DMA на S3;
- безопасный 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;
- `Receiver.*` — RMT RX / совместимый fallback;
- `Measurement.*` — строгая проверка периодов;
- `Protocol.*`, `Radio.*` — ESP-NOW;
- `App.*` — общий конечный автомат SOLO/MASTER/SLAVE.
Каталог `tests` содержит локальные unit-тесты чистой логики и автомата кнопок.
## Требования 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` и могут быть изменены до сборки.
| Сигнал | ESP32-C3 | ESP32-S3 |
|---|---:|---:|
| PWM output | GPIO 3 | GPIO 4 |
| Optical RX input | GPIO 4 | GPIO 5 |
| START | GPIO 0 | GPIO 6 |
| MODE | GPIO 1 | GPIO 7 |
| OLED SDA | GPIO 6 | GPIO 8 |
| OLED SCL | GPIO 7 | GPIO 9 |
### OLED
Подключите SSD1306 128×32: `VCC → 3.3 V`, `GND → GND`, `SDA/SCL` по таблице. Адрес по умолчанию `0x3C`. Если OLED не отвечает, тест продолжает работать и пишет диагностику в Serial 115200.
### Работа вообще без OLED
OLED можно не подключать. Откройте Serial Monitor на **115200 baud**: каждый экран всегда дублируется одной строкой вида:
```text
[ 1250][UI ] MODE: SOLO | START=RUN
```
В Serial также выводятся:
- каждое распознанное нажатие START/MODE и текущее состояние автомата;
- вход, изменение и сохранение каждого пункта меню;
- загрузка, проверка и сохранение NVS;
- запуск/остановка PWM и реальные параметры LEDC;
- начало этапа, число отбрасываемых периодов и параметры измерительного окна;
- все действия ESP-NOW, peer, session/stage/sequence, ACK и повторы;
- статистика этапа, первый плохой период и итоговая причина завершения;
- все строки, которые были бы показаны на OLED.
Во время строгого измерительного окна отдельные импульсы намеренно не печатаются: они проверяются потоково, а итоговая статистика выводится после окна. Это предотвращает влияние Serial на точность и переполнение очереди RMT. Журнал действий включён параметрами в `Config.h`:
```cpp
constexpr bool SERIAL_ACTION_LOG = true;
constexpr bool SERIAL_LOG_TIMESTAMPS = true;
```
### Кнопки
По умолчанию задано:
```cpp
#define BUTTON_ACTIVE_LEVEL LOW
```
Поэтому каждая кнопка подключается между своим GPIO и GND, а прошивка автоматически включает `INPUT_PULLUP`.
Если установить `BUTTON_ACTIVE_LEVEL HIGH`, подключайте кнопку между GPIO и 3.3 V; автоматически будет использован `INPUT_PULLDOWN`. Других изменений логики не требуется.
## Подключение сигнала
### SOLO
```text
ESP GPIO_PWM -> вход передатчика оптического канала
выход приёмника оптического канала -> ESP GPIO_RX
GND ESP -> GND входной/выходной электроники (если канал не гальванически развязан)
```
### MASTER / SLAVE
```text
MASTER GPIO_PWM -> вход передатчика проверяемого канала
выход приёмника проверяемого канала -> SLAVE GPIO_RX
MASTER <~~~~ ESP-NOW Wi-Fi channel 6 ~~~~> SLAVE
```
На обеих ESP должны совпадать `ESPNOW_WIFI_CHANNEL` и версия прошивки. Slave сначала переводится в `SLAVE READY` кнопкой START, затем START нажимается на Master.
**GPIO ESP32 допускают только логические уровни 0…3.3 В.** Не подавайте 5 В на `GPIO_RX`; применяйте согласование уровня. Если оптический приёмник инвертирует сигнал, установите:
```cpp
#define RX_SIGNAL_INVERTED true
```
## Управление
В ожидании:
- MODE short: `SOLO → MASTER → SLAVE → SOLO`, выбранная роль сохраняется;
- MODE long: открыть настройки;
- START short: начать тест;
- START long во время теста: ABORT, PWM немедленно выключается.
В настройках:
- MODE short: следующий параметр;
- MODE long: проверить диапазон, сохранить один раз в NVS и выйти;
- START short: следующее значение;
- START long: предыдущее значение, затем autorepeat при удержании.
Удержание обеих кнопок минимум 1.5 с при включении восстанавливает defaults.
## Настройка диапазона
Редактируйте отдельные `constexpr`-массивы в `Config.h`. Начальная и конечная частоты намеренно находятся в разных массивах. Сохранённые индексы всегда проверяются; после изменения массивов повреждённая/несовместимая настройка не приводит к выходу за границы.
Последовательность всегда начинается точно с START, идёт с STEP и завершается точно END. Например, `100…1000` с шагом `300` даёт `100, 400, 700, 1000`. Конечная точка не дублируется, вычисления выполняются через 64-битные промежуточные значения.
`ALL` пересчитывается после изменения START, END, STEP, TEST TIME или REPEATS. Частота каждой точки предварительно запрашивается у LEDC с duty=0 (на выходе остаётся безопасный уровень), поэтому в расчёте используется фактически достижимая частота. Для каждой точки учитывается:
```text
PWM_SETTLE_CYCLES / actualFrequency + TEST_TIME * REPEATS
```
## Строгая проверка
После каждой перенастройки PWM приёмник:
1. отбрасывает ровно `PWM_SETTLE_CYCLES` полных периодов;
2. очищает статистику;
3. непрерывно проверяет все полные периоды всех повторов.
Незавершённый период в начале и конце окна не учитывается. Период, пересекающий границу повторов, не теряется. Для каждого периода отдельно вычисляются частота и duty; средние используются только для диагностики. Любой один выход за допуск немедленно завершает всю проверку.
Причины: `NO SIGNAL`, `PERIOD OUT`, `DUTY OUT`, `EXTRA EDGE`, `GLITCH`, `LOST EDGE`, `TOO FEW PERIODS`, `LINK LOST`, `UNSUPPORTED`, `RESOLUTION`, `ABORTED`.
### Пределы
- C3: гарантированный проектный диапазон до 10 кГц; настраиваемый строгий предел по умолчанию 100 кГц;
- S3: строгий предел до 1 МГц только при рабочем RMT DMA;
- выше строгого аппаратного предела выдаётся `UNSUPPORTED`, ослабленной проверки нет;
- комбинации, для которых LEDC или RX timer не дают выбранную точность, завершаются `RESOLUTION` до запуска заведомо неверного теста.
Реальный предел зависит от конкретной платы, разводки, формы фронтов, Wi-Fi нагрузки и оптического оборудования. Начинайте проверку с 100 Гц…10 кГц.
## Первый запуск SOLO
1. Соберите схему SOLO и ещё раз убедитесь, что на `GPIO_RX` не бывает напряжения выше 3.3 В.
2. Откройте Serial Monitor на 115200 baud.
3. Включите плату. На OLED должно быть `MODE: SOLO` / `START=RUN`.
4. Если выбран другой режим, коротко нажимайте MODE до SOLO.
5. Для первого опыта оставьте defaults: 100 Гц…10 кГц, duty 50%, accuracy 5%.
6. Коротко нажмите START.
7. Serial покажет запрошенные и фактические параметры LEDC, список частот, ALL и статистику каждой точки.
8. Успех: `PASS ...` / `START=REPEAT`. Ошибка: `FAIL AT ...` и точная причина.
## Проверка проекта
Финальный исходный код собран Arduino CLI, использующим тот же builder, что и Arduino IDE:
| Target | Arduino-ESP32 | Flash | RAM | Результат |
|---|---:|---:|---:|---|
| ESP32-C3 | 3.3.10 | 1,024,299 B (78%) | 39,460 B (12%) | PASS |
| ESP32-S3 | 3.3.10 | 950,608 B (72%) | 48,620 B (14%) | PASS |
Локальные unit-тесты: `core tests: PASS`, `button tests: PASS`. Они покрывают неделимый диапазон, END без дубля, ALL, границы допусков, немедленный FAIL, resolution, checksum настроек, CRC протокола и отсутствие short после long.
Физическое оборудование в этой среде недоступно, поэтому реальные оптические фронты, RMT DMA под длительной нагрузкой, дальность ESP-NOW и электрическая совместимость должны быть проверены на ваших платах. Сборка и программные тесты не выдаются за аппаратный тест.