Temporiser une valeur de capteur

Bonjour,

Voici mon problème.

Je cherche à "temporiser la valeur reçue d'un capteur". Je m'explique.

Imaginons un LDR dans une pièce noire, lumières éteintes. Si j'allume la lumière de la pièce, la valeur de mon LDR va brutalement varier de 0 à 100 par exemple.

J'essaye de trouver un moyen de rendre ce changement plus fluide, moins brutal.

J'ai pensé à un système d'incrémentation mais je ne sais pas comment l'exprimer en code.
Par exemple :

  • La valeur de mon LDR est 0
  • La lumière s'allume, le LDR passe à 100
  • Je créé une variable qui part de 0 vers la valeur actuelle de mon capteur de façon logarithmique dans un temps donné.
    (C'est là ou je coince).

Ou peut-être y a t-il une autre façon de faire plus simple ?

Je vous remercie.

Cheerhill

Cheerhill:
... de façon logarithmique ...

Quel est l'avantage d'avoir une loi logarithmique ?

Cordialement.

Pierre

Bonjour,

Effectivement, je ne pense pas qu'une variation logarithmique soit essentiel. Elle peut tout à fait être linéaire.

Cheerhill

Hello,

J'utiliserais un système PID qui permet de gérer simplement ce genre de problématique.

voici un article clair sur le sujet : Implémenter un PID sans faire de calculs ! » Sciences et Techniques

Coyotte

Un simple intégrateur suffit :

x = 0;
tant que (x < V) faire {
  x = x+V*dt/T
  attendre le prochain incrément de temps

}

où x est la variable, V la valeur finale, dt l'incrément de temps et T la durée au bout de laquelle x vaut V.

Cordialement.

Pierre

Cheerhill:
Ou peut-être y a t-il une autre façon de faire plus simple ?

il y a une solution en faisant une moyenne tournante sur un certains nombres de mesures, la nouvelle mesure remplace la plus ancienne ... en prenant une puissance de 2 (2 4 8 16 ...) la moyenne est facile a faire (addition + décalage)

Si j'allume la lumière de la pièce, la valeur de mon LDR va brutalement varier de 0 à 100 par exemple.
J'essaye de trouver un moyen de rendre ce changement plus fluide, moins brutal.

Sans cahier des charges et un peu plus d'explications on n'y arrivera pas.

  1. le capteur a ses caractéristiques de réponse, tu ne cherche pas à les modifier. Oui/Non ?
  2. Tu veux que le résultat final passe par tous un certain nombre de niveaux intermédiaires entre mesure_1 et mesure_2 et que cela prenne un certain temps. Oui/Non ?

Si les réponses sont Oui il faut que tu définisse le nombre de niveaux intermédiaires et le temps d'établissement du nouveaux résultat de mesure. La suite sera de la programmation toute simple, une boucle for, ou while, devrait faire l'affaire.

Il y a aussi la possibilité de placer un "gros" condensateur aux bornes de la LDR mais la faisabilité dépendra du temps demandé. Défaut de la solution le temps de charge du condensateur ne sera pas constant il dépendra de la valeur résistive de la LDR.

Hello,

Je vous remercie pour vos réponses et vais essayer d'être plus clair.

J'utilise un capteur de lumière pour créer des variations avec un synthétiseur. Lorsque l'on éteint la lumière la variation est très brutale. C'est pourquoi j'aimerais la rendre plus douce.

On allume la lumière : La valeur de mon LDR passe de 0 à 100( par exemple) subitement.

J'essaye de trouver un moyen par exemple pour que cette valeur passe à 100 en une seconde en passant par toutes les valeurs entre 0 et 100.

C'est ce qu'on appelle une génération de rampe, ou comment passer progressivement d'une valeur min à une valeur max en un temps t

dans cet exemple, la variable "demarrer_rampe" et le test associé sont à remplacer par ta condition de démarrage

unsigned long t=1000;           // duree rampe
unsigned long t1;               // debut rampe
unsigned long t2;               // fin rampe
bool calcul_rampe_en_cours=false;
bool demarrer_rampe=false;
float consigne=0;

void setup() {
 

}

void loop() {
  unsigned long t_intermediaire;

  // ce test pour savoir quand on demarre
  if(demarrer_rampe) {
    t1=millis();
    t2=t1+t;
    calcul_rampe_en_cours=true;
  }

  // calcul de rampe
  if(calcul_rampe_en_cours) {
    t_intermediaire=millis();
    if(t_intermediaire>=t2) {
      calcul_rampe_en_cours=false;
    } else {
      // calcul consigne
      consigne=t/(t_intermediaire-t1);
    }
  }
}

la variable consigne contient une valeur de 0 à 1, qui est un pourcentage

Mais que vas tu faire de cette valeur ?
D'après ce que j'ai pu comprendre un faudrait un variateur 220V pour piloter la lampe

Il suffit de rajouter un condensateur en parallèle de la LDR. C'est 0 lignes de code.

Bonjour,

Merci pour vos réponses.
Alain46, La génération de rampe me semble être ce que je recherche.

Par contre, je ne comprends pas où mettre les valeurs dans ton code ?
Le temps et les variables me semblent être dissociées.

Merci.

Bonjour

Sauf erreur de ma part, la proposition d'Alain46 permet de réaliser une transition linéaire, entre une valeur initiale et une valeur finale (= consigne).

C'est le plus simple à faire, mais aux extrémités le démarrage et l'arrêt sont brutaux.

Pour bien illustrer : si je fais par exemple un parallèle avec le déplacement physique d'un objet depuis un point A vers un point B, c'est comme si ce déplacement se faisait à vitesse constante entre A et B. Là où ce n'est pas réaliste, c'est qu'au démarrage on passe instantanément d'une vitesse nulle à une vitesse constante, et inversement à l'arrivée.

Le mouvement idéal part du point A avec une vitesse nulle, accélère progressivement jusqu'au milieu de la distance, puis ralentit progressivement jusqu'à s'arrêter en B.

Si tu veux une vraie transition douce, c'est ce type de trajectoire qu'il te faut modéliser.

Mathématiquement, si on raisonne en accélération constante, la courbe temporelle est basée sur des paraboles, tangentes en milieu de trajectoire.

Mais on peut aussi utiliser une sinusoïde, peut-être plus simple à mettre en oeuvre, avec un rendu très proche.

Dans les exemples associés à ma bibliothèque simpleLedRGB.h tu trouveras un exemple de gestion de transition douce basée sur une sinusoïde, simultanément sur les trois couleurs.
C'est l'exemple 3 fondu aléatoire.

Concrêtement, il suffit d'ajouter une ligne dans le code d'Alain46

...
      consigne=t/(t_intermediaire-t1);
      consigne= 1.0 - (cos(consigne* M_PI) + 1.0)/2.0; //consigne adoucie
...

Dans la boucle d'acquisition faire :

nouvelle_valeur = analogRead(maLDR);
valeurs_actuelle = alpha * nouvelle_valeur + (1 - alpha) * valeurs_actuelle ;

alpha doit être compris entre 0 et 1. Toutes les variables sont de type float. alpha va déterminer le temps de réponse. Plus alpha sera petit plus on mettra de temps pour atteindre la valeur finale.

Hello,

Je vous remercie tous pour vos réponses.

La solution de fdufnews convient parfaitement. La formule lisse très bien les résultats obtenus et empêche les "sautes" brusques en cas de parasites ou de changement brutaux de valeurs.

Une photo du résultat de mon "poor man's oscilloscope".

Merci ! :slight_smile: