# Структуры данных

## Основные файлы

| Файл | Назначение |
|---|---|
| `Core/Inc/ad_parameter_identification.h` | режимы, команды, измерения, параметры двигателя |
| `Core/Src/ad_parameter_identification.c` | логика запуска, блокировки, fault, valid-mask |
| `Core/Inc/ad_inverter.h` | команда и состояние TIM1/inverter слоя |
| `Core/Src/ad_inverter.c` | PWM-тесты и начальные алгоритмы `Rs/Ls/Ll` |
| `Core/Inc/ad_board.h` | чтение ADC и удобные функции запуска |
| `Core/Src/ad_board.c` | распиновка ADC IHM08M1 и board loop |
| `Core/Inc/ad_debug.h` | `g_ad_debug` для Keil Watch |
| `Core/Inc/simulink_interface.h` | входная/выходная шина и пакет телеметрии |

## Измерения

```c
typedef struct
{
    float ia_A;
    float ib_A;
    float ic_A;
    float ia_rms_A;
    float ib_rms_A;
    float ic_rms_A;
    float vdc_V;
    float va_V;
    float vb_V;
    float vc_V;
    float speed_rpm;
    float torque_Nm;
    float temperature_C;
    uint32_t timestamp_us;
    uint32_t status_flags;
    float slip_percent;
} AD_Measurements_t;
```

| Поле | Источник |
|---|---|
| `ia_A` | `PA0 / ADC1_IN1 / PhA` |
| `ib_A` | `PC1 / ADC1_IN7 / PhB` |
| `ic_A` | `PC0 / ADC1_IN6 / PhC` |
| `ia_rms_A` | IIR RMS phase A current |
| `ib_rms_A` | IIR RMS phase B current |
| `ic_rms_A` | IIR RMS phase C current |
| `va_V`, `vb_V`, `vc_V` | estimated phase voltages from TIM1 duty and DC-link voltage |
| `torque_Nm` | estimated torque, Nm; uses valid `J/B` with speed, otherwise electrical power fallback; if no speed sensor is present, the fallback uses the inverter electrical frequency and `pole_pairs` |
| `slip_percent` | induction-motor slip in percent: `(n_sync - speed_rpm) / n_sync * 100`, where `n_sync = 60 * electrical_frequency_Hz / pole_pairs` |
| `temperature_C` | STM32 internal temperature sensor, ADC1 channel 16 |
| `vdc_V` | `PA1 / ADC1_IN2 / BUSV`, усреднение и IIR-фильтр |
| `timestamp_us` | `HAL_GetTick() * 1000` |
| `status_flags` | флаги измерений и защит |

## Параметры двигателя

```c
typedef struct
{
    float Rs_ohm;
    float Rr_ohm;
    float Ls_H;
    float Lr_H;
    float Lm_H;
    float Ll_H;
    float J_kg_m2;
    float B_Nm_s;
    float pole_pairs;
    float nominal_voltage_V;
    float nominal_current_A;
    float nominal_frequency_Hz;
    float nominal_power_W;
    float nominal_speed_rpm;
    uint32_t valid_mask;
} AD_MotorParameters_t;
```

`valid_mask` обязательно проверять перед использованием параметра:

| Бит | Значение |
|---|---|
| `AD_MOTOR_PARAM_VALID_RS` | действителен `Rs_ohm` |
| `AD_MOTOR_PARAM_VALID_RR` | действителен `Rr_ohm` |
| `AD_MOTOR_PARAM_VALID_LS` | действителен `Ls_H` |
| `AD_MOTOR_PARAM_VALID_LR` | действителен `Lr_H` |
| `AD_MOTOR_PARAM_VALID_LM` | действителен `Lm_H` |
| `AD_MOTOR_PARAM_VALID_LL` | действителен `Ll_H` |
| `AD_MOTOR_PARAM_VALID_J` | действителен `J_kg_m2` |
| `AD_MOTOR_PARAM_VALID_B` | действителен `B_Nm_s` |

Текущий алгоритм реально выставляет только `RS`, `LS` и `LL`.

## Команда

```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;
```

`pwm_polarity_flags` управляет полярностью TIM1 PWM: 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. `pwm_duty_limit` используется для одиночных PWM-тестов и измерительных импульсов. `rotation_frequency_Hz`, `rotation_modulation` и `rotation_ramp_time_ms` управляют режимом `AD_PARAM_ID_MODE_ROTATION_3HZ`; `0` означает значения по умолчанию `3.0 Hz`, `0.35` и `3000 ms`, частота зажимается в диапазон `0.1..200.0 Hz`.

## Состояние инвертора

```c
typedef struct
{
    uint8_t initialized;
    uint8_t pwm_running;
    uint8_t outputs_allowed_by_build;
    float duty_a;
    float duty_b;
    float duty_c;
    float electrical_frequency_Hz;
    float electrical_angle_rad;
    float requested_test_duty;
    float applied_test_duty;
    uint16_t pwm_polarity_flags;
    uint16_t pwm_timing_mode;
    uint8_t service_output;
    uint8_t service_pwm_running;
    uint8_t id_stage;
} AD_InverterState_t;
```

| Поле | Смысл |
|---|---|
| `initialized` | выполнен `AD_Inverter_Init()` |
| `pwm_running` | TIM1 PWM запущен |
| `outputs_allowed_by_build` | сборка разрешает физические выходы |
| `duty_a/b/c` | последние duty фаз или выбранного тестового канала |
| `electrical_frequency_Hz` | current inverter electrical frequency for rotating PWM and torque estimation |
| `electrical_angle_rad` | current inverter electrical angle for rotating PWM |
| `service_output` | выбранный канал теста `UH..WL` или `ALL` |
| `service_pwm_running` | активен сервисный PWM-тест |
| `id_stage` | стадия измерительного алгоритма |

## Состояние идентификации

| Флаг | Смысл |
|---|---|
| `AD_PARAM_ID_STATUS_ACTIVE` | режим активен |
| `AD_PARAM_ID_STATUS_POWER_TEST_BLOCKED` | силовой тест заблокирован |
| `AD_PARAM_ID_STATUS_POWER_STAGE_ARMED` | силовая часть программно разрешена |
| `AD_PARAM_ID_STATUS_FAULT_LATCHED` | авария защёлкнута |
| `AD_PARAM_ID_STATUS_TIMEOUT` | истекло время теста |
| `AD_PARAM_ID_STATUS_LOCKED_ROTOR_BLOCKED` | locked-rotor режим не разрешён |
| `AD_PARAM_ID_STATUS_SAFETY_LIMITS_UNKNOWN` | не заданы пределы тока или напряжения |
| `AD_PARAM_ID_STATUS_DATA_VALID` | есть действительные данные |
| `AD_PARAM_ID_STATUS_COMPLETE` | измерительный алгоритм завершён |
| `AD_PARAM_ID_STATUS_PARTIAL_COMPLETE` | измерены не все параметры, но часть результата действительна |
| `AD_PARAM_ID_STATUS_STEP_FAILED` | один из этапов измерения не получил достаточного сигнала/условий |
| `AD_PARAM_ID_STATUS_LOCKED_ROTOR_SKIPPED` | этап locked-rotor пропущен, потому что он не разрешён |

## Сводная отладка

```c
volatile AD_DebugView_t g_ad_debug;
```

`g_ad_debug` обновляется в `AD_Project_Loop()` и содержит копии `project`, `inverter`, `adc`, `measurements`, `motor_parameters`, `command`, `param_id_status`, `param_id_faults`, `param_id_mode`, `power_stage_allowed`, `test_running`, `tick_ms`.
