Lisser un signal analogique

MoyenneGlissante_exLors de l’acquisition d’un signal analogique en provenance d’un capteur, les valeurs sont souvent très fluctuantes, et ces fluctuations ne sont pas toujours significatives : ce sont des bruits, des parasites, des vibrations, voire des erreurs de mesure ou de communication …

Afin de garantir la stabilité du système il est alors nécessaire de lisser ces valeurs.

Différentes méthodes de lissage peuvent être employées …

Moyenne glissante

Principe

MoyenneGlissante

Moyenne glissante sur 4 valeurs consécutives d’une série

C’est une moyenne calculée tour à tour sur N valeurs consécutives d’une série de valeurs : pour chaque échantillon de mesure, on calcul la moyenne des N-1 échantillons précédents et de l’échantillon courant :

 

 

 

 

 

Programme

Sans bibliothèque :

/*
  Lissage : moyenne glissante
  source : http://www.arduino.cc/en/Tutorial/Smoothing
*/


// Définition du nombre d'échantillons
// pour le calcul de la moyenne glissante
const int nEchantillons = 20;

int echantillon[nEchantillons];    // un tableau pour stocker les échantillons lus
int indice = 0;                    // l'indice de l'échantillon courant
float total = 0;                   // la somme des échantillons mémorisés
float moyenne = 0;                 // la moyenne des échantillons mémorisés

int inputPin = A0;

void setup() {
  // Initialisation du port série
  Serial.begin(9600);
  // On remplit le tableau d'échantillons avec des 0
  for (int i = 0; i < nEchantillons; i++) {
    echantillon[i] = 0;
  }
}

void loop() {
  // Soustraction de l'echantillon précédent
  total = total - echantillon[indice];
  
  // Lecture du capteur
  echantillon[indice] = analogRead(inputPin);
  Serial.print(echantillon[indice]);
  
  // Ajout du dernier echantillon
  total = total + echantillon[indice];
  
  // Incrémentation de l'indice
  indice++;
  // si on est à la fin du tableau ...
  if (indice >= nEchantillons) {
    // ...retour au début
    indice = 0;
  }

  // calcul de la moyenne
  moyenne = total / nEchantillons;


  Serial.print(",");
  Serial.println(moyenne);
  delay(1);
}

Source : http://www.arduino.cc/en/Tutorial/Smoothing

Avec la bibliothèque RunningAverage :

/*
  Lissage : moyenne glissante
  source : https://github.com/RobTillaart/Arduino/tree/master/libraries/RunningAverage
*/

#include "RunningAverage.h"

RunningAverage MoyGliss(20);  // objet "Moyenne Glissante" avec nombre d'échantillons pour le calcul
int compteur = 0;             // un compteur d'échantillons
float moyenne = 0;            // la moyenne glissante des échantillons

int inputPin = A0;

void setup(void) 
{
  // Initialisation du port série
  Serial.begin(9600);
  // Initialisation de l'objet "Moyenne Glissante"
  MoyGliss.clear();
}

void loop(void) 
{
  // Lecture du capteur
  int echantillon = analogRead(inputPin);
  
  // Ajout de l'échantillon à l'objet "Moyenne Glissante"
  MoyGliss.addValue(echantillon);
  
  // Récupération de la moyenne glissante
  moyenne = MoyGliss.getAverage();
  
  // Affichage des résultats
  Serial.print(echantillon);
  Serial.print(",");
  Serial.println(moyenne);
  
  // Incrémentation du compteur
  compteur++;
  // Effacement de l'historique pour éviter les débordements
  if (compteur == 300)
  {
    compteur = 0;
    MoyGliss.clear();
  }
  
  delay(1);
}

 

 

Vous aimerez aussi...

