Lisser un signal analogique
Lors 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
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); }
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.
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é
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
Bonjour,
peut-être pouvez-vous m’éclairer sur un point, je ne comprend pas les expressions :
– i <
– indice >
(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 !
ok j’ai compris :
< correspond à =
Bonjour
Il y avait quelques problèmes d’encodage des caractères. J’ai corrigé, ça devrait être plus clair
Merci
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.
Bonjour
Il faut télécharger l’ensemble du dépôt en cliquant sur Arduino, puis Clone or download.
CF
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
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
Bonjour,
comment appliquer une moyenne provenant d’un capteur ?
merci
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 unaddValue()
.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.
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 ?
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