Arduino - moyenne mobile glissante permanente

De Centre de Ressources Numériques - Labomedia
Aller à : navigation, rechercher

Méthode très simple pour calculer une moyenne mobile dans un code arduino

PRINCIPE GÉNÉRAL:

NombreDeValeursGlissantes = x
Ratio = x/100;
MoyenneIntantT = (ValeurLue * Ratio) + ((1-Ratio) * MoyenneIntantTInitial)

Comment calculer une moyenne mobile dans un code arduino ?.

Bonne question ! Et bien voici une façon très simple d'y arriver.

Petit rappel de ce qu'est une moyenne mobile, c'est ici: https://fr.wikipedia.org/wiki/Moyenne_glissante

Rappelons rapidement ce que nous cherchons à faire par un exemple: une tension variable qui arrive dans une fiche analogique A0, en utilisant analogRead. On veut mesurer la moyenne des données qui arrivent la fiche A0, en unités analogiques, via la fonction analogRead ( voir https://www.arduino.cc/en/Reference/analogRead).

Le manuel Arduino, en ligne, nous dit ceci à propos de analogRead: une unité analogique lue, correspond à 0.0049 volts, soit 4.9 mV par unité analogique (ce qui correspond à 5/1024, car il y a entre 0 et 1023 unités de mesures possibles, ce qui fait 1024 unités, et pas 1023 comme on peut souvent le lire). On lit aussi, que l'arduino fait 10000 mesures par seconde, et que donc, 1 mesure se fait toutes les 0.0001 secondes.

int FicheCapteur = A0; // c'est la fiche A0 que l'on mesure
int DonneeCapteeEnA0 = 0; // on met à zéro la donnée en A0, au début
const float UniteVoltEnA0 = 0.0049; // Une unité analogique, équivaut à 0.0049 volt
float VoltsEnA0 = DonneeCapteeEnA0 * UniteVoltEnA0; // L'équivalence en volt, de la mesure en analogique
float U = VoltsEnA0; // On nomme la tension U, car c'est plus élégant

On effectue la mesure du voltage dans la fiche A0, par une boucle simple de type:

void setup() {
  Serial.begin(9600);
}
void loop() {
  DonneeCapteeEnA0 = analogRead(FicheCapteur); // on mesure ce qui arrive dans la fiche 
  U; // l'arduino calcul la tension U
  Serial.println(U); // affichage dans le moniteur série de la tension U
}

Toutes les 0.0001 secondes, l'arduino fait une mesure de ce qui entre dans la fiche analogique A0 et calcule le voltage U, et l'affiche dans le moniteur série. Imaginons que cela renvoit à un moment donné, la série des 10 tensions variables suivantes:

# les données mesurées par l'arduino:
O
2
5
1
3
7
8
2
4
9

On veut calculer la moyenne de ces 10 nombres. On prend donc la somme de ces 10 chiffres, et on divise cette somme par 10. Cela signifie, que l'on accorde un poids identique à chacun de ces chiffres, dans le calcul de la moyenne. Chacun pèse pour 10% (1 chiffre) dans le calcul de la moyenne (de 10 chiffres). Alors que la somme des autres valeurs (9 chiffres) de la moyenne pèse pour 90% dans le calcul de cette moyenne (de 10 chiffres). Cela pourrait s'écrire comme ceci:

MoyenneTensionsULues= [(U0x10%)]+[somme(U1;U2;...;U10)x90%]
MoyenneIntantT = (ValeurLue * 10%) + ((1-(10/100)) * MoyenneIntantTInitial)
MoyenneIntantT = (ValeurLue * (10/100)) + ((1-(10/100)) * MoyenneIntantTInitial)

Ce qui se traduit par:

NombreDeValeurs = 10; // Nombre de chiffres pris en compte pour le calcul
Ratio = 1/NombreDeValeurs; // Poids d'une unité de chiffre, par rapport au nombre total de chiffres pris en compte pour le calcul
Uµdebut; // La valeur moyenne en début de boucle
Uµ = (Ratio * U) + ((1-Ration) * Uµdebut); // La valeur moyenne à l'instant de la valeur U mesurée
Uµ = Uµdebut; // La valeur moyenne calculée, devient la valeur moyenne de début de boucle pour la prochaine récurrence


Dès lors, le code complet ARDUINO pour calculer une moyenne mobile glissante permanente, pourrait-être celui-ci:

// FONCTION MOYENNE MOBILE GLISSANTE PERMANENTE

// Saisie des données :
const int FicheCapteur = A0; // indiquez ici quelle est la fiche mesurée
const int NombreDeValeurs = 10; // indiquez ici le nombre de chiffres pris en compte dans le calcul de la moyenne

// Laissez la suite du code tel quel -->

// Constantes et Calculs préalables versus équivalence volts et unité analogique
int DonneeCaptee = 0; // on initialise la donnée à zéro
const float UniteVoltAnalogique = 0.0049; // Une unité analogique, équivaut à 0.0049 volt
float VoltsFicheAnalogique = DonneeCaptee * UniteVoltAnalogique; // L'équivalence en volt, de la mesure en analogique

// Constantes et Calculs préalables versus calculs de la moyenne
float RatioNbVal = 1 / NombreDeValeurs; // Poids d'une unité de chiffre, par rapport au nombre total de chiffres pris en compte pour le calcul
float MoyenneDebut = 0; // La valeur moyenne en début de boucle, initialisée à zéro
float Moyenne = (RatioNbVal * VoltsFicheAnalogique) + ((1-RatioNbVal) * MoyenneDebut); // La valeur moyenne

// Initialisation du port série
void setup() {
  Serial.begin(9600);
}

// Boucle infinie
void loop() {
  DonneeCaptee = analogRead(FicheCapteur); // on mesure ce qui arrive dans la fiche 
  Moyenne; // calcul de la moyenne
  Moyenne = MoyenneDebut; // Puis, la valeur moyenne devient la valeur moyenne de début de boucle pour la prochaine récurrence
  Serial.println(Moyenne); // affichage dans le moniteur série de la moyenne
}