STM32 - Analogread

Analogread cannot be used together with low side current sensing on STM32 because it initializes/configures/calibrates/starts/stops/deinitializes the ADC each time, which breaks the low side current sensing and makes Analogread very slow.

I have a promising fix here that could potentially be accepted by STM32DUINO, but this code is used by many STM32 chips, so I would need your feedback on different boards/chips with different use cases :pray:

with platformio, it’s easy to test it by editing the platformio.ini file.
Adding this will pick the modified STSTM32 platform:
platform_packages = framework-arduinoststm32@https://github.com/Candas1/Arduino_Core_STM32.git#analogread

Adding this will use a fork of SimpleFOC with small fixes to make analogread work:
https://github.com/Candas1/Arduino-FOC.git#analogread

Don’t use this in foc_current mode if you are not confident that the current sense is not broken.
In this example I use low side current sense and a potentiometer:

One aspect I didn’t check yet is the possibility of changing the resolution of analogRead with the analogReadResolution function, I need to test it to make sure it works for STM32DUINO, but in the case of SimpleFOC it might break the low current sensing.

[EDIT] it won’t work on the b-g431b-esc1 implementation
[EDIT2] Now changing the resolution should also work, but you need to set the resolution to 12 bits for the current sense to work properly analogReadResolution(12);

1 Like

Hehe, a big congratulations and a big thank you :slight_smile:
I don’t have anything to test on hand, no soldering iron,
and my STM32 test cards with potentiometers are at the FabLab…
I’m on vacation all next week, so I’ll test in 1 week…
But I’m sure you’ll find plenty of testers!

Hello,
I don’t have an STM32 with a potentiometer at hand.

I have just tested with the “MKS DRIVE MINI” board
to read M0_TEMP ==> PC5 & AUX_TEMP ==> PA5
the GM5208 motor works (in angle and foc_current mode)
it may vibrate a little more than without analogRead.
on the other hand, it consumes the same current all the time, 0.8 [Amp] in my case.

Add this code and your library:

#define M0_TEMP PC5
#define AUX_TEMP PA5

void setup() {
  //▬▬▬▬▬▬▬▬▬▬▬▬Temp▬▬▬▬▬▬▬▬▬▬▬▬
  pinMode(M0_TEMP, INPUT_PULLUP); // M0_TEMP PC5
  pinMode(AUX_TEMP, INPUT_PULLUP); // AUX_TEMP PA5
  analogReadResolution(12);
  ...
  }

void loop() {
  long now = millis();
  if (now - 250 > timestamp) {
    Serial1.println("analogRead M0_TEMP:" + String(analogRead(M0_TEMP)));
    Serial1.println("analogRead AUX_TEMP:" + String(analogRead(AUX_TEMP)));
    Serial1.println("");
    //analogRead(M0_TEMP); // M0_TEMP PC5 | AUX_TEMP PA5
    timestamp = now;
  }
...
  }

1 Like

Thanks !!!

Yesterday evening on the same board I noticed some glitches from times to time on the current sensing:

That could be one reason for the vibrations, it’s not happening without analogread. I need to check what is happening.

I measured analogread takes around 15us instead of 65us before depending on what channel is sampled. It’s much better but still too slow for sampling a single channel, so it should really be used for non frequent sampling, not running each loop but every 10 loop or more.

Long term solution is to create an adc class that can sample more than one channel and replace analogread for simplefoc, I started to look at how to implement it.

[EDIT] ah you are downsampling already :+1:

Some tips about analoRead on STM32DUINO.

Pin Map:
analogread sequentially scans through PinMap_ADC to find the pin’s ADC information (eg. F405).
The further the pin is in the list, the more time it takes.
You can redefine PinMap_ADC in your sketch, keeping only the analog pins you need(analoRead, current sense, MagneticSensorAnalog, …).

const PinMap PinMap_ADC = {
{PC_5, ADC1, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 15, 0)}, // ADC1_IN15
{PA_3, ADC1, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 3, 0)}, // ADC1_IN3
{PC_0, ADC1, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 10, 0)}, // ADC1_IN10
{PC_1, ADC1, STM_PIN_DATA_EXT(STM_MODE_ANALOG, GPIO_NOPULL, 0, 11, 0)}, // ADC1_IN11
};

Analogread Execution went from 17us to 14us for PA3, and from 22us to 14us for PC5 :scream:

Sampling Time:
STM32DUINO uses ADC_SAMPLINGTIME as default sampling time in analogread for pin channels, and ADC_SAMPLINGTIME_INTERNAL for internal channels (Voltage reference, internal temperature, …).
On STM32F405, ADC_SAMPLETIME_15CYCLES for pin channels, and ADC_SAMPLETIME_480CYCLES for internal channels.

By using this build flag, analogread is using the lowest sampling time, which is ADC_SAMPLETIME_3CYCLES on F405

-DADC_SAMPLINGTIME0

This only saved 0.1us, but it’s worth knowing how to change the sampling time