Optimizing ADC Performance for InlineCurrentSense on STM32 in SimpleFOC

Hello SimpleFOC Developers and Users,

I’m setting up a FOC system on an STM32F401, using analog current sense amplifiers (e.g., INA240) feeding into the STM32’s ADC. My goal is to achieve fast and accurate 12-bit current readings for the InlineCurrentSense class.

I’m aware that the default analogRead() in STM32duino environments can be slow and might default to 10-bit resolution. To get the best performance for the FOC loop, I believe a direct HAL/LL-based ADC implementation is necessary for the _readADCVoltage() and _configureADC() functions specific to STM32.

Could the community share:

  1. Whether SimpleFOC’s STM32 port already includes an optimized HAL/LL-based implementation for these ADC utility functions?

  2. If so, where can I find this implementation and any specific configuration notes?

  3. If a generic analogRead() is currently used for STM32, are there established examples or recommended strategies for users to integrate their own faster, 12-bit HAL/LL ADC routines with InlineCurrentSense? For instance, by providing custom _readADCVoltage_STM32 and _configureADC_STM32 functions?

I’m keen to ensure the current sensing part of my FOC loop is as efficient as possible.

Thank you for your help!

You can probably just use the LowsideCurrentSense class. The inline hardware doesn’t require synchronization with the PWM, but it doesn’t hurt. Inline hall effect current sensors are noisy and need oversampling, but INA240 should be clean enough to use a single sample.

If you want to write your own code anyway, read the ADC section of RM0368 https://www.st.com/resource/en/reference_manual/rm0368-stm32f401xbc-and-stm32f401xde-advanced-armbased-32bit-mcus-stmicroelectronics.pdf

And DMA as well if you want oversampling, since F401 doesn’t have hardware oversampling (have the DMA write into a circular buffer of however many samples you want, and make a custom _readADCVoltageInline that adds up the values in it).

F401’s ADC and DMA are much less complicated than G4’s, so it’s a good one to learn on.

Personally I find it easier to work with the hardware registers directly rather than the LL/HAL libraries. The register definitions are in …\packages\STMicroelectronics\hardware\stm32\2.3.0\system\Drivers\CMSIS\Device\ST\STM32F4xx\Include

At startup, you need to enable the peripherals in the RCC registers, RCC_APB2ENR |= RCC_APB2ENR_ADC1EN; and RCC_AHB1ENR |= RCC_AHB1ENR_DMA2EN; if using DMA. Or call whatever LL/HAL functions do the same thing (though I was not able to find them easily, hence why I prefer registers).

I have noticed, that the STM32F401 only got one ADC. Many other MPUs got two or more ADCs. When you use low side current sensing, you would like to sample two (or perhaps three) currents at the same time to calculate the current vector with a time stamp on it.

I do not know the implementation of the Simple FOC software. But I would expect the ADC (s) to be triggered by the same timer, that controls the PWM. It is necessary, when you use low side current sense. With in line current sense, the current should not change that much in time. But the on board transients caused by the switching of any half bridge might cause noise in the current signal. Therefore you like to synchronize the timing to the PWM timer to control that, and then more ADCs are preferable.

Hi dekutree64 and Backflip,

Thank you so much for your insightful responses and suggestions regarding ADC and encoder performance on STM32!

Your advice to look into LowsideCurrentSense for its DMA-based ADC implementation on STM32 was particularly helpful, and it seems like a great solution for using inline sensors like the INA240 efficiently.

dekutree64, your comment about the STM32G4 series (“F401’s ADC and DMA are much less complicated than G4’s, so it’s a good one to learn on”) also spurred me to look into the G4 line more closely. I was surprised to find that development boards for MCUs like the STM32G431 (with CORDIC, multiple ADCs, and built-in OpAmps) are available at very competitive prices (around $4). This makes the G4 series a very compelling option for FOC projects, potentially even for those starting out, given its dedicated hardware features.

This has significantly helped shape my understanding and component choices. I really appreciate the community’s willingness to share knowledge and experience!

I just noticed this INA240. With this device in line shunts are used and it requires very high common mode rejection of this circuit. The common mode rejection requires very precise alignment of the four resistors for the signal amplifier. I would be reluctant to trust this required alignment with temperature variations and time.

Example: You use 24 VDC and max 10 Arms in each phase. Then you like the power loss of the shunt resistors to be about 0.5 W and then they should be 5 mOhm. 1 amp then provides 5 mV signal. I think you like a disturbance from lack of common mode voltage to be below about 0.2 Amp - it is 1 mV. So the alignment of these resistors should be better than 1:24.000. However, you can chose to measure the current only, when the corresponding half bridge voltage is low (or only high). This should eliminate most of possible lack of common mode rejection. So I recommend to do that with these kinds of inline current sensors.