J'ai entrepris de rendre propre l'acquisition de valeurs analogiques de CTN (sondes de température de locaux).
Après avoir plus ou moins "débruité" les valeurs par un filtrage physique, je me suis penché sur un principe de moyenne glissante, glané çà et là.
J'en ai testé plusieurs que j'ai adaptés à ma configuration utilisant un ADS1115.
J'ai été agréablement surpris par les résultats d'un code que je vous livre :
#include "ADS1X15.h"
ADS1115 ADS(0x48); // ADS1115 physiquement défini à l'adresse 0x48
const int nbEchant = 10;
int lectures [nbEchant];
int LectIndex = 0;
long total = 0;
int valBrute = 0;
void setup() {
Serial.begin(9600);
ADS.begin();
ADS.setGain(0);
ADS.setMode(1);
ADS.setDataRate(7);
}
void loop() {
valBrute = ADS.readADC(0);
float Temp = ((Lisse()*3.3 / 17293) -0.7854) / 34.952E-3 ; // adaptation des signaux pour la zone linéaire de la CTN
Serial.print(F("lisse : ")); Serial.println(Temp);
delay(200);
}
long Lisse() { /* fonction Lisse */
//Calcul de la moyenne des lectures
long moyenne;
// soustrait la dernière lecture:
total = total - lectures[LectIndex];
// lecture de la variable brute:
lectures[LectIndex] = valBrute;
// ajoute la valeur lue au total:
total = total + lectures[LectIndex];
// incrémente l'index
LectIndex = LectIndex + 1;
if (LectIndex >= nbEchant) {
LectIndex = 0; }
// calcul de la moyenne:
moyenne = total / nbEchant;
return moyenne;
}
Mon problème est que je dois traiter 4 valeurs (pour 4 locaux) et je me refuse à écrire 4 fois le même code en dédiant chaque variable à chaque local.
J'avoue avoir du mal à écrire une fonction paramétrée pouvant traiter cela.
Le temps de traitement n'est pas un point critique et peut dépasser la seconde...
Bonsoir jpbricole,
Oui je confirme. Le code transmis a été testé sur les 4 voies successivement.
Je viens de trouver un code ressemblant mais utilisant une bibliothèque :
/*
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);
}
Sympa de ta part. Entre-temps je vais tester celui basé sur la bibliothèque runningAverage dont je viens d'adapter l'exemple à 2 capteurs pour mon besoin de 4. Le code devient très simple...
On en reparle donc,
Il faudrait créer un jeu de variables par capteur et le passer en argument à la fonction Lisse()
C'est un peu ce que fait la librairie dont tu parles. Mais elle le fait avec une classe et ses variables associées.
A ce sujet, il faut faire attention, chaque instance de la classe alloue un tableau de float de la taille passée en argument au constructeur.
Tout se joue avec des tableaux supplémentaires, je te laisse découvrir.
C'est la fonction valeurParSonde(int sondeNum) qui retourne la température de la sonde sondeNum
Comme je n'ai pas ce capteur, j'au du faire semblant avec un tableau de valeurs const int valEmul[] = {18000, 10000, 8000, 4000};
que tu pourra supprimer. J'ai aiguillé la lecture des sondes sur ce tableau:
//int valBrute = ADS.readADC(sondeNum);
int valBrute = valEmul[sondeNum];
Le programme:
#include <ADS1X15.h>
const int sondesNombre = 4; //( Sondes de 0 à 3
ADS1115 ADS(0x48); // ADS1115 physiquement défini à l'adresse 0x48
const int nbEchant = 10;
int lectures [sondesNombre] [nbEchant];
int LectIndex [sondesNombre];
long total [sondesNombre];
//int valBrute = 0;
const int valEmul[] = {18000, 10000, 8000, 4000};
void setup() {
Serial.begin(9600);
ADS.begin();
ADS.setGain(0);
ADS.setMode(1);
ADS.setDataRate(7);
}
void loop()
{
for (int s = 0; s < sondesNombre; s ++)
{
float sondeValeur = valeurParSonde(s);
Serial.println("Sonde " + String(s) + "\t" + String(sondeValeur));
}
Serial.println("");
delay(1000);
}
float valeurParSonde(int sondeNum)
{
//int valBrute = ADS.readADC(sondeNum);
int valBrute = valEmul[sondeNum];
float Temp = ((Lisse(sondeNum, valBrute)*3.3 / 17293) -0.7854) / 34.952E-3 ; // adaptation des signaux pour la zone linéaire de la CTN
return Temp;
}
long Lisse(int sondeNum, int valBrute) /* fonction Lisse */
{
//Calcul de la moyenne des lectures
long moyenne;
// soustrait la dernière lecture:
total[sondeNum] = total[sondeNum] - lectures[sondeNum][LectIndex[sondeNum]];
// lecture de la variable brute:
lectures[sondeNum][LectIndex[sondeNum]] = valBrute;
// ajoute la valeur lue au total:
total[sondeNum] = total[sondeNum] + lectures[sondeNum][LectIndex[sondeNum]];
// incrémente l'index
LectIndex[sondeNum] = LectIndex[sondeNum] + 1;
if (LectIndex[sondeNum] >= nbEchant) {
LectIndex[sondeNum] = 0; }
// calcul de la moyenne:
moyenne = total[sondeNum] / nbEchant;
return moyenne;
}
Merci, ça marche bien...
Entre-temps j'ai utilisé la bibliothèque RunningAverage qui marche bien aussi, mais un peu plus opaque. Je pense utiliser en final ta version.
Encore grand merci de la part d'un débutant en fonctions ...