запущен проект motor identification c терминалкой
This commit is contained in:
82
docs/BUILD_AND_RUN.md
Normal file
82
docs/BUILD_AND_RUN.md
Normal file
@@ -0,0 +1,82 @@
|
||||
# Build and Run
|
||||
|
||||
## What was found
|
||||
|
||||
No STM32G474CEU6 Keil uVision project was found in the current `AD` workspace. The available files are:
|
||||
|
||||
- Simulink models under `Inu_im_1wnd_3lvl/`.
|
||||
- S-function and C2000/TMS320 motor-control reference code under `Inu_im_1wnd_3lvl/Inu/`.
|
||||
- New portable STM32-safe wrapper files under `Core/Inc` and `Core/Src`.
|
||||
|
||||
A sibling candidate project exists outside the writable root:
|
||||
|
||||
- `F:\set\workspace\setcorp\set506\git_project\stm32g474\stm32g474_IHM08M\IHM08M\MDK-ARM\IHM08M.uvprojx`
|
||||
- Target: `STM32G474RETx`, board `NUCLEO-G474RE`, package `LQFP64`.
|
||||
- Requested target: `STM32G474CEU6`.
|
||||
|
||||
Because of the target/package mismatch and write permissions, this project was analyzed but not modified.
|
||||
|
||||
## New files to add to Keil
|
||||
|
||||
Add these files to the STM32G474CEU6 Keil project once the real `.uvprojx` is available:
|
||||
|
||||
- `Core/Inc/ad_parameter_identification.h`
|
||||
- `Core/Src/ad_parameter_identification.c`
|
||||
- `Core/Inc/simulink_interface.h`
|
||||
- `Core/Src/simulink_interface.c`
|
||||
|
||||
Add `Core/Inc` to the include path.
|
||||
|
||||
## Suggested call points
|
||||
|
||||
After CubeMX init:
|
||||
|
||||
```c
|
||||
SimulinkInterface_Init();
|
||||
```
|
||||
|
||||
In the fast control loop after measurements are updated:
|
||||
|
||||
```c
|
||||
SimulinkInterface_SetMeasurements(&measurements);
|
||||
SimulinkInterface_StepFast();
|
||||
```
|
||||
|
||||
In a slow loop or diagnostic timer:
|
||||
|
||||
```c
|
||||
SimulinkInterface_StepSlow();
|
||||
```
|
||||
|
||||
## Safety default
|
||||
|
||||
`AD_PARAM_ID_ENABLE_POWER_TESTS` defaults to `0`. With this default, the code does not request PWM, driver enable, or any power-stage action.
|
||||
|
||||
To allow hardware tests later, define the macro in the compiler settings or before including the header:
|
||||
|
||||
```c
|
||||
#define AD_PARAM_ID_ENABLE_POWER_TESTS 1
|
||||
```
|
||||
|
||||
Do this only after pinout, driver enable, break/fault inputs, current/voltage scaling, and emergency stop are verified on hardware.
|
||||
|
||||
## Keil build steps
|
||||
|
||||
1. Open the real STM32G474CEU6 `.uvprojx`.
|
||||
2. Add `Core/Inc` to C/C++ include paths.
|
||||
3. Add the two new `.c` files to a user group.
|
||||
4. Build.
|
||||
5. Resolve any project-specific include path or C dialect settings.
|
||||
6. Keep generated Simulink files in a separate group and do not edit them directly.
|
||||
|
||||
For the sibling `IHM08M.uvprojx` candidate, first confirm that `STM32G474RETx` is acceptable or regenerate it for `STM32G474CEU6`. Then copy/add the new files from this `AD` workspace into that project.
|
||||
|
||||
## Hardware check before any power test
|
||||
|
||||
- Verify all PWM pins with oscilloscope while gate driver is disabled.
|
||||
- Verify driver enable polarity.
|
||||
- Verify fault/break input polarity.
|
||||
- Verify ADC offsets and scaling for currents and DC-link voltage.
|
||||
- Verify emergency stop path disables PWM in hardware.
|
||||
- Verify watchdog behavior.
|
||||
- Verify `AD_ParamID_IsPowerStageAllowed()` stays `0` with default build settings.
|
||||
74
docs/DATA_STRUCTURES.md
Normal file
74
docs/DATA_STRUCTURES.md
Normal file
@@ -0,0 +1,74 @@
|
||||
# Data Structures
|
||||
|
||||
## Project status
|
||||
|
||||
The current workspace contains Simulink S-function code and a C2000/TMS320 motor-control implementation. It does not contain a verified STM32G474CEU6 CubeMX/Keil project. New STM32-safe wrapper structures are placed in `Core/Inc/ad_parameter_identification.h` and `Core/Inc/simulink_interface.h`.
|
||||
|
||||
## Main structures and globals
|
||||
|
||||
| Name | Type | File | Purpose | Fields | Used by | Simulink mapping | Notes |
|
||||
|------|------|------|---------|--------|---------|------------------|-------|
|
||||
| `AD_MotorParameters_t` | `struct` | `Core/Inc/ad_parameter_identification.h` | Portable AD parameter set | `Rs_ohm`, `Rr_ohm`, `Ls_H`, `Lr_H`, `Lm_H`, `Ll_H`, `J_kg_m2`, `B_Nm_s`, nominal values, `valid_mask` | ParamID, Simulink wrapper, telemetry | Should become a Simulink Bus Object | Values are not invented; `valid_mask` marks known fields |
|
||||
| `AD_Measurements_t` | `struct` | `Core/Inc/ad_parameter_identification.h` | Runtime measurements from MCU | `ia_A`, `ib_A`, `ic_A`, `vdc_V`, phase voltages, speed, slip, temperature, timestamp, status flags | ParamID, Simulink wrapper, telemetry | Simulink input bus from MCU to model | ADC scaling/pin sources are TODO for STM32 |
|
||||
| `AD_Command_t` | `struct` | `Core/Inc/ad_parameter_identification.h` | Commands from Simulink/host | `enable`, `test_mode`, `reset_faults`, limits | Simulink wrapper, ParamID | Simulink output bus from model to MCU | Power tests blocked unless explicitly enabled in compile-time config |
|
||||
| `AD_ParamID_SafetyLimits_t` | `struct` | `Core/Inc/ad_parameter_identification.h` | Software safety thresholds | Current, voltage, temperature, speed, timeout | ParamID safety checks | Can be filled from Simulink command or calibration | Zero means UNKNOWN/disabled for that limit |
|
||||
| `SimulinkInterface_InputBus_t` | `struct` | `Core/Inc/simulink_interface.h` | MCU-to-Simulink wrapper data | Measurements, parameters, ParamID status/fault/mode | `SimulinkInterface_*` | Simulink input Bus Object | Stable wrapper, no generated-code edits |
|
||||
| `SimulinkInterface_OutputBus_t` | `struct` | `Core/Inc/simulink_interface.h` | Simulink-to-MCU wrapper data | Command, telemetry state | `SimulinkInterface_*` | Simulink output Bus Object | Contains `AD_Command_t` |
|
||||
| `SimulinkTelemetryPacket_t` | `struct` | `Core/Inc/simulink_interface.h` | Binary telemetry packet | Header + payload | `SimulinkInterface_PackTelemetry` | Optional UART/CAN/USB payload | CRC16 over payload |
|
||||
| `Estimate_Test_t` | `enum` | `Inu/estimate.h` | Existing identification state | `IDLE`, `RS`, `RR_L`, `LM`, `DONE` | `estimate.c`, `upr.c` | Indirect via S-function output/status | C2000/S-function reference |
|
||||
| `Params_t` | `struct` | `Inu/estimate.h` | Existing estimated AD params | `Rs`, `Rr`, `Lm`, `Lk`, `Lls`, `Llr`, `Zk`, `Rk`, `Xk` | `estimate.c` | No direct Bus Object found | Candidate mapping to `AD_MotorParameters_t` |
|
||||
| `RsState_t` | `struct` | `Inu/estimate.h` | Existing Rs test state | step, timers, averaged U/I | `process_Rs` | Not directly exported | Existing method: two DC current levels |
|
||||
| `RrlState_t` | `struct` | `Inu/estimate.h` | Existing rotor/leakage test state | frequency sweep, RMS sums, averages | `process_RrL` | Not directly exported | Existing method: AC current injection |
|
||||
| `LmState_t` | `struct` | `Inu/estimate.h` | Existing magnetizing test state | integration state, averaging | `process_Lm` | Not directly exported | Existing method: integrate `V - Rs*I` |
|
||||
| `struct SgmPar` | `struct` | `Inu/def.h:465` | Runtime AD model parameters | `Rs`, `Lls`, `Rr`, `Llr`, `Lm`, derived `Ls`, `Lr`, `SigmaLs`, `Tr`, `Kl` | `detcoeff.c`, `upr.c`, `isr.c` | Values initialized in S-function setup | Existing AD parameter source |
|
||||
| `struct Result` | `struct` | `Inu/def.h:400` | Raw ADC results after offsets | `udc1`, `ic1`, `ia1`, etc. | `isr.c` | Simulated through wrapper inputs | MCU runtime measurement state |
|
||||
| `struct Offset` | `struct` | `Inu/def.h:357` | ADC offset calibration | current and `Udc` offsets | `detcoeff.c`, `isr.c`, `controller.c` | Parameters in S-function setup | Must be replaced by STM32 ADC calibration |
|
||||
| `struct Mst` | `struct` | `Inu/def.h:343` | Commands from upper controller | start, fault reset, mode, speed/power refs, limits | `controller.c`, `isr.c`, `upr.c` | Existing S-function input vector | Maps partly to `AD_Command_t` |
|
||||
| `struct Protect` | `struct` | `Inu/def.h:383` | Existing protection thresholds/state | current, voltage, speed limits and timers | `isr.c`, `detcoeff.c` | Initialized from `param[]` | Maps partly to safety limits |
|
||||
| `struct Out` | `struct` | `Inu/def.h:370` | Filtered output values | `udc1`, `iac1`, `wm`, `me`, `pm` | `isr.c` | Existing S-function outputs | Telemetry candidate |
|
||||
| `struct Emerg` | `struct` | `Inu/def.h:298` | Fault snapshot | voltage, current, torque, speed, power | `snapshot_emergency` | Not directly mapped | Useful for telemetry fault frame |
|
||||
| `struct Cc`, `Cf`, `Csp` | `struct` | `Inu/def.h` | Current/flux/speed-power regulators | PI terms, limits, feed-forward | `upr.c` | Internal only | Runtime MCU control state |
|
||||
| `struct Ivc`, `Ip` | `struct` | `Inu/def.h` | Vector-control transforms | slip, angle, sin/cos, currents, flux | `upr.c` | Internal only | Runtime MCU control state |
|
||||
| `param[]` | global array | `Inu/param.h`, `Inu/detcoeff.c` | EEPROM-like parameter storage | `param[303..307]` are AD electrical params | `detcoeff.c`, `param.c`, `controller.c` | S-function initializes values | Existing format is not STM32-specific |
|
||||
|
||||
## Structures from Simulink
|
||||
|
||||
Existing S-function wrapper:
|
||||
|
||||
- Input vector width: `INPUT_0_WIDTH = 17` in `Inu/wrapper_inu.h`.
|
||||
- Output vector width: `OUTPUT_0_WIDTH = 35` in `Inu/wrapper_inu.h`.
|
||||
- Input mapping is manually unpacked in `Inu/controller.c:28..47`.
|
||||
- Output mapping is manually packed in `Inu/controller.c:615..662`.
|
||||
|
||||
New wrapper:
|
||||
|
||||
- `SimulinkInterface_OutputBus_t.command` is the command path from Simulink to MCU.
|
||||
- It should map to a Simulink Bus Object containing `AD_Command_t`.
|
||||
|
||||
## Structures sent to Simulink
|
||||
|
||||
- Existing: the S-function output vector contains PWM states, `state`, `faultNo`, `inuWork`, flux, speed, power, currents, torque, current limit, modulation limit, and `theta_out`.
|
||||
- New: `SimulinkInterface_InputBus_t` sends `AD_Measurements_t`, `AD_MotorParameters_t`, ParamID mode/status/faults.
|
||||
|
||||
## Runtime MCU state
|
||||
|
||||
- Existing C2000 runtime state: `Result`, `Out`, `Emerg`, `Protect`, `Cc`, `Cf`, `Csp`, `Ivc`, `Ip`, `RsState_t`, `RrlState_t`, `LmState_t`.
|
||||
- New STM32-safe runtime state is private in `Core/Src/ad_parameter_identification.c` and `Core/Src/simulink_interface.c`.
|
||||
|
||||
## Configuration state
|
||||
|
||||
- Existing: `param[]`, `SgmPar`, `Protect`, offset fields.
|
||||
- New: `AD_ParamID_SafetyLimits_t`, `AD_Command_t`, `AD_MotorParameters_t.valid_mask`.
|
||||
|
||||
## Mapping notes
|
||||
|
||||
| Existing field | New field | Status |
|
||||
|----------------|-----------|--------|
|
||||
| `sgmPar.Rs` | `AD_MotorParameters_t.Rs_ohm` | Direct mapping |
|
||||
| `sgmPar.Rr` | `AD_MotorParameters_t.Rr_ohm` | Direct mapping |
|
||||
| `sgmPar.Ls` | `AD_MotorParameters_t.Ls_H` | Direct mapping if calculated |
|
||||
| `sgmPar.Lr` | `AD_MotorParameters_t.Lr_H` | Direct mapping if calculated |
|
||||
| `sgmPar.Lm` | `AD_MotorParameters_t.Lm_H` | Direct mapping |
|
||||
| `sgmPar.Lls + sgmPar.Llr` | `AD_MotorParameters_t.Ll_H` | Derived mapping |
|
||||
| `udc1`, `ia1Nf`, `ib1Nf`, `result.ic1` | `AD_Measurements_t` | Requires STM32 ADC scaling TODO |
|
||||
| `mst.start`, `mst.faultReset`, `mst.pzMode` | `AD_Command_t` | Partial mapping |
|
||||
26
docs/KEIL_ADD_FILES.md
Normal file
26
docs/KEIL_ADD_FILES.md
Normal file
@@ -0,0 +1,26 @@
|
||||
# Keil Add Files
|
||||
|
||||
Automatic `.uvprojx` editing was not performed because no STM32G474CEU6 Keil project exists in the current `AD` workspace.
|
||||
|
||||
A sibling candidate project was found:
|
||||
|
||||
```text
|
||||
F:\set\workspace\setcorp\set506\git_project\stm32g474\stm32g474_IHM08M\IHM08M\MDK-ARM\IHM08M.uvprojx
|
||||
```
|
||||
|
||||
It targets `STM32G474RETx`/NUCLEO-G474RE, not `STM32G474CEU6`, and is outside the writable root for this task.
|
||||
|
||||
When the real Keil project is available, add:
|
||||
|
||||
| Group | File |
|
||||
|-------|------|
|
||||
| User/Simulink Interface | `Core/Src/simulink_interface.c` |
|
||||
| User/AD Parameter Identification | `Core/Src/ad_parameter_identification.c` |
|
||||
|
||||
Also add include path:
|
||||
|
||||
```text
|
||||
Core/Inc
|
||||
```
|
||||
|
||||
Do not add or edit generated Simulink files by hand unless the generated-code workflow requires it.
|
||||
95
docs/MD_DRIVER_MAP.md
Normal file
95
docs/MD_DRIVER_MAP.md
Normal file
@@ -0,0 +1,95 @@
|
||||
# MD / Motor Driver Map
|
||||
|
||||
## Status
|
||||
|
||||
No STM32G474CEU6 motor-driver files such as `md.c`, `motor_driver.c`, `gate_driver.c`, `drv.c`, `inverter.c`, `pwm.c`, or STM32 `tim.c/adc.c/gpio.c` were found in the current `AD` workspace.
|
||||
|
||||
The available motor-driver evidence is a C2000/TMS320 INU implementation under `Inu_im_1wnd_3lvl/Inu`.
|
||||
|
||||
A sibling STM32G474 candidate was found at `F:\set\workspace\setcorp\set506\git_project\stm32g474\stm32g474_IHM08M\IHM08M`, but it targets `STM32G474RETx`/NUCLEO-G474RE, not the requested `STM32G474CEU6`.
|
||||
|
||||
## Driver pins
|
||||
|
||||
| Function | STM32G474 status | Existing source evidence | Notes |
|
||||
|----------|------------------|--------------------------|-------|
|
||||
| Gate/PWM outputs | UNKNOWN/TODO | GPIO0..GPIO11 mapped to ePWM1A/B..ePWM6A/B in `Inu/init28335.c:177..188` | STM32 TIM channels must be extracted from `.ioc` when available |
|
||||
| Driver enable | UNKNOWN/TODO | No explicit `EN_GATE`/`DRV_EN` STM32 pin found | Existing C2000 enables pulses by clearing Trip-Zone latch in `pwm()` |
|
||||
| Driver fault | UNKNOWN/TODO | `DI_24V_SOURCE_FAULT` on C2000 GPIO50, active high | Real STM32 fault input must be documented from schematic/CubeMX |
|
||||
| EEPROM/SPI CS | UNKNOWN/TODO | C2000 GPIO57 `CS_SET/CS_CLEAR`, SPIA on GPIO54..56 | Exact external device UNKNOWN |
|
||||
| Status LEDs | UNKNOWN/TODO | GPIO59..61 active-low LEDs | Board-specific, not motor-driver critical |
|
||||
|
||||
## PWM generation
|
||||
|
||||
Existing C2000 implementation:
|
||||
|
||||
- ePWM1..ePWM6 are initialized in `SetupEpwm()` in `Inu/init28335.c`.
|
||||
- ePWM period uses `T1_PRD` derived from `T_PWM`.
|
||||
- PWM compare registers are written in `pwm()` in `Inu/upr.c:537..558`.
|
||||
- Dead-time uses `DT` in `Inu/def.h`.
|
||||
- Emergency PWM disable uses Trip-Zone force `TZFRC.all = 0x0004` in `stop_inu()` in `Inu/isr.c:300..328`.
|
||||
|
||||
STM32G474 TODO:
|
||||
|
||||
- Identify TIM1/TIM8 or other advanced timer instance.
|
||||
- Identify complementary channels, dead-time, break input, BKIN polarity, off-state behavior.
|
||||
- Verify that all PWM outputs remain disabled after reset and during ParamID default state.
|
||||
|
||||
Candidate STM32G474RETx project:
|
||||
|
||||
- TIM1 PWM is configured only for `TIM_CHANNEL_1` with output pin `PA7/TIM1_CH1N`.
|
||||
- `MX_TIM1_Init()` has `DeadTime = 0`, `BreakState = TIM_BREAK_DISABLE`, `Break2State = TIM_BREAK2_DISABLE`, `AutomaticOutput = TIM_AUTOMATICOUTPUT_DISABLE`.
|
||||
- Calls to `HAL_Init()`, `SystemClock_Config()`, `MX_GPIO_Init()`, and `MX_TIM1_Init()` are commented out in `Core/Src/main.c`, so the candidate firmware currently does not initialize peripherals at runtime.
|
||||
|
||||
## ADC/current sense
|
||||
|
||||
Existing C2000 implementation:
|
||||
|
||||
| Measurement | Existing source | Notes |
|
||||
|-------------|-----------------|-------|
|
||||
| DC-link voltage `udc1` | `AdcMirror.ADCRESULT0`, `Inu/isr.c:37` | Offset `offset.Udc1`, scale `GAIN_UDC` |
|
||||
| Current `ic1` | `AdcMirror.ADCRESULT2`, `Inu/isr.c:38` | Offset `offset.Ic1`, scale `GAIN_IAC` |
|
||||
| Current `ia1` | `AdcMirror.ADCRESULT4`, `Inu/isr.c:39` | Offset `offset.Ia1`, scale `GAIN_IAC` |
|
||||
| Current `ib1` | `AdcMirror.ADCRESULT6`, `Inu/isr.c:40` | Offset `offset.Ib1`, scale `GAIN_IAC` |
|
||||
|
||||
STM32G474 TODO:
|
||||
|
||||
- Identify ADC instances and channels from `.ioc`.
|
||||
- Identify injected/regular conversion, DMA buffers, trigger timer, sampling time.
|
||||
- Map ADC raw values into `AD_Measurements_t`.
|
||||
|
||||
Candidate STM32G474RETx project:
|
||||
|
||||
- No ADC module is enabled in `stm32g4xx_hal_conf.h`.
|
||||
- No ADC pins/channels are configured in `IHM08M.ioc`.
|
||||
|
||||
## Protection logic found
|
||||
|
||||
| Protection | Existing implementation | Fault |
|
||||
|------------|-------------------------|-------|
|
||||
| Overcurrent | `result.ia1/ib1/ic1` checked against `protect.IacMax/IacMin` in `Inu/isr.c:97..101` | `faultNo = 22` |
|
||||
| DC-link undervoltage | `udc1Nf < protect.UdcMin` with debounce in `Inu/isr.c:104..115` | `faultNo = 30` |
|
||||
| DC-link overvoltage | `udc1Nf > protect.UdcMax` in `Inu/isr.c:121..123` | `faultNo = 24` |
|
||||
| Overspeed | `wm > protect.WmMax` with debounce in `Inu/isr.c:126..137` | `faultNo = 32` |
|
||||
| +24 V supply fault | `DI_24V_SOURCE_FAULT == 1` with debounce in `Inu/isr.c:140..151` | `faultNo = 7` |
|
||||
| PWM shutdown | `stop_inu()` forces Trip-Zone and clears compare registers | Safe stop path |
|
||||
|
||||
## Missing or unverified protections
|
||||
|
||||
- STM32G474 hardware break input: UNKNOWN.
|
||||
- Gate-driver fault polarity and latch behavior: UNKNOWN.
|
||||
- Overtemperature source: UNKNOWN.
|
||||
- Emergency stop pin: UNKNOWN.
|
||||
- DC-link discharge/ready signal: UNKNOWN.
|
||||
- Hardware overcurrent comparator/OPAMP/COMP chain: UNKNOWN.
|
||||
- Watchdog strategy for STM32 project: UNKNOWN.
|
||||
|
||||
## New safe software interlock
|
||||
|
||||
`Core/Src/ad_parameter_identification.c` adds:
|
||||
|
||||
- Compile-time default `AD_PARAM_ID_ENABLE_POWER_TESTS = 0`.
|
||||
- Software enable gate via `AD_ParamID_SetSoftwareEnable`.
|
||||
- Fault latch via `AD_PARAM_ID_STATUS_FAULT_LATCHED`.
|
||||
- Emergency stop API `AD_ParamID_EmergencyStop`.
|
||||
- Checks for measurement status flags and configured current/voltage/temperature/speed limits.
|
||||
- Locked-rotor mode blocked unless `AD_ParamID_SetLockedRotorAllowed(1)` is called and power tests are compiled in.
|
||||
114
docs/PINMAP_STM32G474CEU6.md
Normal file
114
docs/PINMAP_STM32G474CEU6.md
Normal file
@@ -0,0 +1,114 @@
|
||||
# PINMAP STM32G474CEU6
|
||||
|
||||
## Source inventory
|
||||
|
||||
| Item | Result | Evidence |
|
||||
|------|--------|----------|
|
||||
| STM32G474CEU6 Keil `.uvprojx` | UNKNOWN/TODO | No `.uvprojx` found under `F:\set\workspace\setcorp\set506\AD` |
|
||||
| Candidate STM32G474 Keil `.uvprojx` | FOUND OUTSIDE WRITABLE ROOT | `F:\set\workspace\setcorp\set506\git_project\stm32g474\stm32g474_IHM08M\IHM08M\MDK-ARM\IHM08M.uvprojx` |
|
||||
| Candidate CubeMX `.ioc` | FOUND OUTSIDE WRITABLE ROOT | `F:\set\workspace\setcorp\set506\git_project\stm32g474\stm32g474_IHM08M\IHM08M\IHM08M.ioc` |
|
||||
| Candidate target MCU | MISMATCH | `.ioc` and `.uvprojx` use `STM32G474RETx`, board `NUCLEO-G474RE`, package `LQFP64`; requested MCU is `STM32G474CEU6` |
|
||||
| STM32 HAL/LL init files in current `AD` workspace | UNKNOWN/TODO | No `Core/Src/main.c`, `gpio.c`, `adc.c`, `tim.c`, `stm32g4xx_hal_msp.c` under `AD` before this task |
|
||||
| Simulink model | FOUND | `Inu_im_1wnd_3lvl/inu_im_1wnd_3lvl.slx`, `Inu_im_1wnd_3lvl/inu_im_1wnd_3lvl_r2021b.slx` |
|
||||
| Existing embedded reference code | FOUND, non-STM32 | `Inu_im_1wnd_3lvl/Inu/*.c`, target comments and headers reference `TMS320F28335/TMS320F28379D` |
|
||||
|
||||
## Verified STM32G474CEU6 pins
|
||||
|
||||
No verified STM32G474CEU6 pin assignment is present in the current `AD` workspace. The table is intentionally not populated with guessed CubeMX defaults.
|
||||
|
||||
| MCU pin | Port/Pin | Signal name | Direction | Peripheral/AF | Connected block | Source file | Init function | Active level | Notes |
|
||||
|---------|----------|-------------|-----------|----------------|-----------------|-------------|---------------|--------------|-------|
|
||||
| UNKNOWN | UNKNOWN | UNKNOWN | UNKNOWN | UNKNOWN | UNKNOWN | TODO: add `.ioc`, `main.h`, `gpio.c`, `stm32g4xx_hal_msp.c`, `.uvprojx` | UNKNOWN | UNKNOWN | STM32G474CEU6 pinout cannot be reconstructed from the files currently present |
|
||||
|
||||
## Candidate STM32G474RETx pins found outside `AD`
|
||||
|
||||
These rows come from the sibling NUCLEO-G474RE project. They are useful evidence, but they are not a verified `STM32G474CEU6` pinout.
|
||||
|
||||
| MCU pin | Port/Pin | Signal name | Direction | Peripheral/AF | Connected block | Source file | Init function | Active level | Notes |
|
||||
|---------|----------|-------------|-----------|----------------|-----------------|-------------|---------------|--------------|-------|
|
||||
| LQFP64 pin UNKNOWN | PC13 | B1 | Input interrupt | EXTI13 | Blue push button | `IHM08M.ioc`, `Core/Inc/main.h`, `Core/Src/main.c:250` | `MX_GPIO_Init` | Rising edge | Candidate project only |
|
||||
| LQFP64 pin UNKNOWN | PC14 | RCC_OSC32_IN | Input | LSE oscillator | 32.768 kHz crystal | `IHM08M.ioc`, `Core/Inc/main.h` | RCC/CubeMX | Analog clock | Candidate project only |
|
||||
| LQFP64 pin UNKNOWN | PC15 | RCC_OSC32_OUT | Output | LSE oscillator | 32.768 kHz crystal | `IHM08M.ioc`, `Core/Inc/main.h` | RCC/CubeMX | Analog clock | Candidate project only |
|
||||
| LQFP64 pin UNKNOWN | PF0 | RCC_OSC_IN | Input | HSE oscillator | External oscillator | `IHM08M.ioc`, `Core/Inc/main.h` | RCC/CubeMX | Analog clock | Candidate project only |
|
||||
| LQFP64 pin UNKNOWN | PF1 | RCC_OSC_OUT | Output | HSE oscillator | External oscillator | `IHM08M.ioc`, `Core/Inc/main.h` | RCC/CubeMX | Analog clock | Candidate project only |
|
||||
| LQFP64 pin UNKNOWN | PA5 | LD2 | Output | GPIO output | Green LED | `IHM08M.ioc`, `Core/Inc/main.h`, `Core/Src/main.c:256` | `MX_GPIO_Init` | Reset by init; Nucleo LED usually active high | Candidate project only |
|
||||
| LQFP64 pin UNKNOWN | PA7 | TIM1_CH1N | PWM output | AF6 TIM1_CH1N, open-drain AF in MSP | PWM Generation1 CH1N | `IHM08M.ioc`, `Core/Src/stm32g4xx_hal_msp.c:122` | `MX_TIM1_Init`, `HAL_TIM_MspPostInit` | PWM, polarity high | Break disabled, dead-time 0 in `MX_TIM1_Init` |
|
||||
| LQFP64 pin UNKNOWN | PB0 | UNKNOWN GPIO output | Output | GPIO output | UNKNOWN | `IHM08M.ioc`, `Core/Src/main.c:263` | `MX_GPIO_Init` | Reset by init | Candidate project only |
|
||||
| LQFP64 pin UNKNOWN | PB1 | UNKNOWN GPIO output | Output | GPIO output | UNKNOWN | `IHM08M.ioc`, `Core/Src/main.c:263` | `MX_GPIO_Init` | Reset by init | Candidate project only |
|
||||
| LQFP64 pin UNKNOWN | PA8 | UNKNOWN GPIO output | Output | GPIO output | UNKNOWN | `IHM08M.ioc`, `Core/Src/main.c:256` | `MX_GPIO_Init` | Reset by init | Candidate project only |
|
||||
| LQFP64 pin UNKNOWN | PA9 | UNKNOWN GPIO output | Output | GPIO output | UNKNOWN | `IHM08M.ioc`, `Core/Src/main.c:256` | `MX_GPIO_Init` | Reset by init | Candidate project only |
|
||||
| LQFP64 pin UNKNOWN | PA10 | UNKNOWN GPIO output | Output | GPIO output | UNKNOWN | `IHM08M.ioc`, `Core/Src/main.c:256` | `MX_GPIO_Init` | Reset by init | Candidate project only |
|
||||
| LQFP64 pin UNKNOWN | PA13 | T_SWDIO | Debug | SWDIO | SWD | `IHM08M.ioc`, `Core/Inc/main.h` | SYS/CubeMX | Debug | Candidate project only |
|
||||
| LQFP64 pin UNKNOWN | PA14 | T_SWCLK | Debug | SWCLK | SWD | `IHM08M.ioc`, `Core/Inc/main.h` | SYS/CubeMX | Debug | Candidate project only |
|
||||
| LQFP64 pin UNKNOWN | PB3 | T_SWO | Debug | SWO | Trace | `IHM08M.ioc`, `Core/Inc/main.h` | SYS/CubeMX | Debug | Candidate project only |
|
||||
|
||||
Candidate project peripheral status:
|
||||
|
||||
| Peripheral | Status | Evidence |
|
||||
|------------|--------|----------|
|
||||
| ADC | Not enabled | `HAL_ADC_MODULE_ENABLED` commented in `Core/Inc/stm32g4xx_hal_conf.h` |
|
||||
| TIM/PWM | TIM1 PWM CH1N only | `MX_TIM1_Init`, `PA7 TIM1_CH1N` |
|
||||
| GPIO | PC13, PA5, PA8, PA9, PA10, PB0, PB1 plus debug/osc pins | `.ioc`, `main.c` |
|
||||
| DMA | HAL DMA source included by project, no configured DMA init found | `.uvprojx`, no `MX_DMA_Init` |
|
||||
| UART/USART | Not enabled | `HAL_USART_MODULE_ENABLED` commented |
|
||||
| CAN/FDCAN | Not enabled | `HAL_FDCAN_MODULE_ENABLED` commented |
|
||||
| SPI/I2C | Not enabled | `HAL_SPI_MODULE_ENABLED`, `HAL_I2C_MODULE_ENABLED` commented |
|
||||
| OPAMP/COMP | Not enabled | `HAL_OPAMP_MODULE_ENABLED`, `HAL_COMP_MODULE_ENABLED` commented |
|
||||
| Watchdog/fault inputs | Not configured | No IWDG/WWDG init; TIM1 break disabled |
|
||||
|
||||
## Non-STM32 reference signals found in existing code
|
||||
|
||||
These rows are not STM32 pins. They are the actual motor-control pin/peripheral evidence found in the available C2000/Simulink source and should be used only as a migration checklist.
|
||||
|
||||
| MCU pin | Port/Pin | Signal name | Direction | Peripheral/AF | Connected block | Source file | Init function | Active level | Notes |
|
||||
|---------|----------|-------------|-----------|----------------|-----------------|-------------|---------------|--------------|-------|
|
||||
| TMS320 GPIO0 | GPIO0 | EPWM1A | PWM output | ePWM1A | INU phase/control leg | `Inu/init28335.c:177` | `SetupGpio` | PWM | C2000 reference only |
|
||||
| TMS320 GPIO1 | GPIO1 | EPWM1B | PWM output | ePWM1B | INU phase/control leg | `Inu/init28335.c:178` | `SetupGpio` | PWM | Complementary/dead-band in ePWM |
|
||||
| TMS320 GPIO2 | GPIO2 | EPWM2A | PWM output | ePWM2A | INU phase/control leg | `Inu/init28335.c:179` | `SetupGpio` | PWM | C2000 reference only |
|
||||
| TMS320 GPIO3 | GPIO3 | EPWM2B | PWM output | ePWM2B | INU phase/control leg | `Inu/init28335.c:180` | `SetupGpio` | PWM | C2000 reference only |
|
||||
| TMS320 GPIO4 | GPIO4 | EPWM3A | PWM output | ePWM3A | INU phase/control leg | `Inu/init28335.c:181` | `SetupGpio` | PWM | C2000 reference only |
|
||||
| TMS320 GPIO5 | GPIO5 | EPWM3B | PWM output | ePWM3B | INU phase/control leg | `Inu/init28335.c:182` | `SetupGpio` | PWM | C2000 reference only |
|
||||
| TMS320 GPIO6 | GPIO6 | EPWM4A | PWM output | ePWM4A | INU phase/control leg | `Inu/init28335.c:183` | `SetupGpio` | PWM | C2000 reference only |
|
||||
| TMS320 GPIO7 | GPIO7 | EPWM4B | PWM output | ePWM4B | INU phase/control leg | `Inu/init28335.c:184` | `SetupGpio` | PWM | C2000 reference only |
|
||||
| TMS320 GPIO8 | GPIO8 | EPWM5A | PWM output | ePWM5A | INU phase/control leg | `Inu/init28335.c:185` | `SetupGpio` | PWM | C2000 reference only |
|
||||
| TMS320 GPIO9 | GPIO9 | EPWM5B | PWM output | ePWM5B | INU phase/control leg | `Inu/init28335.c:186` | `SetupGpio` | PWM | C2000 reference only |
|
||||
| TMS320 GPIO10 | GPIO10 | EPWM6A | PWM output | ePWM6A | INU phase/control leg | `Inu/init28335.c:187` | `SetupGpio` | PWM | C2000 reference only |
|
||||
| TMS320 GPIO11 | GPIO11 | EPWM6B | PWM output | ePWM6B | INU phase/control leg | `Inu/init28335.c:188` | `SetupGpio` | PWM | C2000 reference only |
|
||||
| TMS320 GPIO22 | GPIO22 | SCITXDB | Output | SCI-B TX | Communication | `Inu/init28335.c:200` | `SetupGpio` | UART idle high | Exact protocol UNKNOWN |
|
||||
| TMS320 GPIO23 | GPIO23 | SCIRXDB | Input | SCI-B RX | Communication | `Inu/init28335.c:201` | `SetupGpio` | UART idle high | Exact protocol UNKNOWN |
|
||||
| TMS320 GPIO24 | GPIO24 | EQEP2A | Input | eQEP2A | Speed/position sensor | `Inu/init28335.c:202` | `SetupGpio`, `SetupEqep` | Quadrature | Used by `sens_wm()` |
|
||||
| TMS320 GPIO25 | GPIO25 | EQEP2B | Input | eQEP2B | Speed/position sensor | `Inu/init28335.c:203` | `SetupGpio`, `SetupEqep` | Quadrature | Used by `sens_wm()` |
|
||||
| TMS320 GPIO26 | GPIO26 | EQEP2I | Input | eQEP2I | Index sensor | `Inu/init28335.c:204` | `SetupGpio`, `SetupEqep` | Index | Used by eQEP block |
|
||||
| TMS320 GPIO28 | GPIO28 | SCIRXDA | Input | SCI-A RX | Communication | `Inu/init28335.c:206` | `SetupGpio` | UART idle high | Protocol UNKNOWN |
|
||||
| TMS320 GPIO29 | GPIO29 | SCITXDA | Output | SCI-A TX | Communication | `Inu/init28335.c:207` | `SetupGpio` | UART idle high | Protocol UNKNOWN |
|
||||
| TMS320 GPIO32 | GPIO32 | EPWMSYNCI | Input | ePWM sync in | PWM sync | `Inu/init28335.c:211` | `SetupGpio` | Peripheral | C2000 reference only |
|
||||
| TMS320 GPIO33 | GPIO33 | EPWMSYNCO | Output | ePWM sync out | PWM sync | `Inu/init28335.c:212` | `SetupGpio` | Peripheral | C2000 reference only |
|
||||
| TMS320 GPIO50 | GPIO50 | DI_24V_SOURCE_FAULT | Input | GPIO | +24 V supply fault | `Inu/def.h:139`, `Inu/isr.c:140` | `SetupGpio` | Active high | FaultNo 7 after debounce |
|
||||
| TMS320 GPIO54 | GPIO54 | SPISIMOA | Output | SPI-A MOSI | EEPROM or external SPI | `Inu/init28335.c:234` | `SetupGpio` | SPI | Exact device UNKNOWN |
|
||||
| TMS320 GPIO55 | GPIO55 | SPISOMIA | Input | SPI-A MISO | EEPROM or external SPI | `Inu/init28335.c:235` | `SetupGpio` | SPI | Exact device UNKNOWN |
|
||||
| TMS320 GPIO56 | GPIO56 | SPICLKA | Output | SPI-A SCK | EEPROM or external SPI | `Inu/init28335.c:236` | `SetupGpio` | SPI | Exact device UNKNOWN |
|
||||
| TMS320 GPIO57 | GPIO57 | CS | Output | GPIO | EEPROM chip select | `Inu/def.h:180` | `SetupGpio` | Active high by macro `CS_SET` | Verify external device polarity |
|
||||
| TMS320 GPIO59 | GPIO59 | LED_GREEN1 | Output | GPIO | Ready LED | `Inu/def.h:184` | `SetupGpio` | Active low | `ON` writes GPBCLEAR |
|
||||
| TMS320 GPIO60 | GPIO60 | LED_GREEN2 | Output | GPIO | Work LED | `Inu/def.h:188` | `SetupGpio` | Active low | `ON` writes GPBCLEAR |
|
||||
| TMS320 GPIO61 | GPIO61 | LED_RED | Output | GPIO | Fault LED | `Inu/def.h:192` | `SetupGpio` | Active low | `ON` writes GPBCLEAR |
|
||||
| TMS320 GPIO62 | GPIO62 | SCIRXDC | Input | SCI-C RX | Communication | `Inu/init28335.c:242` | `SetupGpio` | UART idle high | Protocol UNKNOWN |
|
||||
| TMS320 GPIO63 | GPIO63 | SCITXDC | Output | SCI-C TX | Communication | `Inu/init28335.c:243` | `SetupGpio` | UART idle high | Also has `DO_GPIO63_CLEAR` macro |
|
||||
|
||||
## ADC evidence in existing code
|
||||
|
||||
| ADC result | Signal | Source file | Init function | Notes |
|
||||
|------------|--------|-------------|---------------|-------|
|
||||
| ADCRESULT0 | `udc1` | `Inu/isr.c:37`, `Inu/controller.c:340` | `SetupAdc` | DC-link voltage, offset `offset.Udc1` |
|
||||
| ADCRESULT2 | `ic1` | `Inu/isr.c:38`, `Inu/controller.c:347` | `SetupAdc` | Phase/current channel C, offset `offset.Ic1` |
|
||||
| ADCRESULT4 | `ia1` | `Inu/isr.c:39`, `Inu/controller.c:356` | `SetupAdc` | Phase/current channel A, offset `offset.Ia1` |
|
||||
| ADCRESULT6 | `ib1` | `Inu/isr.c:40`, `Inu/controller.c:363` | `SetupAdc` | Phase/current channel B, offset `offset.Ib1` |
|
||||
|
||||
## TODO for STM32G474CEU6 migration
|
||||
|
||||
Add the real STM32 project files, then regenerate this document from:
|
||||
|
||||
- `.ioc`: pin names, peripherals, AF selections, ADC channels, DMA, timers.
|
||||
- `Core/Inc/main.h`: GPIO aliases and active-level macros.
|
||||
- `Core/Src/gpio.c`, `adc.c`, `tim.c`, `usart.c`, `fdcan.c`, `spi.c`, `i2c.c`: init functions.
|
||||
- `Core/Src/stm32g4xx_hal_msp.c`: MSP GPIO AF and DMA binding.
|
||||
- `.uvprojx`: included source tree and target device.
|
||||
128
docs/SIMULINK_INTEGRATION.md
Normal file
128
docs/SIMULINK_INTEGRATION.md
Normal file
@@ -0,0 +1,128 @@
|
||||
# Simulink Integration
|
||||
|
||||
## Existing Simulink artifacts
|
||||
|
||||
| Artifact | Status | Notes |
|
||||
|----------|--------|-------|
|
||||
| `Inu_im_1wnd_3lvl/inu_im_1wnd_3lvl.slx` | FOUND | Simulink model |
|
||||
| `Inu_im_1wnd_3lvl/inu_im_1wnd_3lvl_r2021b.slx` | FOUND | Simulink model copy/version |
|
||||
| `Inu_im_1wnd_3lvl/Inu/wrapper_inu.c` | FOUND | Level-2 C S-function wrapper |
|
||||
| `Inu_im_1wnd_3lvl/Inu/controller.c` | FOUND | Model-side processor/peripheral simulation |
|
||||
| ERT generated code (`ert_main.c`, `model.c`, `model.h`, `rtwtypes.h`) | NOT FOUND | Only `slprj` cache/accel artifacts are present |
|
||||
|
||||
## Existing S-function mapping
|
||||
|
||||
Wrapper:
|
||||
|
||||
- S-function name: `wrapper_inu`.
|
||||
- Main update path: `mdlUpdate()` calls `controller(S, u, xD, rW, iW)`.
|
||||
- Input width: `17`.
|
||||
- Output width: `35`.
|
||||
- Sample time: first and only S-function parameter, read in `mdlInitializeSampleTimes()`.
|
||||
|
||||
Input vector unpacking in `Inu/controller.c:28..47`:
|
||||
|
||||
| Index | Existing signal | Meaning |
|
||||
|-------|-----------------|---------|
|
||||
| 0 | `udc1_ml` | DC-link voltage, V |
|
||||
| 1 | `ia1_ml` | Phase current A, A |
|
||||
| 2 | `ib1_ml` | Phase current B, A |
|
||||
| 3 | `ic1_ml` | Phase current C, A |
|
||||
| 4 | `wm_ml` | Mechanical speed, rad/s |
|
||||
| 5 | `mst.faultReset` | Fault reset |
|
||||
| 6 | `mst.start` | Start command |
|
||||
| 7 | `mst.pzMode` | Speed/power mode |
|
||||
| 8 | `mst.wmZz` | Speed reference, p.u. |
|
||||
| 9 | `mst.pmZz` | Power reference, scaled |
|
||||
| 10 | `mst.wmLim` | Speed limit, p.u. |
|
||||
| 11 | `mst.pmLim` | Power limit, scaled |
|
||||
| 12 | `mst.pIncrMaxTy` | Power ramp up |
|
||||
| 13 | `mst.pDecrMaxTy` | Power ramp down |
|
||||
| 14 | `iref` | Current reference, p.u. |
|
||||
| 15..16 | `paramNew[]` | Parameter writes |
|
||||
|
||||
Output vector packing in `Inu/controller.c:615..662`:
|
||||
|
||||
- PWM logical outputs for ePWM1..ePWM6 A/B after dead-time/trip simulation.
|
||||
- State and fault signals.
|
||||
- Start/work/mode status.
|
||||
- Flux, speed, power, current, torque and limits.
|
||||
- `theta_out`.
|
||||
|
||||
## New wrapper API
|
||||
|
||||
Files:
|
||||
|
||||
- `Core/Inc/simulink_interface.h`
|
||||
- `Core/Src/simulink_interface.c`
|
||||
- `Core/Inc/ad_parameter_identification.h`
|
||||
- `Core/Src/ad_parameter_identification.c`
|
||||
|
||||
Functions:
|
||||
|
||||
```c
|
||||
void SimulinkInterface_Init(void);
|
||||
void SimulinkInterface_StepFast(void);
|
||||
void SimulinkInterface_StepSlow(void);
|
||||
void SimulinkInterface_UpdateInputs(void);
|
||||
void SimulinkInterface_UpdateOutputs(void);
|
||||
void SimulinkInterface_PackTelemetry(void);
|
||||
void SimulinkInterface_UnpackCommand(void);
|
||||
```
|
||||
|
||||
## Bus Object proposal
|
||||
|
||||
Create Simulink Bus Objects that exactly match:
|
||||
|
||||
- `AD_Measurements_t`
|
||||
- `AD_MotorParameters_t`
|
||||
- `AD_Command_t`
|
||||
- `SimulinkInterface_InputBus_t`
|
||||
- `SimulinkInterface_OutputBus_t`
|
||||
|
||||
Keep field order and fixed-width integer types identical to the C headers.
|
||||
|
||||
## MCU-to-Simulink signals
|
||||
|
||||
Use `SimulinkInterface_InputBus_t`:
|
||||
|
||||
- `measurements`: raw physical measurements already scaled to SI units.
|
||||
- `motor_parameters`: known or estimated AD parameters; validity is controlled by `valid_mask`.
|
||||
- `param_id_status`: identification status bits.
|
||||
- `param_id_faults`: latched fault bits.
|
||||
- `param_id_mode`: current identification mode.
|
||||
|
||||
## Simulink-to-MCU signals
|
||||
|
||||
Use `SimulinkInterface_OutputBus_t.command`:
|
||||
|
||||
- `enable`: software enable request.
|
||||
- `test_mode`: one of `AD_PARAM_ID_MODE_*`.
|
||||
- `reset_faults`: clears the software fault latch.
|
||||
- `pwm_duty_limit`, `current_limit_A`, `voltage_limit_V`, `speed_limit_rpm`: safety/control limits.
|
||||
|
||||
## Loop rates
|
||||
|
||||
Current STM32 timing is UNKNOWN because the STM32G474 project is not present.
|
||||
|
||||
Recommended mapping after CubeMX/Keil project is available:
|
||||
|
||||
- `SimulinkInterface_StepFast()`: call from ADC/PWM control interrupt, typically current-loop rate.
|
||||
- `SimulinkInterface_StepSlow()`: call from main loop or a slower timer, typically telemetry/diagnostics rate.
|
||||
- `SimulinkInterface_UpdateInputs()`: after ADC/speed/temperature measurement update.
|
||||
- `SimulinkInterface_UpdateOutputs()`: after Simulink command unpacking and safety state update.
|
||||
|
||||
## Safety behavior
|
||||
|
||||
- Generated Simulink files are not modified.
|
||||
- New wrapper does not enable power hardware.
|
||||
- `AD_PARAM_ID_ENABLE_POWER_TESTS` defaults to `0`.
|
||||
- With the default setting, requested power tests fall back to data logging and set `AD_PARAM_ID_STATUS_POWER_TEST_BLOCKED`.
|
||||
|
||||
## TODO
|
||||
|
||||
- Add real STM32G474 generated code or `.ioc`.
|
||||
- Identify generated model step function if ERT code is later generated.
|
||||
- Decide whether the Simulink model will consume the new Bus Objects directly or through a C Caller/S-function layer.
|
||||
- Map STM32 ADC/TIM/DMA data into `AD_Measurements_t`.
|
||||
- Map final motor-control outputs to a verified motor-driver abstraction, not directly to PWM registers.
|
||||
453
docs/TELEMETRY_PROTOCOL.md
Normal file
453
docs/TELEMETRY_PROTOCOL.md
Normal file
@@ -0,0 +1,453 @@
|
||||
# Протокол телеметрии
|
||||
|
||||
Документ описывает текущий бинарный пакет телеметрии из прошивки
|
||||
`AD_Keil_Project`.
|
||||
|
||||
Основные файлы реализации:
|
||||
|
||||
| Файл | Назначение |
|
||||
|---|---|
|
||||
| `Core/Inc/simulink_interface.h` | Формат пакета, версия, размеры, API |
|
||||
| `Core/Src/simulink_interface.c` | Заполнение пакета и CRC16 |
|
||||
| `Core/Inc/ad_binary_transport.h` | Выбор протокола и транспорта |
|
||||
| `Core/Src/ad_binary_transport.c` | Отправка готового пакета |
|
||||
| `Core/Src/ad_usb_cdc.c` | USB FS CDC ACM транспорт |
|
||||
| `Core/Src/ad_can_telemetry.c` | FDCAN1 classic CAN транспорт |
|
||||
| `Core/Src/ad_modbus.c` | Modbus-регистры включения бинарной телеметрии |
|
||||
|
||||
## Кратко
|
||||
|
||||
Прошивка формирует один бинарный пакет `SimulinkTelemetryPacket_t`.
|
||||
Пакет можно отдавать через USB CDC, через FDCAN1 classic CAN или одновременно
|
||||
через оба транспорта.
|
||||
|
||||
По умолчанию бинарный поток выключен:
|
||||
|
||||
```c
|
||||
AD_HOST_PROTOCOL_DEFAULT = 0
|
||||
AD_BINARY_TELEMETRY_TRANSPORT_DEFAULT = 0
|
||||
```
|
||||
|
||||
То есть после старта активен режим `0` - Modbus-контроль без бинарной
|
||||
телеметрии. Чтобы включить поток, нужно через Modbus записать:
|
||||
|
||||
```text
|
||||
0x001D / 29 = транспорт
|
||||
0x001C / 28 = 1
|
||||
```
|
||||
|
||||
Где транспорт:
|
||||
|
||||
| Значение | Транспорт |
|
||||
|---:|---|
|
||||
| `0` | USB CDC |
|
||||
| `1` | CAN/FDCAN1 |
|
||||
| `2` | USB CDC и CAN/FDCAN1 одновременно |
|
||||
|
||||
Чтобы выключить бинарный поток:
|
||||
|
||||
```text
|
||||
0x001C / 28 = 0
|
||||
```
|
||||
|
||||
## Частота
|
||||
|
||||
Пакет обновляется в `SimulinkInterface_StepSlow()`, который вызывается из
|
||||
`AD_Board_Loop()` раз в `AD_BOARD_SLOW_PERIOD_MS = 10` мс.
|
||||
|
||||
Отправка из `AD_BinaryTransport_Loop()` также ограничена периодом:
|
||||
|
||||
```c
|
||||
AD_BINARY_TELEMETRY_PERIOD_MS = 10
|
||||
```
|
||||
|
||||
Итого штатная частота телеметрии - около `100 Гц`, если главный цикл успевает
|
||||
обслуживать транспорт.
|
||||
|
||||
## Кодирование данных
|
||||
|
||||
| Параметр | Значение |
|
||||
|---|---|
|
||||
| Порядок байт | little-endian, как у STM32 Cortex-M |
|
||||
| `float` | IEEE-754 binary32, 4 байта |
|
||||
| Выравнивание | обычное C-выравнивание ARMCLANG, без `packed` |
|
||||
| Текущий размер заголовка | `16` байт |
|
||||
| Текущий размер payload | `136` байт |
|
||||
| Текущий размер полного пакета | `152` байта |
|
||||
| Максимум, разрешенный кодом | `SIMULINK_TELEMETRY_MAX_BYTES = 256` |
|
||||
|
||||
Если структура в C будет изменена, PC-парсер должен проверять
|
||||
`header.version` и `header.payload_size`.
|
||||
|
||||
## Заголовок пакета
|
||||
|
||||
Тип: `SimulinkTelemetryHeader_t`.
|
||||
|
||||
Смещения указаны от начала пакета.
|
||||
|
||||
| Offset | Размер | Тип | Поле | Значение / описание |
|
||||
|---:|---:|---|---|---|
|
||||
| `0` | `4` | `uint32_t` | `magic` | `0x41444944` |
|
||||
| `4` | `2` | `uint16_t` | `version` | `3` |
|
||||
| `6` | `2` | `uint16_t` | `payload_size` | `136` для текущей версии |
|
||||
| `8` | `4` | `uint32_t` | `sequence` | Увеличивается при каждой упаковке |
|
||||
| `12` | `2` | `uint16_t` | `crc16` | CRC16-CCITT по payload |
|
||||
| `14` | `2` | `uint16_t` | `reserved` | `0` |
|
||||
|
||||
`magic` сравнивать как `uint32_t` little-endian. На проводе байты идут так:
|
||||
|
||||
```text
|
||||
44 49 44 41
|
||||
```
|
||||
|
||||
## CRC16
|
||||
|
||||
CRC считается только по payload, без заголовка.
|
||||
|
||||
Параметры:
|
||||
|
||||
| Параметр | Значение |
|
||||
|---|---|
|
||||
| Алгоритм | CRC16-CCITT |
|
||||
| Начальное значение | `0xFFFF` |
|
||||
| Полином | `0x1021` |
|
||||
| Reflection | нет |
|
||||
| Final XOR | нет |
|
||||
|
||||
Проверка на стороне ПК:
|
||||
|
||||
```text
|
||||
crc16_ccitt(packet[16 : 16 + payload_size]) == header.crc16
|
||||
```
|
||||
|
||||
## Payload
|
||||
|
||||
Тип: `SimulinkTelemetryPayload_t`.
|
||||
|
||||
Смещения в таблице указаны от начала payload. Чтобы получить смещение от начала
|
||||
пакета, прибавь `16`.
|
||||
|
||||
### Измерения
|
||||
|
||||
Блок `measurements`, тип `AD_Measurements_t`, размер `64` байта.
|
||||
|
||||
| Payload offset | Тип | Поле | Единицы |
|
||||
|---:|---|---|---|
|
||||
| `0` | `float` | `measurements.ia_A` | A |
|
||||
| `4` | `float` | `measurements.ib_A` | A |
|
||||
| `8` | `float` | `measurements.ic_A` | A |
|
||||
| `12` | `float` | `measurements.ia_rms_A` | A RMS |
|
||||
| `16` | `float` | `measurements.ib_rms_A` | A RMS |
|
||||
| `20` | `float` | `measurements.ic_rms_A` | A RMS |
|
||||
| `24` | `float` | `measurements.vdc_V` | V |
|
||||
| `28` | `float` | `measurements.va_V` | V |
|
||||
| `32` | `float` | `measurements.vb_V` | V |
|
||||
| `36` | `float` | `measurements.vc_V` | V |
|
||||
| `40` | `float` | `measurements.speed_rpm` | rpm |
|
||||
| `44` | `float` | `measurements.torque_Nm` | N*m |
|
||||
| `48` | `float` | `measurements.temperature_C` | град C |
|
||||
| `52` | `uint32_t` | `measurements.timestamp_us` | us |
|
||||
| `56` | `uint32_t` | `measurements.status_flags` | `AD_MEAS_STATUS_*` |
|
||||
| `60` | `float` | `measurements.slip_percent` | % |
|
||||
|
||||
`measurements.status_flags`:
|
||||
|
||||
| Бит | Маска | Флаг |
|
||||
|---:|---:|---|
|
||||
| `0` | `0x00000001` | `AD_MEAS_STATUS_OVERCURRENT` |
|
||||
| `1` | `0x00000002` | `AD_MEAS_STATUS_OVERVOLTAGE` |
|
||||
| `2` | `0x00000004` | `AD_MEAS_STATUS_UNDERVOLTAGE` |
|
||||
| `3` | `0x00000008` | `AD_MEAS_STATUS_OVERTEMPERATURE` |
|
||||
| `4` | `0x00000010` | `AD_MEAS_STATUS_DRIVER_FAULT` |
|
||||
| `5` | `0x00000020` | `AD_MEAS_STATUS_EMERGENCY_STOP` |
|
||||
|
||||
### Параметры двигателя
|
||||
|
||||
Блок `motor_parameters`, тип `AD_MotorParameters_t`, размер `60` байт.
|
||||
|
||||
| Payload offset | Тип | Поле | Единицы |
|
||||
|---:|---|---|---|
|
||||
| `64` | `float` | `motor_parameters.Rs_ohm` | Ohm |
|
||||
| `68` | `float` | `motor_parameters.Rr_ohm` | Ohm |
|
||||
| `72` | `float` | `motor_parameters.Ls_H` | H |
|
||||
| `76` | `float` | `motor_parameters.Lr_H` | H |
|
||||
| `80` | `float` | `motor_parameters.Lm_H` | H |
|
||||
| `84` | `float` | `motor_parameters.Ll_H` | H |
|
||||
| `88` | `float` | `motor_parameters.J_kg_m2` | kg*m2 |
|
||||
| `92` | `float` | `motor_parameters.B_Nm_s` | N*m*s |
|
||||
| `96` | `float` | `motor_parameters.pole_pairs` | пары полюсов |
|
||||
| `100` | `float` | `motor_parameters.nominal_voltage_V` | V |
|
||||
| `104` | `float` | `motor_parameters.nominal_current_A` | A |
|
||||
| `108` | `float` | `motor_parameters.nominal_frequency_Hz` | Hz |
|
||||
| `112` | `float` | `motor_parameters.nominal_power_W` | W |
|
||||
| `116` | `float` | `motor_parameters.nominal_speed_rpm` | rpm |
|
||||
| `120` | `uint32_t` | `motor_parameters.valid_mask` | `AD_MOTOR_PARAM_VALID_*` |
|
||||
|
||||
`valid_mask`:
|
||||
|
||||
| Бит | Маска | Флаг | Поле |
|
||||
|---:|---:|---|---|
|
||||
| `0` | `0x00000001` | `AD_MOTOR_PARAM_VALID_RS` | `Rs_ohm` |
|
||||
| `1` | `0x00000002` | `AD_MOTOR_PARAM_VALID_RR` | `Rr_ohm` |
|
||||
| `2` | `0x00000004` | `AD_MOTOR_PARAM_VALID_LS` | `Ls_H` |
|
||||
| `3` | `0x00000008` | `AD_MOTOR_PARAM_VALID_LR` | `Lr_H` |
|
||||
| `4` | `0x00000010` | `AD_MOTOR_PARAM_VALID_LM` | `Lm_H` |
|
||||
| `5` | `0x00000020` | `AD_MOTOR_PARAM_VALID_LL` | `Ll_H` |
|
||||
| `6` | `0x00000040` | `AD_MOTOR_PARAM_VALID_J` | `J_kg_m2` |
|
||||
| `7` | `0x00000080` | `AD_MOTOR_PARAM_VALID_B` | `B_Nm_s` |
|
||||
| `8` | `0x00000100` | `AD_MOTOR_PARAM_VALID_NOMINALS` | nominal fields |
|
||||
| `9` | `0x00000200` | `AD_MOTOR_PARAM_VALID_POLE_PAIRS` | `pole_pairs` |
|
||||
|
||||
Перед использованием результата идентификации обязательно проверять
|
||||
соответствующий бит `valid_mask`.
|
||||
|
||||
### Статус идентификации и команда
|
||||
|
||||
| Payload offset | Тип | Поле | Описание |
|
||||
|---:|---|---|---|
|
||||
| `124` | `uint32_t` | `param_id_status` | `AD_PARAM_ID_STATUS_*` |
|
||||
| `128` | `uint32_t` | `param_id_faults` | `AD_PARAM_ID_FAULT_*` |
|
||||
| `132` | `uint8_t` | `param_id_mode` | Текущий режим `AD_PARAM_ID_MODE_*` |
|
||||
| `133` | `uint8_t` | `command_enable` | Последняя команда enable |
|
||||
| `134` | `uint8_t` | `command_test_mode` | Последняя команда test mode |
|
||||
| `135` | `uint8_t` | `reserved` | `0` |
|
||||
|
||||
`param_id_status`:
|
||||
|
||||
| Бит | Маска | Флаг |
|
||||
|---:|---:|---|
|
||||
| `0` | `0x00000001` | `AD_PARAM_ID_STATUS_ACTIVE` |
|
||||
| `1` | `0x00000002` | `AD_PARAM_ID_STATUS_POWER_TEST_BLOCKED` |
|
||||
| `2` | `0x00000004` | `AD_PARAM_ID_STATUS_POWER_STAGE_ARMED` |
|
||||
| `3` | `0x00000008` | `AD_PARAM_ID_STATUS_FAULT_LATCHED` |
|
||||
| `4` | `0x00000010` | `AD_PARAM_ID_STATUS_TIMEOUT` |
|
||||
| `5` | `0x00000020` | `AD_PARAM_ID_STATUS_LOCKED_ROTOR_BLOCKED` |
|
||||
| `6` | `0x00000040` | `AD_PARAM_ID_STATUS_SAFETY_LIMITS_UNKNOWN` |
|
||||
| `7` | `0x00000080` | `AD_PARAM_ID_STATUS_DATA_VALID` |
|
||||
| `8` | `0x00000100` | `AD_PARAM_ID_STATUS_COMPLETE` |
|
||||
|
||||
`param_id_faults`:
|
||||
|
||||
| Бит | Маска | Флаг |
|
||||
|---:|---:|---|
|
||||
| `0` | `0x00000001` | `AD_PARAM_ID_FAULT_OVERCURRENT` |
|
||||
| `1` | `0x00000002` | `AD_PARAM_ID_FAULT_OVERVOLTAGE` |
|
||||
| `2` | `0x00000004` | `AD_PARAM_ID_FAULT_UNDERVOLTAGE` |
|
||||
| `3` | `0x00000008` | `AD_PARAM_ID_FAULT_OVERTEMPERATURE` |
|
||||
| `4` | `0x00000010` | `AD_PARAM_ID_FAULT_DRIVER` |
|
||||
| `5` | `0x00000020` | `AD_PARAM_ID_FAULT_EMERGENCY_STOP` |
|
||||
| `6` | `0x00000040` | `AD_PARAM_ID_FAULT_TIMEOUT` |
|
||||
| `7` | `0x00000080` | `AD_PARAM_ID_FAULT_NULL_INPUT` |
|
||||
|
||||
Режимы `param_id_mode` и `command_test_mode`:
|
||||
|
||||
| Значение | Режим |
|
||||
|---:|---|
|
||||
| `0` | `AD_PARAM_ID_MODE_IDLE` |
|
||||
| `1` | `AD_PARAM_ID_MODE_STATOR_RESISTANCE` |
|
||||
| `2` | `AD_PARAM_ID_MODE_NO_LOAD_MAGNETIZING` |
|
||||
| `3` | `AD_PARAM_ID_MODE_LOCKED_ROTOR_LEAKAGE` |
|
||||
| `4` | `AD_PARAM_ID_MODE_INERTIA_FRICTION` |
|
||||
| `5` | `AD_PARAM_ID_MODE_DATA_LOGGING` |
|
||||
| `6` | `AD_PARAM_ID_MODE_PWM_TEST_UH` |
|
||||
| `7` | `AD_PARAM_ID_MODE_PWM_TEST_UL` |
|
||||
| `8` | `AD_PARAM_ID_MODE_PWM_TEST_VH` |
|
||||
| `9` | `AD_PARAM_ID_MODE_PWM_TEST_VL` |
|
||||
| `10` | `AD_PARAM_ID_MODE_PWM_TEST_WH` |
|
||||
| `11` | `AD_PARAM_ID_MODE_PWM_TEST_WL` |
|
||||
| `12` | `AD_PARAM_ID_MODE_PWM_TEST_ALL` |
|
||||
| `13` | `AD_PARAM_ID_MODE_AUTO_IDENTIFICATION` |
|
||||
| `14` | `AD_PARAM_ID_MODE_ROTATION_3HZ` |
|
||||
|
||||
## USB CDC транспорт
|
||||
|
||||
USB реализован как CDC ACM устройство на USB FS:
|
||||
|
||||
| Параметр | Значение |
|
||||
|---|---|
|
||||
| Линии | `PA11 USB_DM`, `PA12 USB_DP` |
|
||||
| Тактирование | `HSI48` |
|
||||
| VID/PID | `0x0483 / 0x5740` |
|
||||
| Product string | `AD Telemetry CDC` |
|
||||
| Data IN endpoint | `0x81`, bulk, 64 байта |
|
||||
| Data OUT endpoint | `0x01`, bulk, 64 байта |
|
||||
| CMD endpoint | `0x82`, interrupt, 8 байт |
|
||||
|
||||
Код вызывает `HAL_PCD_EP_Transmit()` на весь пакет сразу, но CDC на стороне ПК
|
||||
нужно считать потоком байт. Один `read()` на ПК не обязан совпадать с одним
|
||||
пакетом прошивки.
|
||||
|
||||
Рекомендуемый парсер:
|
||||
|
||||
1. Искать в потоке magic bytes `44 49 44 41`.
|
||||
2. Дочитать 16-байтный заголовок.
|
||||
3. Проверить `version == 3`.
|
||||
4. Проверить `payload_size == 136` или обработать совместимую новую версию.
|
||||
5. Дочитать `payload_size` байт.
|
||||
6. Проверить CRC16.
|
||||
7. Передать payload в декодер.
|
||||
|
||||
## CAN/FDCAN транспорт
|
||||
|
||||
CAN реализован через FDCAN1 в режиме classic CAN, кадры по 8 байт.
|
||||
|
||||
| Параметр | Значение |
|
||||
|---|---|
|
||||
| Периферия | `FDCAN1` |
|
||||
| RX/TX | `PB8 / PB9` |
|
||||
| Frame format | Classic CAN |
|
||||
| Bit rate switch | Off |
|
||||
| Default base standard ID | `0x5A0` |
|
||||
| Payload одного CAN-кадра | до 8 байт |
|
||||
|
||||
Базовый ID задается:
|
||||
|
||||
```c
|
||||
AD_CAN_TELEMETRY_STD_ID_BASE = 0x5A0
|
||||
```
|
||||
|
||||
Полный бинарный пакет режется последовательно:
|
||||
|
||||
| CAN ID | Данные |
|
||||
|---:|---|
|
||||
| `0x5A0` | bytes `0..7` |
|
||||
| `0x5A1` | bytes `8..15` |
|
||||
| `0x5A2` | bytes `16..23` |
|
||||
| `...` | `...` |
|
||||
|
||||
Для текущего пакета `152` байта нужно `19` CAN-кадров:
|
||||
|
||||
```text
|
||||
ceil(152 / 8) = 19
|
||||
IDs: 0x5A0..0x5B2
|
||||
```
|
||||
|
||||
Последний кадр несет полный 8-байтный блок.
|
||||
|
||||
Рекомендация для приемника CAN:
|
||||
|
||||
1. Считать кадр с `base_id`.
|
||||
2. Начать буфер нового пакета.
|
||||
3. Добавлять кадры `base_id + index`.
|
||||
4. После первых 16 байт прочитать `payload_size`.
|
||||
5. Ждать `16 + payload_size` байт.
|
||||
6. Проверить `magic`, `version`, `sequence`, `crc16`.
|
||||
7. При пропуске ID или смене `sequence` сбросить сборку пакета.
|
||||
|
||||
## Включение через Modbus
|
||||
|
||||
Modbus RTU остается каналом управления.
|
||||
|
||||
| Параметр | Значение |
|
||||
|---|---|
|
||||
| UART | `USART2` |
|
||||
| TX/RX | `PA2 / PA3` |
|
||||
| Скорость | `115200` |
|
||||
| Формат | `8N1` |
|
||||
| Slave address | `1` |
|
||||
|
||||
Регистры:
|
||||
|
||||
| Адрес hex / dec | Имя | Доступ | Значение |
|
||||
|---:|---|---|---|
|
||||
| `0x001C` / `28` | `control_host_protocol` | R/W | `0` = Modbus, `1` = binary telemetry |
|
||||
| `0x001D` / `29` | `control_binary_transport` | R/W | `0` = USB, `1` = CAN, `2` = USB + CAN |
|
||||
|
||||
Пример включения USB CDC:
|
||||
|
||||
```text
|
||||
write 0x001D / 29 = 0
|
||||
write 0x001C / 28 = 1
|
||||
```
|
||||
|
||||
Пример включения CAN:
|
||||
|
||||
```text
|
||||
write 0x001D / 29 = 1
|
||||
write 0x001C / 28 = 1
|
||||
```
|
||||
|
||||
Пример одновременной отправки USB и CAN:
|
||||
|
||||
```text
|
||||
write 0x001D / 29 = 2
|
||||
write 0x001C / 28 = 1
|
||||
```
|
||||
|
||||
Остановка бинарной телеметрии:
|
||||
|
||||
```text
|
||||
write 0x001C / 28 = 0
|
||||
```
|
||||
|
||||
## Состояние транспорта в отладчике
|
||||
|
||||
Основной debug-view:
|
||||
|
||||
```c
|
||||
g_ad_debug.binary_transport
|
||||
g_ad_debug.modbus
|
||||
```
|
||||
|
||||
`g_ad_debug.binary_transport.status_flags`:
|
||||
|
||||
| Бит | Маска | Флаг |
|
||||
|---:|---:|---|
|
||||
| `0` | `0x00000001` | `AD_BINARY_TRANSPORT_STATUS_INITIALIZED` |
|
||||
| `1` | `0x00000002` | `AD_BINARY_TRANSPORT_STATUS_USB_READY` |
|
||||
| `2` | `0x00000004` | `AD_BINARY_TRANSPORT_STATUS_CAN_READY` |
|
||||
| `3` | `0x00000008` | `AD_BINARY_TRANSPORT_STATUS_USB_CONFIGURED` |
|
||||
| `4` | `0x00000010` | `AD_BINARY_TRANSPORT_STATUS_USB_TX_BUSY` |
|
||||
| `5` | `0x00000020` | `AD_BINARY_TRANSPORT_STATUS_CAN_TX_BUSY` |
|
||||
| `6` | `0x00000040` | `AD_BINARY_TRANSPORT_STATUS_LAST_DROPPED` |
|
||||
|
||||
Полезные счетчики:
|
||||
|
||||
| Поле | Значение |
|
||||
|---|---|
|
||||
| `tx_packets` | Сколько пакетов успешно поставлено хотя бы в один транспорт |
|
||||
| `usb_packets` | Сколько пакетов принято USB TX |
|
||||
| `can_packets` | Сколько пакетов принято CAN TX |
|
||||
| `dropped_packets` | Сколько пакетов сброшено из-за busy/error/size |
|
||||
| `last_size_bytes` | Последний размер пакета, сейчас должен быть `152` |
|
||||
| `last_tx_tick_ms` | `HAL_GetTick()` последней успешной постановки |
|
||||
|
||||
## API прошивки
|
||||
|
||||
```c
|
||||
void SimulinkInterface_PackTelemetry(void);
|
||||
const SimulinkTelemetryPacket_t* SimulinkInterface_GetTelemetryPacket(void);
|
||||
const uint8_t* SimulinkInterface_GetTelemetryBytes(void);
|
||||
size_t SimulinkInterface_GetTelemetrySize(void);
|
||||
|
||||
void AD_BinaryTransport_Init(void);
|
||||
void AD_BinaryTransport_Loop(void);
|
||||
uint8_t AD_BinaryTransport_SetProtocol(uint16_t protocol);
|
||||
uint8_t AD_BinaryTransport_SetTransport(uint16_t transport);
|
||||
const AD_BinaryTransportState_t* AD_BinaryTransport_GetState(void);
|
||||
```
|
||||
|
||||
## Минимальный Python-декодер CRC
|
||||
|
||||
```python
|
||||
def crc16_ccitt(data: bytes) -> int:
|
||||
crc = 0xFFFF
|
||||
for value in data:
|
||||
crc ^= value << 8
|
||||
for _ in range(8):
|
||||
if crc & 0x8000:
|
||||
crc = ((crc << 1) ^ 0x1021) & 0xFFFF
|
||||
else:
|
||||
crc = (crc << 1) & 0xFFFF
|
||||
return crc
|
||||
```
|
||||
|
||||
Поля unpack для текущей версии:
|
||||
|
||||
```python
|
||||
HEADER_FMT = "<IHHIHH"
|
||||
PAYLOAD_SIZE_V3 = 136
|
||||
PACKET_SIZE_V3 = 16 + PAYLOAD_SIZE_V3
|
||||
MAGIC = 0x41444944
|
||||
VERSION = 3
|
||||
```
|
||||
Reference in New Issue
Block a user