Integrating an AS5048A Absolute SPI Encoder into STM32 MCSDK for Sensored FOC and Position Control
Hello,
I have an STM32G474RE Nucleo-64 with an X-NUCLEO-IHM16M1 driving a GB2208 motor with 7 pole pairs. My goal is to use an AS5048A absolute magnetic encoder for sensored FOC and position control.
MCSDK already runs the motor correctly in sensorless mode, and I can reliably read the AS5048A. However, integrating it into MCSDK has been much less straightforward than expected.
Current implementation
I use TIM1 CH4 to trigger TIM2. TIM2 starts the AS5048A SPI transaction approximately 3 µs after the trigger. My assumption was that this provides a relatively quiet switching interval, avoids interfering with current ADC sampling, and reduces MOSFET switching noise. I am not certain whether this assumption is valid or whether encoder acquisition should instead be synchronized with a specific PWM/ADC event.
After determining the encoder direction and electrical offset, I calculate the electrical angle as:
electrical_angle = (pole_pairs * mechanical_angle + electrical_offset);I then inject the encoder-derived electrical and mechanical angles into the FOC path from:
__weak uint8_t TSK_HighFrequencyTask(void)For position control, I implemented an outer PID loop running at 500 Hz, or once every 2 ms. Its output is a speed reference sent through:
MC_ProgramSpeedRampMotor1(...)The rotor initially spins, often for multiple revolutions, and then stops with an observer/convergence or speed-feedback fault.
My current understanding is that I have replaced the angle used by FOC without replacing the State Observer + PLL feedback component. Therefore, the FOC uses the AS5048A angle while the sensorless observer still performs estimation, startup convergence, reliability checks, and fault generation. Unsurprisingly, those two feedback paths do not remain consistent. MCSDK has a generic Speed & Position Feedback componentspeed_pos_fdbk.h, while the existing implementation is specifically the State Observer + PLL component sto_pll_speed_pos_fdbk.c+1 . This suggests that overwriting angle variables inside the high-frequency task is the wrong abstraction. (This is just an opinion and maybe wrong)
Questions
-
Is my encoder sampling timing reasonable?
Is triggering the AS5048A read approximately 3 µs after TIM1 CH4 a valid way to avoid ADC acquisition and switching noise? Is there a recommended PWM event or ADC-injected-conversion completion point for triggering SPI encoder acquisition on the STM32G474? -
Must the observer be replaced completely?
For absolute-encoder FOC, should I implement a new Speed & Position Feedback component derived from MCSDK’s generic feedback interface and remove the STO-PLL from:- electrical-angle selection,
- startup convergence,
- speed calculation/reliability checks, and
- fault generation?
Or does MCSDK provide a supported configuration or existing component for SPI absolute encoders?
-
What is the cleanest integration method?
Is there a documented way to integrate a custom absolute encoder into MCSDK without modifying generated high-frequency-task code? My current approach -- overwriting angles insideTSK_HighFrequencyTask()-- feels like a hack. -
Is the outer position-control architecture valid?
Is a 500 Hz position PID producing a speed reference throughMC_ProgramSpeedRampMotor1()appropriate, or should the position controller output anIq/torque reference instead? Also, does repeatedly calling the speed-ramp API every 2 ms restart or interfere with the ramp state machine?
My MCSDK version is 6.4.2, generated with Motor Control Workbench.
I would appreciate confirmation of whether the overall architecture is valid and which MCSDK interfaces should be implemented or replaced.
