cancel
Showing results for 
Search instead for 
Did you mean: 

How to speed up function execution?

LIFER.1
Associate II

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;

}

clk.jpg

How can I significantly reduce the processing time for this function?

Thank you for your help.

5 REPLIES 5
Danish1
Lead III

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).

LIFER.1
Associate II

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...

LIFER.1
Associate II

 

 

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;
}

 

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.

If you feel a post has answered your question, please click "Accept as Solution".

Try

return somme / (float)remplitest;