Files
motor_params/AD_Keil_Project/AD_docs/MODBUS_REGISTERS.md

23 KiB
Raw Blame History

Modbus RTU регистры

Порт

Modbus RTU slave запущен на ST-LINK VCP:

Параметр Значение
UART USART2
TX PA2 / USART2_TX
RX PA3 / USART2_RX
Скорость 512000
Формат 8N1
Slave address 1

Приём USART2 сделан через USART2_IRQHandler() и HAL_UARTEx_ReceiveToIdle_IT(). Готовый кадр фиксируется в HAL_UARTEx_RxEventCallback() по событию IDLE на линии UART, после этого основной цикл проверяет CRC и отправляет ответ.

Настройки задаются в Core/Inc/ad_project_config.h:

AD_MODBUS_ENABLE
AD_MODBUS_SLAVE_ADDRESS
AD_MODBUS_UART_BAUDRATE

Поддержанные функции:

Функция Назначение
0x03 чтение holding registers
0x06 запись одного holding register
0x10 запись нескольких holding registers

Структура holding-регистров в прошивке

Текущие значения holding-регистров зеркалируются в структуру:

MB_REGS->holding.H000_device_id
MB_REGS->holding.H035_input_volt_0p1_v
MB_REGS->holding.H048_param_valid_mask_lo

Для доступа по номеру регистра можно использовать сырой массив:

MB_REGS->holding_raw[35]

Та же карта копируется в debug-view:

g_ad_debug.modbus_regs.holding.H035_input_volt_0p1_v

Значения в структуре уже в формате Modbus-регистров uint16_t, то есть с теми же масштабами, что указаны в таблицах ниже. Если карту нужно обновить вручную из другого модуля, вызови AD_Modbus_RefreshRegisters().

Быстрая проверка связи

После прошивки сначала проверь чтение первых двух holding-регистров:

Slave ID: 1
Function: 03 Read Holding Registers
Address: 0
Quantity: 2
Ожидаемый ответ: 0xAD01, 0x0008

Если программа на ПК работает в формате 4xxxx, используй адрес 40001 вместо 0. В прошивке поддержаны оба варианта: 0x0000 / 0 и 40001 читают один и тот же регистр device id.

Если ответа нет, проверь:

Что смотреть Норма
COM-порт ST-LINK VCP выбран правильный порт платы
Скорость 512000
Формат 8N1, без flow control
Slave ID 1
Функция 03, не 04
g_ad_debug.modbus.initialized 1
g_ad_debug.modbus.status_flags есть бит AD_MODBUS_STATUS_UART_RX_ACTIVE
g_ad_debug.modbus.rx_frames растёт при правильных запросах
g_ad_debug.modbus.crc_errors не должен расти при верной скорости/CRC
g_ad_debug.modbus.uart_errors не должен расти; если растёт, смотри скорость, порт, шум, overrun

Расшифровка g_ad_debug.modbus.status_flags:

Бит Маска Флаг Значение
0 0x00000001 AD_MODBUS_STATUS_INITIALIZED Modbus инициализирован
1 0x00000002 AD_MODBUS_STATUS_FRAME_READY принят кадр UART, основной цикл ещё не обработал его
2 0x00000004 AD_MODBUS_STATUS_LAST_FRAME_OK последний обработанный кадр прошёл CRC и был принят
3 0x00000008 AD_MODBUS_STATUS_LAST_FRAME_ERROR в последнем кадре была ошибка CRC/UART/overflow
4 0x00000010 AD_MODBUS_STATUS_UART_RX_ACTIVE приём UART активен, HAL_UARTEx_ReceiveToIdle_IT() запущен
5 0x00000020 AD_MODBUS_STATUS_RX_OVERFLOW переполнение RX или новый кадр пришёл до обработки предыдущего

Нормальное состояние после старта без запросов: есть INITIALIZED и UART_RX_ACTIVE. После корректного запроса дополнительно появляется LAST_FRAME_OK, а счётчик g_ad_debug.modbus.rx_frames растёт.

Управление