15 réponses

  1. Buxi dit :

    Merci beaucoup pour cet article, vraiment !
    J’utilise un arduino DUE avec lequel j’ai construit un instrument de musique, cet article m’a permis de résoudre un problème et d’améliorer considérablement mon invention.

  2. André dit :

    Bonjour
    Merci beaucoup pour ces codes sur les moyennes glissantes. C’est un plaisir et d’utiliser les solutions des problèmes déjà résolus, c’est avantageux, simple et efficace mais pouvez vous me conseiller un code économique en mémoires pour lisser en simultané les mesures d’une dizaine de capteurs et les traiter pour commander des actionneurs. Si possible sans faire chauffer Arduino Mega 2560
    Cordialement

    André

    • cfaury dit :

      Bonjour
      Je n’ai pas testé, mais je pense qu’avec la bibliothèque RunningAverage (2ème partie de l’article) il est possible de créer autant d’objets RunningAverage que l’on souhaite… reste à savoir si ça fait chauffer un Mega…
      Cordialement

  3. Edmon dit :

    Bonjour,

    peut-être pouvez-vous m’éclairer sur un point, je ne comprend pas les expressions :
    – i &lt
    – indice &gt

    (et d’ailleurs l’IDE non plus :  »
    error: ‘i’ was not declared in this scope

    for (int i = 0; i & lt; nEchantillons; i++) {

    ^

    C:\Users\Edmon\AppData\Local\Temp\arduino_modified_sketch_802396\sketch_dec26b.ino: In function ‘void loop()’:

    sketch_dec26b:41: error: ‘gt’ was not declared in this scope

    if (indice >= nEchantillons) {

    ^

    sketch_dec26b:41: error: expected ‘)’ before ‘;’ token

    if (indice >= nEchantillons) {

    ^

    sketch_dec26b:41: error: expected primary-expression before ‘=’ token

    if (indice >= nEchantillons) {

    ^

    exit status 1
    ‘lt’ was not declared in this scope
    « )

    Merci !

  4. Samuel dit :

    Bonjour, je n’arrive pas à avoir la bibli RunningAverage, sur le site github il n’y a pas le bouton pour la télécharger.

  5. Romain B dit :

    Bonjour,
    Pour quoi est-ce que la valeur du compteur ne doit pas dépasser 300 à la deuxième méthode ?
    Comment est-ce qu’on connait cette valeur anti-débordement ?

    Merci pour votre article

    • cfaury dit :

      Bonjour
      300 est la valeur utilisée dans l’exemple de base fourni avec la bibliothèque.
      On peut tout à fait la modifier, voire s’en passer totalement … il faut adapter ce type de lissage au signal que l’on veut traiter.
      A expérimenter donc.
      CF

  6. Sloan dit :

    Bonjour,
    comment appliquer une moyenne provenant d’un capteur ?
    merci

    • cfaury dit :

      Bonjour
      Les exemples donnés s’appliquent parfaitement au lissage de données en provenance de capteurs analogiques (instructions analogRead() ).
      Pour les capteurs numériques, il suffit d’ajouter les valeurs acquises « dans » l’objet RunningAverage avec un addValue().

  7. Clemzo dit :

    Bonjour et merci pour ce bout de code qui m’a permis de lisser les mesures d’un capteur US SR04 et fiabiliser ainsi les résultats obtenus.

  8. Chaillou dit :

    Bonjour,

    Je suis à la recherche d’un « système » permettant de filtrer un signal analogique 0..10V ou 4..20mA d’un capteur de pression. La mesure du capteur n’étant pas stable j’aimerai donc une moyenne des mesures. Est-il possible avec cette carte de brancher directement le capteur dessus et de récupérer un signal 0..10V traité en sortie de carte ?

    • cfaury dit :

      Bonjour
      Le convertisseur Analogique/Numérique de l’Arduino n’accepte des tensions que dans l’intervalle 0-5V.
      La solution la plus simple serait d’utiliser un pont diviseur de tension.
      La plus compliquée serait d’acheter un convertisseur « externe » à l’Arduino
      CF

Répondre à cfaury Annuler la réponse

Votre adresse e-mail ne sera pas publiée. Les champs obligatoires sont indiqués avec *