Filtrage numérique de CTN à multiplier

Bonsoir à tous,

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

Quelqu'un pourrait-il m'aider ?

Bonsoir jackjean

Je suis comme toi :wink:
Dès qu'une chose se répète, je fais une fonction.

Tu as 4 locaux, ça veut dire que:
Local 1 = ADS.readADC(0);
Local 2 = ADS.readADC(1);
Local 3 = ADS.readADC(2);
Local 5 = ADS.readADC(3);

J'ai juste?

A+
Cordialement
jpbbricole

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

Bonsoir jackjean

Demain, si tu le désires, je peux adapter ton programme aux 4 mesures.

Bonne soirée
jpbbricole

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.

1 Like

Bonjour jackjean
Voilà, j'ai "bricolé" ton sketch :wink:

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

A+
Cordialement
jpbbricole

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

Bonsoir jackjean

Tu verra, les fonctions vont vite te devenir indispensables :wink:

Bonne continuation
Cordialement
jpbbricole

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.