Адрес hex / dec Поле структуры Доступ Масштаб Назначение
0x0000 / 0 H000_device_id R 1 device id 0xAD01
0x0001 / 1 H001_protocol_version R 1 версия карты регистров
0x0002 / 2 H002_control_enable R/W 1 enable: 0 стоп, 1 разрешить команду
0x0003 / 3 H003_control_mode R/W 1 режим AD_PARAM_ID_MODE_*
0x0004 / 4 H004_control_reset_faults W 1 квитирование ошибок: записать 1
0x0005 / 5 H005_control_stop W 1 стоп: записать 1
0x0006 / 6 H006_control_locked_rotor_allowed R/W 1 разрешение locked-rotor теста
0x0007 / 7 H007_control_pwm_duty_0p0001 R/W 0.0001 лимит duty PWM
0x0008 / 8 H008_limit_current_0p01_a R/W 0.01 А предел тока
0x0009 / 9 H009_limit_overvoltage_0p1_v R/W 0.1 В предел перенапряжения DC-звена
0x000A / 10 H010_limit_undervoltage_0p1_v R/W 0.1 В предел недонапряжения, 0 отключает проверку
0x000B / 11 H011_limit_speed_rpm R/W 1 об/мин предел скорости
0x000C / 12 H012_limit_temperature_0p1_c R/W 0.1 град C предел температуры
0x000D / 13 H013_control_rotation_freq_0p1_hz R/W 0.1 Hz частота режима ROTATION_3HZ, firmware clamp 0.1..200.0 Hz
0x000E / 14 H014_control_rotation_mod_0p0001 R/W 0.0001 коэффициент модуляции режима ROTATION_3HZ
0x000F / 15 H015_control_pwm_polarity_flags R/W bitmask полярность PWM: bit0=UH/VH/WH inverted, bit1=UL/VL/WL inverted

Пример: duty 0.08 записать как 800 в 0x0007 / 7; для режима ROTATION_3HZ частоту 3.00 Hz записать как 30, 20.0 Hz как 200, 50.0 Hz как 500 в 0x000D / 13, модуляцию 0.35 как 3500 в 0x000E / 14. Полярность PWM: 0 - штатно, 1 - инвертировать UH/VH/WH, 2 - инвертировать UL/VL/WL, 3 - инвертировать все.

Статусы и ошибки

Адрес hex / dec Поле структуры Доступ Назначение
0x0010 / 16 H016_status_mode R фактический режим идентификации
0x0011 / 17 H017_status_flags_lo R AD_PARAM_ID_STATUS_*, младшее слово
0x0012 / 18 H018_status_flags_hi R AD_PARAM_ID_STATUS_*, старшее слово
0x0013 / 19 H019_fault_flags_lo R AD_PARAM_ID_FAULT_*, младшее слово
0x0014 / 20 H020_fault_flags_hi R AD_PARAM_ID_FAULT_*, старшее слово
0x0015 / 21 H021_power_stage_allowed R AD_ParamID_IsPowerStageAllowed()
0x0016 / 22 H022_test_running R тест активен
0x0017 / 23 H023_inverter_pwm_running R PWM TIM1 запущен
0x0018 / 24 H024_inverter_service_output R сервисный выход UH..WL/ALL
0x0019 / 25 H025_inverter_id_stage R стадия алгоритма измерения
0x001A / 26 H026_control_pwm_timing_mode R/W 0=up, 1=center
0x001B / 27 H027_control_motor_control_type R/W 0=AD/sine, 1=BLDC/6-step
0x001E / 30 H030_control_rotation_ramp_time_ms R/W ramp to rotation_frequency_Hz/rotation_modulation, 0 = default 3000 ms
0x001F / 31 H031_control_reset_phase_current_peaks W сброс накопленных пиков фазных токов: записать 1

Флаги статуса и ошибок оформлены enum в ad_parameter_identification.h: AD_ParamID_StatusFlag_t, AD_ParamID_FaultFlag_t, AD_MeasurementStatusFlag_t, AD_MotorParamValidFlag_t.

Расшифровка status_flags_lo (0x0011 / 17):

Бит Маска Флаг Значение
0 0x0001 AD_PARAM_ID_STATUS_ACTIVE режим активен
1 0x0002 AD_PARAM_ID_STATUS_POWER_TEST_BLOCKED силовой тест заблокирован
2 0x0004 AD_PARAM_ID_STATUS_POWER_STAGE_ARMED силовая часть программно разрешена
3 0x0008 AD_PARAM_ID_STATUS_FAULT_LATCHED авария защёлкнута
4 0x0010 AD_PARAM_ID_STATUS_TIMEOUT истекло время теста
5 0x0020 AD_PARAM_ID_STATUS_LOCKED_ROTOR_BLOCKED отдельный locked-rotor режим не разрешён
6 0x0040 AD_PARAM_ID_STATUS_SAFETY_LIMITS_UNKNOWN не заданы пределы тока или напряжения
7 0x0080 AD_PARAM_ID_STATUS_DATA_VALID есть актуальные измерения/данные
8 0x0100 AD_PARAM_ID_STATUS_COMPLETE алгоритм завершён
9 0x0200 AD_PARAM_ID_STATUS_PARTIAL_COMPLETE результат частичный, смотри valid_mask
10 0x0400 AD_PARAM_ID_STATUS_STEP_FAILED один из этапов не получил достаточных условий
11 0x0800 AD_PARAM_ID_STATUS_LOCKED_ROTOR_SKIPPED locked-rotor этап автоидентификации пропущен

fault_flags в прошивке имеет тип uint32_t и отдается двумя holding-регистрами:

Регистр Поле структуры Биты
0x0013 / 19 H019_fault_flags_lo биты 0..15
0x0014 / 20 H020_fault_flags_hi биты 16..31

Расшифровка fault_flags_lo (0x0013 / 19):

Бит Маска Флаг Значение
0 0x0001 AD_PARAM_ID_FAULT_OVERCURRENT превышен ток
1 0x0002 AD_PARAM_ID_FAULT_OVERVOLTAGE превышено напряжение DC-звена
2 0x0004 AD_PARAM_ID_FAULT_UNDERVOLTAGE напряжение DC-звена ниже лимита
3 0x0008 AD_PARAM_ID_FAULT_OVERTEMPERATURE превышена температура
4 0x0010 AD_PARAM_ID_FAULT_DRIVER ошибка драйвера силового каскада
5 0x0020 AD_PARAM_ID_FAULT_EMERGENCY_STOP аварийный останов
6 0x0040 AD_PARAM_ID_FAULT_TIMEOUT таймаут теста
7 0x0080 AD_PARAM_ID_FAULT_NULL_INPUT нет входных измерений
8..15 0xFF00 reserved сейчас не используются

fault_flags_hi (0x0014 / 20) сейчас зарезервирован и в норме равен 0. Если позже появятся флаги с битами 16..31, они будут отображаться здесь.

Измерения

Адрес hex / dec Поле структуры Доступ Масштаб Назначение
0x0020 / 32 H032_meas_ia_0p001_a R 0.001 А ток фазы A, int16
0x0021 / 33 H033_meas_ib_0p001_a R 0.001 А ток фазы B, int16
0x0022 / 34 H034_meas_ic_0p001_a R 0.001 А ток фазы C, int16
0x0023 / 35 H035_input_volt_0p1_v R 0.1 В DC-звено
0x0024 / 36 H036_meas_temp_0p1_c R 0.1 град C STM32 internal temperature
0x0025 / 37 H037_meas_status_lo R 1 AD_MEAS_STATUS_*, младшее слово
0x0026 / 38 H038_meas_status_hi R 1 AD_MEAS_STATUS_*, старшее слово
0x0027 / 39 H039_meas_speed_rpm R 1 rpm speed_rpm, int16
0x0028 / 40 H040_meas_ia_rms_0p001_A R 0.001 A phase A RMS current
0x0029 / 41 H041_meas_ib_rms_0p001_B R 0.001 A phase B RMS current
0x002A / 42 H042_meas_ic_rms_0p001_C R 0.001 A phase C RMS current
0x002B / 43 H043_meas_torque_0p001_nm R 0.001 Nm estimated torque, int16
0x002C / 44 H044_meas_ia_peak_0p001_a R 0.001 A phase A peak absolute current
0x002D / 45 H045_meas_ib_peak_0p001_a R 0.001 A phase B peak absolute current
0x002E / 46 H046_meas_ic_peak_0p001_a R 0.001 A phase C peak absolute current
0x002F / 47 H047_meas_slip_0p01_percent R 0.01 % induction motor slip, int16: (n_sync - speed_rpm) / n_sync * 100

Токи передаются как 16-битное значение в дополнительном коде. Например -1200 означает -1.2 А.

Результаты идентификации

