# Распиновка, измерения и управление тестами

## Проект

Keil-проект:

```text
F:\set\workspace\setcorp\set506\AD\AD_Keil_Project\MDK-ARM\IHM08M.uvprojx
```

Распиновка силовой части приведена к `X-NUCLEO-IHM08M1`. ADC-каналы и PWM-линии не выбраны случайно: они сверены с IHM08M1.

## Распиновка IHM08M1

Разъёмы указаны для платы `NUCLEO-G474RE`: ST morpho `CN7/CN10`, Arduino `CN5/CN8/CN9` и ST-LINK VCP. Для `PC1` и `PC0` на ST morpho в документации ST есть альтернативы через solder bridges, поэтому их нужно проверить на конкретной плате.

| Пин STM32 | Функция | Сигнал IHM08M1 | Разъём NUCLEO | Пин разъёма | Использование в проекте |
|---|---|---|---|---:|---|
| `PA0` | `ADC1_IN1` | `PhA` | `CN8` / `CN7` | `1` / `28` | ток фазы A |
| `PC1` | `ADC1_IN7` | `PhB` | `CN8` / `CN7` | `5` / `36` | ток фазы B; на `CN7-36` проверить вариант `PC1/PB9` |
| `PC0` | `ADC1_IN6` | `PhC` | `CN8` / `CN7` | `6` / `38` | ток фазы C; на `CN7-38` проверить вариант `PC0/PA15` |
| `PA1` | `ADC1_IN2` | `BUSV` | `CN8` / `CN7` | `2` / `30` | напряжение DC-звена |
| `PC2` | `ADC1_IN8` | `Temp. Sens.` | `CN7` | `35` | пин учтён, чтение температуры ещё не подключено |
| `PA8` | `TIM1_CH1` | `UH` | `CN9` / `CN10` | `8` / `23` | верхний ключ U |
| `PA7` | `TIM1_CH1N` | `UL` | `CN5` / `CN10` | `4` / `15` | нижний ключ U |
| `PA9` | `TIM1_CH2` | `VH` | `CN5` / `CN10` | `1` / `21` | верхний ключ V |
| `PB0` | `TIM1_CH2N` | `VL` | `CN8` / `CN7` | `4` / `34` | нижний ключ V |
| `PA10` | `TIM1_CH3` | `WH` | `CN9` / `CN10` | `3` / `33` | верхний ключ W |
| `PB1` | `TIM1_CH3N` | `WL` | `CN10` | `24` | нижний ключ W |
| `PA6` | `TIM1_BKIN` | `BKIN` | `CN5` / `CN10` | `5` / `13` | аппаратное аварийное отключение TIM1 |
| `PA2` | `USART2_TX` | ST-LINK VCP TX | `CN10` | `35` | Modbus RTU; также ST-LINK VCP при нужных solder bridges |
| `PA3` | `USART2_RX` | ST-LINK VCP RX | `CN10` | `37` | Modbus RTU; также ST-LINK VCP при нужных solder bridges |
| `PC13` | GPIO/EXTI | `START/STOP` | `CN7` | `23` | кнопка `B1`, переключает логирование |
| `PA5` | не используется | `PA5 - DAC` | `CN5` / `CN10` | `6` / `11` | конфликт с `LD2` убран |
| `PB3` | GPIO input | `Enc. B/H2` | `CN9` / `CN10` | `4` / `31` | SWO убран из `.ioc` |

Подробная сверка всех пинов находится в `AD_docs/PIN_USAGE_IHM08M1_COMPARE.md`.

## Измеряемые параметры

`AD_Board_ReadMeasurements()` читает ADC и заполняет `AD_Measurements_t`.

| Величина | Поле | Источник | Примечание |
|---|---|---|---|
| ток фазы A | `ia_A` | `PA0 / ADC1_IN1` | масштаб тока пока задаётся макросами |
| ток фазы B | `ib_A` | `PC1 / ADC1_IN7` | масштаб тока пока задаётся макросами |
| ток фазы C | `ic_A` | `PC0 / ADC1_IN6` | масштаб тока пока задаётся макросами |
| DC-звено | `vdc_V` | `PA1 / ADC1_IN2` | учтено измерение `10.0 В -> 0.618 В` на ADC |
| время | `timestamp_us` | `HAL_GetTick() * 1000` | шаг 1 мс в текущей реализации |

DC-звено усредняется по `AD_BOARD_ADC_VDC_AVG_SAMPLES=16` выборкам и фильтруется IIR-фильтром `AD_BOARD_ADC_VDC_FILTER_ALPHA=0.125`. Коэффициент делителя:

```text
AD_BOARD_ADC_VDC_BUS_V_PER_ADC_V = 12.1770
AD_BOARD_ADC_VDC_LOW_CAL_ADC_V = 0.618
AD_BOARD_ADC_VDC_LOW_CAL_BUS_V = 10.0
AD_BOARD_ADC_VDC_HIGH_CAL_BUS_V = 14.5
```

## Команда теста

