2025-09-01 9:33 AM - last edited on 2025-09-01 10:07 AM by Andrew Neil
I'm currently implementing very low current measurement electronics, such as Femto Amps.
To do this, I'm using the STM32G431CBU MCU. I'm acquiring the output voltages of a float voltage transimpetance amplifier, and I'm taking a running average.
My MCU is clocked by a 24 MHz quartz crystal, with the instruction frequency set to its maximum of 170 MHz.
But my function is still slow, between 24 µs and 50 µs.
float MoyenneGlissante(float valeurI, uint8_t MeanMoving)
{
static float buffer[50] = {0}; // capacité max : 50 échantillons
static uint8_t index = 0;
static uint8_t rempli = 0;
// Protection : on limite MeanMoving au max du buffer
if (MeanMoving > 50) MeanMoving = 50;
// Stocke la nouvelle valeur dans le buffer circulaire
buffer[index] = valeurI;
index = (index + 1) % MeanMoving;
// Marqueur pour savoir si le buffer est rempli au moins une fois
if (rempli < MeanMoving) rempli++;
// Calcul de la moyenne glissante
float somme = 0;
for (uint8_t i = 0; i < rempli; i++) {
somme = somme + buffer[i];
}
return somme / rempli;
// return valeurI;
}
How can I significantly reduce the processing time for this function?
Thank you for your help.
2025-09-01 9:41 AM
Your moving average has to do 50 float additions for every new sample, even though you know you have only changed one value in the buffer. This is slow.
If you remember the total of all 50 values between calls, then update one value, all you need do is change the total by (newValue - oldValue).
2025-09-01 9:48 AM
Thanks for your quick response.
Yes, you're right, that's what the next step is.
float MoyenneGlissante(float valeurI, uint8_t MeanMoving)
{
static float buffer[50] = {0}; // capacité max : 50 échantillons
static uint8_t index = 0;
static uint8_t rempli = 0;
// Protection : on limite MeanMoving au max du buffer
if (MeanMoving > 50) MeanMoving = 50;
// Stocke la nouvelle valeur dans le buffer circulaire
buffer[index] = valeurI;
index = (index + 1) % MeanMoving;
// Marqueur pour savoir si le buffer est rempli au moins une fois
if (rempli < MeanMoving) rempli++;
// Calcul de la moyenne glissante
float somme = 0;
for (uint8_t i = 0; i < rempli; i++) {
somme = somme + buffer[i];
}
return somme / rempli;
// return valeurI;
}
But still, too slow...
2025-09-01 9:58 AM
Oops, sorry, it's this one.
float MoyenneGlissante(float valeurI, uint8_t MeanMoving)
{
static float buffertest[50] = {0}; // capacité max : 50 échantillons
static uint8_t indextest = 0;
static uint8_t remplitest = 0;
static float somme = 0; // somme cumulative
// Protection : on limite MeanMoving au max du buffer
if (MeanMoving > 50) MeanMoving = 50;
// Retire l’ancienne valeur du buffer de la somme
somme -= buffertest[indextest];
// Stocke la nouvelle valeur
buffertest[indextest] = valeurI;
// Ajoute la nouvelle valeur à la somme
somme += valeurI;
// Avance l’index circulaire
indextest = (indextest + 1) % MeanMoving;
// Incrémente jusqu’à ce que le buffer soit rempli
if (remplitest < MeanMoving) remplitest++;
// Retourne la moyenne glissante
return somme / remplitest;
}
2025-09-01 10:02 AM - edited 2025-09-01 10:02 AM
Your code hasn't changed... Saving the sum as @Danish1 recommends will dramatically speed things up. However, since you are using floats, the math is not exact and you'll eventually have some error in the calculation. It would be better to reconfigure things and save integer values instead, if possible.
Otherwise, storing data in CCMRAM will improve speed a little as will executing from RAM.
Seems like the code only works if MeanMoving is constant. I'd remove it as a variable and keep it fixed.
2025-09-01 10:28 AM
Try
return somme / (float)remplitest;