Адрес hex / dec Поле структуры Доступ Масштаб Назначение
0x0030 / 48 H048_param_valid_mask_lo R 1 valid_mask, младшее слово
0x0031 / 49 H049_param_valid_mask_hi R 1 valid_mask, старшее слово
0x0032 / 50 H050_param_rs_mohm R 1 мОм Rs_ohm
0x0033 / 51 H051_param_ls_uh_lo R 1 мкГн Ls_H, младшее слово uint32
0x0034 / 52 H052_param_ls_uh_hi R 1 мкГн Ls_H, старшее слово uint32
0x0035 / 53 H053_param_ll_uh_lo R 1 мкГн Ll_H, младшее слово uint32
0x0036 / 54 H054_param_ll_uh_hi R 1 мкГн Ll_H, старшее слово uint32
0x0037 / 55 H055_param_rr_mohm R 1 мОм Rr_ohm
0x0038 / 56 H056_param_lr_uh_lo R 1 мкГн Lr_H, младшее слово uint32
0x0039 / 57 H057_param_lr_uh_hi R 1 мкГн Lr_H, старшее слово uint32
0x003A / 58 H058_param_lm_uh_lo R 1 мкГн Lm_H, младшее слово uint32
0x003B / 59 H059_param_lm_uh_hi R 1 мкГн Lm_H, старшее слово uint32
0x003C / 60 H060_param_j_nkgm2_lo R 1 nkg*m2 J_kg_m2, младшее слово uint32
0x003D / 61 H061_param_j_nkgm2_hi R 1 nkg*m2 J_kg_m2, старшее слово uint32
0x003E / 62 H062_param_b_nnms_lo R 1 nNm*s B_Nm_s, младшее слово uint32
0x003F / 63 H063_param_b_nnms_hi R 1 nNm*s B_Nm_s, старшее слово uint32
0x0040 / 64 H064_param_pole_pairs R/W 1 pair motor pole pairs for synchronous speed, slip, and torque calculations
0x0041 / 65 H065_param_phase_shunt_mohm R/W 1 мОм сопротивление фазных шунтов; default 0.1 Ом = 100

Перед использованием результата обязательно проверить valid_mask.

Запуск теста через Modbus

Для запуска используй holding-регистры управления через функцию 0x06 Write Single Register или 0x10 Write Multiple Registers. Проверку состояния делай функцией 0x03 Read Holding Registers. Если мастер работает в формате 4xxxx, прибавляй базу 40001: например 0x0002 / 2 это 40003, а 0x0007 / 7 это 40008.

Пиши enable (0x0002 / 2) последним. До этого нужно задать duty, лимиты и режим, иначе можно запустить предыдущий режим со старыми настройками.

Базовая последовательность:

1. Проверить связь:
   read 0x0000 / 0, quantity 2
   ожидаемо: 0xAD01, 0x0008

2. Остановить предыдущий тест:
   write 0x0005 / 5 = 1

3. Сбросить latched fault, если был:
   write 0x0004 / 4 = 1

4. Задать ограничения и duty:
   write 0x0007 / 7  = 800    ; duty 0.08
   write 0x0008 / 8  = 1000   ; ток 10.00 А
   write 0x0009 / 9  = 600    ; перенапряжение 60.0 В
   write 0x000A / 10 = 0      ; недонапряжение отключено
   write 0x000B / 11 = 1000   ; скорость 1000 rpm
   write 0x000C / 12 = 850    ; температура 85.0 град C
   write 0x000D / 13 = 30     ; ROTATION_3HZ: частота 3.00 Hz
   write 0x000E / 14 = 3500   ; ROTATION_3HZ: модуляция 0.35
   write 0x000F / 15 = 1      ; PWM polarity flags
   write 0x001A / 26 = 1      ; PWM timing: 0=up, 1=center
   write 0x001B / 27 = 0      ; motor control: 0=AD/sine, 1=BLDC/6-step
   write 0x001E / 30 = 3000   ; rotation ramp time, ms
   write 0x0041 / 65 = 100    ; phase shunts 0.1 Ohm

5. Выбрать режим теста:
   write 0x0003 / 3 = <mode>

6. Запустить:
   write 0x0002 / 2 = 1

Ту же подготовку можно отправить одним 0x10 Write Multiple Registers, если пишешь непрерывный диапазон 0x0007..0x000F для duty/лимитов/параметров вращения/полярности. 0x001A..0x001B для up/center и AD/BLDC пишутся отдельным диапазоном, 0x001E для времени рампы - отдельным регистром. Режим и enable удобнее оставить отдельными командами: сначала 0x0003 / 3, затем 0x0002 / 2.

