Asservissement du niveau de luminosité d'une LED

Bonjour à tous !

Je travaille sur un petit projet qui est un challenge personnel. Je cherche à asservir le niveau de luminosité d'une led. Pour info, je connais plutôt bien la théorie et la simulation des asservissements mais c'est la première fois que j'en implémente sur microcontrôleur et j'éprouve quelques difficultés.
Je possède un asservissement comprenant un PID et un feedback par capteur (une photorésistance).

J'ai réalisé un code utilisant les équations de base du PID et je n'ai pas utilisé PID_v1.h dans un soucis d'apprentissage du fonctionnement. La consigne est un niveau de luminosité acquis par le capteur.

J'ai donc ce code :

int data = 0 ;
int consigne = 600 ;
int erreur = 0 ;
int somme_erreur = 0 ;
int delta_erreur = 0 ;
int erreur_precedente = consigne ;
int cmd = 0 ;

double Kp = 0.005 ;
double Ki = 1.0 ;
double Kd = 0.012 ;

void setup()
{
  Serial.begin(9600) ;

  pinMode(A0,INPUT) ;
  pinMode(3,OUTPUT) ;

  delay(100) ;
}

void loop()
{
  data = analogRead(A0) ;

  Serial.print(data) ;
  Serial.print(",") ;
  Serial.print(consigne) ;
  Serial.println() ;

  erreur = consigne - data ;
  somme_erreur = somme_erreur + erreur ;
  delta_erreur = erreur - erreur_precedente ; 
  erreur_precedente = erreur ;

  cmd = Kp * erreur + Ki * somme_erreur + Kd * delta_erreur ;

  analogWrite(3,cmd);
  delay(1) ;
}

Le réglage du PID est empirique pour le moment mais je compte utiliser une méthode de réglage par la suite (Ziegler, Broida, etc.). Je n'ai pas simulé ni identifié sur ce projet.

L'objectif est d'atteindre une réponse stable et proche de la consigne mais je n'y arrive pas (voir traceur), j'ai pourtant modifié les différents gains du PID mais je n'obtiens rien de satisfaisant.

Je vous mets quelques schémas et images pour mieux comprendre le projet.

Auriez-vous des idées de problèmes sur mon code ou sur le projet en général ? Je commence à être à court d'idées. Je vous remercie d'avance ! :smiley:

Guillaume

  • le premier souci c’est que votre capteur n’a pas de persistance rétinienne et le PWM alterne rapidement des états ou la LED est éteinte (0V) et où la LED est allumée (5V) donc suivant la vitesse de la loop() votre LDR va voir 0 ou 1023 (ou une valeur max qui dépend de ce qu’elle capte)… il vous faudrait mesurer le PWM réel dans votre boucle de rétro-action

  • d’autre part, puisque vous êtes sur UNO, les int sont limités pour les calculs (2 octets signés). Essayez de passer vos variables en long (voire tout en double)

Bonjour,

Merci de votre retour rapide ! Donc, si je comprends bien, le PWM n'est pas un bon moyen de commande car ma photorésistance voit simplement des fronts à 0V et 5V (0 et 1023) ? La luminosité apparente (à l'œil) de la led ne serait donc pas réelle ?

Je ne comprends pas bien, il s'agit juste de gagner en résolution sur les calculs en passant les int en double ? C'est vrai que cela rendrait l'asservissement plus précis.

car ma photorésistance voit simplement des fronts à 0V et 5V

Je ne pense pas. Tout dépend de la LDR. Une GL5528 par exemple a un temps de réponse de 20 à 30ms.
Donc c'est lent ...

Je viens de faire un essai en boucle ouverte en fixant le PWM à 100 et en réalisant une acquisition sur la LDR et je retrouve une réponse assez fluctuante...

void loop()
{
  data = analogRead(A0) ;
 
  Serial.print(data) ;
  Serial.print(",") ;
  Serial.print(consigne) ;
  Serial.println() ;

  analogWrite(3,100);
}

Il semblerait que soit le capteur n'est pas stable, soit effectivement je suis assez rapide pour détecter les pulses du PWM malgré le fait que j'ai une LDR classique.

Guillaume36:
Je viens de faire un essai en boucle ouverte en fixant le PWM à 100 et en réalisant une acquisition sur la LDR et je retrouve une réponse assez fluctuante...

void loop()

{
 data = analogRead(A0) ;

Serial.print(data) ;
 Serial.print(",") ;
 Serial.print(consigne) ;
 Serial.println() ;

analogWrite(3,100);
}



Il semblerait que soit le capteur n'est pas stable, soit effectivement je suis assez rapide pour détecter les pulses du PWM malgré le fait que j'ai une LDR classique. 

