INAV: возможности конкретных плат — справочник для board-aware (AD-705)
Статус: research / discovery + фактическая база данных, используемая кодом
(web/static/js/tools/inav_boards.js). Документ обосновывает, откуда взяты
байтовые/пиновые факты справочника, и фиксирует, что именно НЕ реализовано и
почему (честность важнее охвата).
0. Зачем это нужно
Фаза 1 (AD-705) — план: тула /tools/inav-connect должна знать возможности
КОНКРЕТНОГО подключённого борта (LED-пад, выделенный видео/камера-свитч,
реально обнаруженные сенсоры) и ненавязчиво подсказывать, как их применить.
Модель разрешения — 3 яруса: живой MSP-сигнал → статический справочник
плат → честный null («не знаем»). Этот документ — источник фактов для яруса
2 (справочник) и обоснование, почему часть яруса 1 (живые MSP-каналы)
отложена.
1. Источники и clean-room
Исходники INAV (github.com/iNavFlight/inav, ветка master, 9.1.0-dev,
получено 2026-07-20) читались ТОЛЬКО ради фактов: номера пинов
(PINIO*_PIN, WS2811_PIN), короткий идентификатор платы
(TARGET_BOARD_IDENTIFIER), наличие фич компиляции (USE_LED_STRIP,
USE_SDCARD), дефолтный box PINIO (pinioBoxConfigMutable()->permanentId[N]
в config.c каждого таргета). Это данные протокола/аппаратной конфигурации,
не творческий код — GPLv3-исходники INAV/INAV Configurator в наш репозиторий
не копировались; сами записи справочника и код lookupBoard/
resolveCapability написаны заново.
2. MSP2_INAV_STATUS (0x2000) — байтовый макет
Источники: src/main/fc/fc_msp.c (case MSP2_INAV_STATUS, сериализация
ответа) и src/main/fc/fc_msp_box.c (packSensorStatus() — раскладка
битовой маски сенсоров, используется И MSP_STATUS/MSP_STATUS_EX, И
MSP2_INAV_STATUS).
Поля ответа по порядку (наш кодек читает первые три u16 + armingFlags):
| Смещение | Поле | Тип | Комментарий |
|---|---|---|---|
| 0 | cycleTime |
u16 LE | не используется тулой |
| 2 | i2cErrorCounter |
u16 LE | не используется тулой |
| 4 | sensorStatus |
u16 LE | читаем — маска обнаруженных сенсоров |
| 6 | averageSystemLoadPercent |
u16 LE | не используется |
| 8 | profileByte |
u8 | (batteryProfile<<4)\|profile, не используется |
| 9 | armingFlags |
u32 LE | читаем (AD-830, SFHD-52) — бит ARMED; (AD-848) — плюс бит ARMING_DISABLED_SENSORS_CALIBRATING |
| 13.. | boxModeFlags |
переменной длины (растёт между версиями) | не используется, поэтому mixerProfile в самом хвосте НЕ читаем — его смещение зависит от длины этого поля |
packSensorStatus() (fc_msp_box.c):
bit0 = ACC, bit1 = BARO, bit2 = MAG, bit3 = GPS, bit4 = RANGEFINDER,
bit5 = OPFLOW, bit6 = PITOT, bit7 = TEMP, bit15 = аппаратный сбой (!isHardwareHealthy())
Gyro отдельным битом НЕ кодируется — по конвенции протокола считается всегда
присутствующим (SENSOR_GYRO = 1 << 0, // always present в sensors.h,
внутренний enum, не совпадает с битами packSensorStatus()).
Реализация: parseInavStatus() в web/static/js/tools/inav_msp.js —
короче 6 байт (3×u16) → null (честная деградация, не «сенсоров нет»).
2.1. armingFlags → бит ARMED (AD-830, SFHD-52)
Найденная причина «мотор не крутится из теста». Источник:
src/main/fc/runtime_config.h (armingFlag_e) — ARMED = (1 << 2) (там же
WAS_EVER_ARMED = (1 << 3) и дальше набор ARMING_DISABLED_* причин запрета
армирования, которые тула НЕ разбирает — нужен только сам факт ARMED).
Прошивка ведёт выходы моторов от motor_disarmed[] (то, что пишет
MSP_SET_MOTOR) ТОЛЬКО пока полётник разоружён; под ARM выход ведёт обычный
миксер/RC, override из motor test молча игнорируется — никакой ошибки в
MSP-обмене при этом нет, поэтому баг был не виден по логу MSP-кадров.
Деградация: ответ короче 13 байт (armingFlags физически отсутствует —
старая прошивка) → armed:null, честно «не знаем». Гейт motor test
(motorTestAllowed() в web/static/js/tools/inav_msp.js) блокирует ТОЛЬКО
подтверждённый armed:true — null не блокирует, иначе деградация статуса
сломала бы уже работавший (пусть и вслепую) путь на старой прошивке.
2.2. armingFlags → бит ARMING_DISABLED_SENSORS_CALIBRATING (AD-848)
Гейт вкладки «Калибровка». Источник: src/main/fc/runtime_config.h
(armingFlag_e) — ARMING_DISABLED_SENSORS_CALIBRATING = (1 << 9).
Прошивка (src/main/fc/fc_core.c, updateArmingStatus()/
areSensorsCalibrating()) выставляет этот бит, пока НЕ завершена калибровка
ХОТЯ БЫ ОДНОГО из: баро, компаса, акселя (только если он реально нужен
режимам полёта, isAccRequired()), pitot, nav — бит ОБЩИЙ на все эти
калибровки разом, не только на компас/аксель.
Кроме того, обе команды-триггера калибровки (MSP_ACC_CALIBRATION,
MSP_MAG_CALIBRATION) прошивка (src/main/fc/fc_msp.c) отклоняет
(MSP_RESULT_ERROR), пока полётник ARMED (тот же бит ARMED = (1 << 2),
что и у AD-830/motor test) — гейт калибровки на клиенте переиспользует
armed из § 2.1, отдельного бита для этого не требуется.
Из-за общего бита ARMING_DISABLED_SENSORS_CALIBRATING тула использует его
ТОЛЬКО как вспомогательный «борт подтверждает калибровку» сигнал для
компаса (tickMagCalibration() в web/static/js/tools/inav_msp.js) —
основной прогресс калибровки компаса даёт локальный таймер-фолбэк (протокол
не отдаёт точный прогресс). Для акселя авторитетный источник прогресса —
MSP_CALIBRATION_DATA (14, см. docs/tools/inav-connect.md § «Вкладка
«Калибровка»»): битовые флаги 6 положений НЕ делят бит с другими сенсорами
и потому честнее.
Деградация симметрична § 2.1: ответ короче 13 байт → calibrating:null.
3. MSP2_INAV_OUTPUT_MAPPING_EXT2 (0x210D) — ОТЛОЖЕНО
Канал обещал бы ярус 1 (живой сигнал) для «физический LED-пад по
timer-слоту pinLabel==PIN_LABEL_LED» — board-agnostic сигнал вместо
справочника. Не реализован в Фазе 2: byte-layout serialize-функции для
этой команды не удалось вывести с уверенностью из публичного fc_msp.c без
риска угадывания (в отличие от MSP2_INAV_STATUS, где packSensorStatus()
цитируется в самом файле fc_msp_box.c). Гадать по битам — то же самое, что
уже сознательно отвергнуто для LED legacy MSP_LED_STRIP_CONFIG (AD-703,
см. docs/tools/inav-connect.md § LED). Честность важнее охвата: пока канал
не проверен на реальном источнике/железе, ярус 1 для ledPad/vsw пуст,
разрешение падает на ярус 2 (справочник).
4. Справочник плат — таблица фактов
Для каждой платы: TARGET_BOARD_IDENTIFIER (короткий код MSP), WS2811_PIN
(LED-пад), PINIO*_PIN + дефолтный permanentId (видео/камера-свитч),
USE_SDCARD. Источник каждой строки — файл target.h/config.c таргета в
src/main/target/<TARGET>/ (ссылки — в самом справочнике,
web/static/js/tools/inav_boards.js, поле source).
| Плата (key) | boardId | WS2811 (LED-пад) | PINIO1 (VSW) | PINIO2 (camera) | SD | Заметка |
|---|---|---|---|---|---|---|
MATEKH743 |
H743 |
PA8 |
PD10, box USER1 |
PD11, box USER2 |
да | — |
MATEKF405SE (aka F405-WING / F405-Wing V2/V3) |
MF4S |
PA15 |
PC6 — НЕ заявлен доступным (см. § 7, AD-854) |
PC7 — НЕ заявлен доступным |
да | PINIO собран ТОЛЬКО в firmware-варианте MATEKF405SE_PINIO (#ifdef); базовая (дефолтная, единственная упомянутая на актуальном датащите V2/V3) прошивка держит те же пины как обычный UART6 TX/RX. TARGET_BOARD_IDENTIFIER/USBD_PRODUCT_STRING у ОБОИХ вариантов одинаковые — MSP не различает |
MATEKF405TE |
MF4T |
PB1 |
PA4, box USER1 |
PB5, box USER2 |
нет (SD — отдельный firmware-вариант MATEKF405TE_SD, не моделируем) |
— |
MATEKF722SE (aka F722-WING) |
MF7S (MINI-вариант — MF7M) |
PA8 |
PC8, box USER1 |
PC9, box USER2 |
нет в записи (не проверяли отдельно) | PINIO собран безусловно — общий для SE/MINI |
SPEEDYBEEF405WING |
SP4W |
PA8 |
PC13, box USER1 |
— (один PINIO) | да | — |
SPEEDYBEEF405V3 |
SB43 |
PC9 |
PC3, box USER1 (свободен) |
— | да | — |
SPEEDYBEEF405V4 |
SB44 |
PA8 |
PB11, box BOXARM по умолчанию |
— | не проверяли | ⚠ В отличие от V3, config.c V4 назначает permanentId[0] = BOXARM — пин физически тот же (video-switch по схеме), но не свободен под USER1. Справочник НЕ заявляет vsw доступным на V4 (см. caveats) |
5. Решение про vsw на SPEEDYBEEF405V4
Пин PB11 физически совпадает с назначением VSW на V3, но targetConfiguration()
в config.c V4 явно ставит pinioBoxConfigMutable()->permanentId[0] = BOXARM
(не BOX_PERMANENT_ID_USER1, как у всех остальных 6 плат справочника). Если бы
справочник заявил static.vsw доступным, движок рекомендаций посоветовал бы
использовать пин как видео-свитч — а по факту переключение этого пина
арм/дизармит борт. Решение: static.vsw для V4 не задан (запись не
проходит правило vsw-available), физика и предупреждение — в caveats[].
6. Решение про vsw на MATEKF405SE (SFHD-61/AD-854)
Багрепорт основателя (SFHD-61, /tools/inav-connect, вкладка «Выходы»,
платформа «Самолёт»): ✨-хинт «у этой платы есть выделенный пин VSW» показан
для платы Matek F405 Wing v2 — и, по словам основателя, у неё нет
управляемого питания (VSW-переключения камер). Оригинальное решение Фазы 2
(§ 4, строка MATEKF405SE) заявляло static.vsw/static.cameraSwitch
доступными БЕЗУСЛОВНО, документируя ambiguity firmware-варианта только как
caveat — то есть хинт срабатывал для КАЖДОЙ обнаруженной MATEKF405SE,
независимо от реально установленной прошивки.
Проверка (2026-07-23, gh api repos/iNavFlight/inav/...):
target.h(src/main/target/MATEKF405SE/target.h) —PINIO1_PIN/
PINIO2_PIN(PC6/PC7) объявлены ТОЛЬКО внутри#ifdef MATEKF405SE_PINIO;
без этого макроса те же пины — обычныйUART6TX/RX (#ifndef MATEKF405SE_PINIOв том же файле).docs/boards/MatekF405 Wing.mdиsrc/main/target/MATEKF405SE/README.mdв
самом репозитории INAV подтверждают:MATEKF045SE_PINIO— «alternate
target», а не основной.- Официальный датащит АКТУАЛЬНОГО харда, который продаёт Matek под именем
«F405-Wing V2» (https://www.mateksys.com/?portfolio=f405-wing-v2, сверено
2026-07-23): прошивка — «iNav 6.0 or later firmware (MATEKF405SE)»; PINIO/
VSW/camera-switch НЕ упомянуты нигде в спецификации/пинауте. Отдельного
INAV-таргета под «V2»/«V3» ревизию платы нет — PCB-ревизии Matek делит по
железу, не по прошивке,target.hодин на все. - MSP_BOARD_INFO живого борта отдаёт ОДИН и тот же
TARGET_BOARD_IDENTIFIER
("MF4S")/USBD_PRODUCT_STRING("Matek_F405SE") для ОБОИХ firmware-вариантов
— различить их удалённо нельзя.
Вывод: заявлять static.vsw доступным «по умолчанию» для MATEKF405SE —
соврать подавляющему большинству владельцев этой платы (те, кто не выбирал
осознанно альтернативную прошивку _PINIO при флеше). Решение — тот же
паттерн честности, что и § 5 (SPEEDYBEEF405V4): static.vsw/
static.cameraSwitch/static.userOutputs для MATEKF405SE не заданы
(правило vsw-available не срабатывает), физика — в caveats[]. ledPad/
sd остаются заявленными — WS2811_PIN/USE_SDCARD в target.h безусловны,
firmware-вариант их не затрагивает.
7. Что дальше (вне Фазы 2)
- Проверить
MSP2_INAV_OUTPUT_MAPPING_EXT2(0x210D) на реальном источнике
(например, собрав INAV из исходников и залогировав фактический ответ) —
тогда можно включить ярус 1 дляledPad/vswбез справочника. - Добавить недостающие популярные платы (Matek F411-й ряд, iFlight, Mamba) —
тот же процесс:target.h/config.cконкретного таргета → факты → запись
сsource/verified/confidence.