0x10 Write Multiple Registers validates the whole writable range first, stages all values, then applies the command once. If any value is invalid, none of the packet values are committed.

Режимы mode:

Значение Режим
0 IDLE, останов
1 STATOR_RESISTANCE
2 NO_LOAD_MAGNETIZING
3 LOCKED_ROTOR_LEAKAGE
4 INERTIA_FRICTION
5 DATA_LOGGING
6 PWM_TEST_UH
7 PWM_TEST_UL
8 PWM_TEST_VH
9 PWM_TEST_VL
10 PWM_TEST_WH
11 PWM_TEST_WL
12 PWM_TEST_ALL
13 AUTO_IDENTIFICATION
14 ROTATION_3HZ

Режимы 1, 2, 3, 4, 6..14 требуют силовой части. DATA_LOGGING (5) можно использовать как безопасный режим наблюдения без включения PWM.

Пример запуска PWM-теста верхнего ключа фазы U (UH) с duty 0.08:

write 0x0005 / 5 = 1
write 0x0004 / 4 = 1
write 0x0007 / 7 = 800
write 0x0003 / 3 = 6
write 0x0002 / 2 = 1

Пример запуска автоидентификации:

write 0x0005 / 5 = 1
write 0x0004 / 4 = 1
write 0x0007 / 7 = 800
write 0x0003 / 3 = 13
write 0x0002 / 2 = 1

Для locked-rotor теста дополнительно нужно разрешение:

write 0x0005 / 5 = 1
write 0x0004 / 4 = 1
write 0x0006 / 6 = 1
write 0x0007 / 7 = 800
write 0x0003 / 3 = 3
write 0x0002 / 2 = 1

Контроль после запуска:

read 0x0010 / 16, quantity 10

Смотри основные регистры:

Адрес hex / dec Что должно быть
0x0010 / 16 фактический режим, должен совпасть с выбранным mode
0x0011 / 17 младшее слово AD_PARAM_ID_STATUS_*
0x0013 / 19 младшее слово AD_PARAM_ID_FAULT_*, норма 0
0x0015 / 21 1, если силовой каскад разрешён
0x0016 / 22 1, если тест активен
0x0017 / 23 1, если PWM TIM1 реально запущен
0x0019 / 25 стадия алгоритма измерения

Если читаешь через структуру в отладчике, это те же значения:

MB_REGS->holding.H016_status_mode
MB_REGS->holding.H017_status_flags_lo
MB_REGS->holding.H019_fault_flags_lo
MB_REGS->holding.H022_test_running

Полезные биты статуса 0x0011:

Бит Маска Значение
0 0x0001 тест активен
1 0x0002 силовой тест заблокирован, прошивка ушла в DATA_LOGGING
2 0x0004 power stage armed
3 0x0008 ошибка защёлкнута, нужен сброс через 0x0004 / 4
4 0x0010 timeout
5 0x0020 locked-rotor тест заблокирован
6 0x0040 не заданы безопасные лимиты
8 0x0100 тест завершён

Расшифровка fault_flags_lo и fault_flags_hi приведена выше в разделе “Статусы и ошибки”.

При любой ошибке сначала останови тест, затем квитируй fault:

write 0x0005 / 5 = 1
write 0x0004 / 4 = 1

Останов:

write 0x0005 / 5 = 1

Или:

write 0x0002 / 2 = 0

Для реального PWM нужен build-макрос AD_PROJECT_POWER_TEST_ENABLE=1. Если он равен 0, команды силовых тестов не включат ключи: прошивка выставит AD_PARAM_ID_STATUS_POWER_TEST_BLOCKED и перейдёт в безопасный режим DATA_LOGGING.

Быстрые сценарии

Квитировать ошибку:

write 0x0004 / 4 = 1

Запустить PWM-тест UH с duty 0.08:

write 0x0007 / 7 = 800
write 0x0003 / 3 = 6
write 0x0002 / 2 = 1

Запустить автоидентификацию текущего уровня:

write 0x0007 / 7 = 800
write 0x0003 / 3 = 13
write 0x0002 / 2 = 1

Остановить:

write 0x0005 / 5 = 1

Для физического PWM всё равно нужен build-макрос AD_PROJECT_POWER_TEST_ENABLE=1, иначе команда будет заблокирована защитой проекта.