![boucle_ouverte.PNG|1213x533](upload://3VnP9Prw6Lw5g6aMIL1NVWWFv0v.png)

bonjour
attention aux conditions de la manip (eclairage LDR)
une LDR par exemple detecte le 50Hz d'un eclairage secteur
le temps de reponse d'une LDR est toujours plus petit que son temps de relaxion

La luminosité apparente (à l'œil) de la led ne serait donc pas réelle ?

non elle clignote sur une certaine période donnée avec un temps ON plus ou moins long en fonction de la valeur de PWM.

Effectivement la LDR est lente mais je ne suis pas assez calé sur son fonctionnement pour dire si elle retournera une sorte de valeur moyenne

@guillaume, on voit une certaine régularité sur votre capture mais ça reste une oscillation

essayez votre test avec Serial.begin(2000000); et le traceur série aussi à 2 millions de bauds pour voir si ca change la courbe.

Essayez aussi juste avec la lumière ambiante, led éteinte

Bonjour

EDIT: je réalise que ma réponse fait doublon avec celles plus haut de hbachetti et Artouste

Les photorésistances (pas évident de trouver leur notice technique !) ont des constantes de temps de plusieurs dizaines de millisecondes avec en général des valeleurs différentes pour la transition éclairement--> obscurité et obscurité->éclairement

En voici une particulièrement dissymétrique dans sa réaction :
[https://components101.com/sites/default/files/component_datasheet/LDR%20Datasheet.pdf](https://components101.com/sites/default/files/component_datasheet/LDR Datasheet.pdf)

Salut
C’est le temps de réaction à un front montant ou descendant avec la valeur conservée ensuite pendant suffisamment longtemps

mais concrètement comment cela se traduit si la durée du signal après un front n’est pas assez longue pour atteindre une sorte de stabilité? La valeur lue est elle significative ou indéfinie ?

Si on ne laisse pas le temps au matériau d'atteindre son équilibre sa résistance prend une valeur intérmédiaire définissable si on caractérise l'évolution.
Il me semble que vu de l'extérieur, en faisant abstraction des phénomèmes physiques mis en jeu, on peut à première vue assimiler dans un asservissement une photorésistance a un système du premier ordre.

Merci à tous pour vos réponses vraiment intéressantes.

J'ai donc effectué 4 essais :

Le premier : j'ai réalisé un essai en boucle ouverte avec PWM100 à 9600 bauds et l'éclairage coupé. Je trouve des oscillations donc j'imagine que le problème ne vient pas du 50Hz du secteur.

Le deuxième : c'est le même essai mais à 2Mbauds et je trouve encore des oscillations.

Le troisième : Il s'agit d'un essai led éteinte mais éclairage allumé à 2 Mbauds. On trouve des oscillations donc je pense pouvoir enlever la piste du 50 Hz.

Le dernier : j'ai alimenté la led avec le 3,3 V de la carte et je vois que les oscillations ont disparus.

Je pense que le PWM est responsable de l'oscillation. Qu'en pensez-vous ?

La vitesse de Serial n'a rien à voir avec la vitesse du PWM. Pour les broches en PWM associé au timer 0, comme celui ci sert pour l'horloge et bat le 1024µs, sa fréquence est fixe et si on y touche on touche aussi à delay.Pour la fréquence du PWM, une fréquence basse est bien pour les moteurs, une haute pour les leds, 1000Hz bien pour l'horloge, et c'est ce qui est pris.

Je n'ai pas vu de quelle carte il s'agissait, mais si le PWM ne dépend pas du timer 0, il est extrêmement facile (pour moi) de changer la fréquence. Comme la diode est en direct, on peut travailler en fréquence élevée. Augmenter la fréquence ne monopolise pas le micro car c'est une fonction Hard. autant ne pas s'en priver (y en a qui donnent ce conseil et qui ont un éclairage de cuisine basse fréquence à LED!).

La vitesse de Serial n'a rien à voir avec la vitesse du PWM

oui
Ma suggestion de passer à 2Mbauds c’était parce qu’à 9600 bauds le buffer de sortie va vite saturer et le print devenir bloquant donc on ne lisait pas de manière régulière l’entrée analogique

C'est suite à:

j'ai réalisé un essai en boucle ouverte avec PWM100 à 9600 bauds

Oui mais en #1 Il montre un UNO avec le port série à 9600 bauds. C’est pour cela qu’en #6 j’ai proposé de passer à 2M. Il ne faisait que répondre à ma demande je pense.

Oui, effectivement, je répondais à votre demande pour les 2Mbauds.

Après de nombreux essais, il semblerait que le problème vient du fait que ma photorésistance est assez rapide pour capter les pulses de la led pilotée en PWM. J'ai pensé à filtrer le PWM avec un filtre passe-bas (un RC) et à appliquer ce signal sur la led, qu'en pensez-vous ?

Moi je mettrais un vrai DAC pour avoir une vraie tension plutôt que de bricoler. Certains arduino comme l’Arduino Due, la famille des MKR ou le Zéro en ont un directement sur la carte ou vous pouvez en fabriquer un assez simplement avec un amplificateur opérationnel (rail to rail), une resistance et un condensateur

Ou un module DAC MCP4725 (12 bits).

2 DAC 8bits en sortie des ESP32

Le montage est fait, le code est fait, je pense qu'il faut insérer un filtre RC avant d'aller chercher un DAC.

La fréquence de la PWM peut se changer en modifiant les réglages du timer concerné.
On peut aller jusqu'à environ 64 kHz ce qui simplifie le filtrage.

Il y a 3 timers on peut choisir ses pins (1 timer peut piloter 2 pins en PWM) et il n'est nullement interdit de modifier le timer 0.
Simplement il ne faut pas oublier que si l'on touche au timer 0 les fonctions de temps seront fausses mais d'une quantité parfaitement prévisible.