```c
typedef struct
{
    uint8_t enable;
    uint8_t test_mode;
    uint8_t reset_faults;
    uint16_t pwm_polarity_flags;
    uint16_t pwm_timing_mode;
    uint16_t motor_control_type;
    uint16_t rotation_ramp_time_ms;
    float pwm_duty_limit;
    float rotation_frequency_Hz;
    float rotation_modulation;
    float current_limit_A;
    float voltage_limit_V;
    float undervoltage_limit_V;
    float speed_limit_rpm;
    float temperature_limit_C;
} AD_Command_t;
```

| Поле | Назначение |
|---|---|
| `enable` | `1` включает режим, `0` выключает |
| `test_mode` | один из `AD_PARAM_ID_MODE_*` |
| `reset_faults` | сброс защёлкнутых аварий |
| `pwm_polarity_flags` | bit0 инвертирует `UH/VH/WH`, bit1 инвертирует `UL/VL/WL` |
| `pwm_timing_mode` | `0` = up-counting PWM, `1` = center-aligned PWM |
| `motor_control_type` | `0` = AD/sine, `1` = BLDC/6-step |
| `rotation_ramp_time_ms` | время выхода `rotation_frequency_Hz`/`rotation_modulation` на уставку, по умолчанию `3000 ms` |
| `pwm_duty_limit` | лимит duty для PWM-тестов и измерительных импульсов |
| `rotation_frequency_Hz` | частота режима `AD_PARAM_ID_MODE_ROTATION_3HZ`, по умолчанию `3.0 Hz` |
| `rotation_modulation` | коэффициент модуляции режима `AD_PARAM_ID_MODE_ROTATION_3HZ`, по умолчанию `0.35` |
| `current_limit_A` | программный предел тока |
| `voltage_limit_V` | предел перенапряжения DC-звена |
| `undervoltage_limit_V` | предел недонапряжения, `0` отключает проверку |
| `speed_limit_rpm` | предел скорости |
| `temperature_limit_C` | предел температуры |

## Режимы

| Режим | Код | Назначение |
|---|---:|---|
| `AD_PARAM_ID_MODE_IDLE` | 0 | выключено |
| `AD_PARAM_ID_MODE_STATOR_RESISTANCE` | 1 | измерение `Rs_ohm` |
| `AD_PARAM_ID_MODE_NO_LOAD_MAGNETIZING` | 2 | измерение `Lm_H` |
| `AD_PARAM_ID_MODE_LOCKED_ROTOR_LEAKAGE` | 3 | измерение `Ll_H` и `Rr_ohm` |
| `AD_PARAM_ID_MODE_INERTIA_FRICTION` | 4 | измерение `J/B` при наличии `speed_rpm` |
| `AD_PARAM_ID_MODE_DATA_LOGGING` | 5 | только сбор данных |
| `AD_PARAM_ID_MODE_PWM_TEST_UH` | 6 | PWM на `PA8 / UH` |
| `AD_PARAM_ID_MODE_PWM_TEST_UL` | 7 | PWM на `PA7 / UL` |
| `AD_PARAM_ID_MODE_PWM_TEST_VH` | 8 | PWM на `PA9 / VH` |
| `AD_PARAM_ID_MODE_PWM_TEST_VL` | 9 | PWM на `PB0 / VL` |
| `AD_PARAM_ID_MODE_PWM_TEST_WH` | 10 | PWM на `PA10 / WH` |
| `AD_PARAM_ID_MODE_PWM_TEST_WL` | 11 | PWM на `PB1 / WL` |
| `AD_PARAM_ID_MODE_PWM_TEST_ALL` | 12 | все три плеча, duty фаз `0.5` |
| `AD_PARAM_ID_MODE_AUTO_IDENTIFICATION` | 13 | `Rs`, `Ll`, `Rr`, `Lm`, затем `J/B` |
| `AD_PARAM_ID_MODE_ROTATION_3HZ` | 14 | 6-step вращение с настраиваемой частотой и модуляцией |

## Управление из кода

```c
AD_Board_StartDataLogging();
AD_Board_StartParamTest(AD_PARAM_ID_MODE_STATOR_RESISTANCE);
AD_Board_StartParamTestWithDuty(AD_PARAM_ID_MODE_PWM_TEST_UH, 0.08f);
AD_Board_StartParamTestWithDuty(AD_PARAM_ID_MODE_AUTO_IDENTIFICATION, 0.08f);
AD_Board_StartParamTestWithDuty(AD_PARAM_ID_MODE_ROTATION_3HZ, 0.35f);
AD_Board_StopParamTest();
```

## Условия для реального PWM

Нужны все условия:

- сборка с `AD_PROJECT_POWER_TEST_ENABLE=1` или с двумя макросами `AD_PARAM_ID_ENABLE_POWER_TESTS=1` и `AD_INVERTER_ENABLE_OUTPUTS=1`;
- `AD_Command_t.enable = 1`;
- `current_limit_A > 0`;
- `voltage_limit_V > 0`;
- нет защёлкнутой аварии;
- `BKIN` не активен;
- для режима `AD_PARAM_ID_MODE_LOCKED_ROTOR_LEAKAGE` вызван `AD_ParamID_SetLockedRotorAllowed(1)`.

Если любое условие не выполнено, проект выключает TIM1 и уходит в `DATA_LOGGING`.
