# Карта слоя драйвера двигателя

## Что сейчас реализовано

Проект содержит рабочий слой TIM1 для IHM08M1:

- `PA8 / TIM1_CH1 / UH`;
- `PA7 / TIM1_CH1N / UL`;
- `PA9 / TIM1_CH2 / VH`;
- `PB0 / TIM1_CH2N / VL`;
- `PA10 / TIM1_CH3 / WH`;
- `PB1 / TIM1_CH3N / WL`;
- `PA6 / TIM1_BKIN / BKIN`.

TIM1 PWM timing: center-aligned mode, `ARR=32767`, `PSC=0`; carrier remains about 2.6 kHz.

`MX_TIM1_Init()` настраивает PWM1 на трёх каналах, комплементарные выходы, dead-time `AD_TIM1_DEADTIME_TICKS=100` и Break input.

## Безопасность включения

По умолчанию физические выходы запрещены:

```text
AD_PROJECT_POWER_TEST_ENABLE=0
```

Для стендового включения можно задать:

```text
AD_PROJECT_POWER_TEST_ENABLE=1
```

Это включает внутренние макросы:

```text
AD_PARAM_ID_ENABLE_POWER_TESTS=1
AD_INVERTER_ENABLE_OUTPUTS=1
```

При `Stop`, fault, блокировке силового теста или `enable=0` вызывается `AD_ParamID_HardwareDisable()`, который в реализации `ad_inverter.c` гасит TIM1 через `AD_Inverter_Disable()`.

## API инвертора

| Функция | Назначение |
|---|---|
| `AD_Inverter_Init()` | инициализация состояния inverter слоя |
| `AD_Inverter_Disable()` | останов всех PWM и сброс duty |
| `AD_Inverter_SetDuty(a,b,c)` | запись duty трёх фаз |
| `AD_Inverter_Enable()` | запуск всех трёх каналов и комплементарных выходов |
| `AD_Inverter_StartPwmOutput(output,duty)` | сервисный PWM на один вход драйвера или на все плечи |
| `AD_Inverter_ApplyCommand()` | применить трёхфазную команду |

## PWM-тест каналов

Сервисные режимы:

| Режим | Канал |
|---|---|
| `AD_PARAM_ID_MODE_PWM_TEST_UH` | `PA8 / UH` |
| `AD_PARAM_ID_MODE_PWM_TEST_UL` | `PA7 / UL` |
| `AD_PARAM_ID_MODE_PWM_TEST_VH` | `PA9 / VH` |
| `AD_PARAM_ID_MODE_PWM_TEST_VL` | `PB0 / VL` |
| `AD_PARAM_ID_MODE_PWM_TEST_WH` | `PA10 / WH` |
| `AD_PARAM_ID_MODE_PWM_TEST_WL` | `PB1 / WL` |
| `AD_PARAM_ID_MODE_PWM_TEST_ALL` | все три плеча, duty фаз `0.5` |

Пример:

```c
AD_Board_StartParamTestWithDuty(AD_PARAM_ID_MODE_PWM_TEST_UH, 0.08f);
```

Одиночный PWM-тест удерживает уже запущенный канал и не делает `Stop/Start` на каждом slow-step.

## Алгоритм измерения

Сейчас в `AD_ParamID_HardwareStep()` реализованы:

| Режим | Результат |
|---|---|
| `AD_PARAM_ID_MODE_STATOR_RESISTANCE` | измеряет `Rs_ohm`, ставит `AD_MOTOR_PARAM_VALID_RS` |
| `AD_PARAM_ID_MODE_LOCKED_ROTOR_LEAKAGE` | измеряет `Ll_H` и `Rr_ohm`; после `Lm_H` пересчитывает `Ls_H/Lr_H` |
| `AD_PARAM_ID_MODE_NO_LOAD_MAGNETIZING` | измеряет `Lm_H` вращающимся полем без нагрузки |
| `AD_PARAM_ID_MODE_INERTIA_FRICTION` | измеряет `J_kg_m2` и `B_Nm_s` по разгону/выбегу при наличии `speed_rpm` |
| `AD_PARAM_ID_MODE_AUTO_IDENTIFICATION` | последовательно выполняет `Rs`, `Ll`, `Rr`, `Lm`, затем `J/B` |
| `AD_PARAM_ID_MODE_ROTATION_3HZ` | выдаёт 6-step вращение до 3 Гц для проверки работы двигателя |

Для расчёта `J` и `B` нужен реальный сигнал скорости в `AD_Measurements_t.speed_rpm`; при нулевой скорости механические параметры не помечаются действительными.

## Что ещё нужно проверить на железе

- полярность `UH/UL/VH/VL/WH/WL` на входе реального драйвера;
- что `BKIN` реально выключает TIM1;
- dead-time на затворах или входах драйвера;
- масштаб и ноль токовых датчиков;
- предел тока и напряжения перед первым запуском с двигателем;
- наличие отдельного `EN_GATE`, если он есть на конкретной плате.
