Gradateur pour LED (projet école ingénieur)

Bonjour à tous,

Je poste concernant mon projet de 3ème année en école d'ingénieur.
Je découvre à peine l'univers d'Arduino et j'utilise une Arduino Uno.

Mon projet consiste en la variation de la luminosité d'une ampoule LED dimmable via une application Android (déjà codée).

Depuis hier je suis sur la partie synchronisation secteur + gradateur (par angle de phase) et j'ai un soucis avec l'impulsion envoyé sur mon gradateur.

J'ai constaté dans un premier temps que l'ampoule ne réagissait pas comme je l'aurais souhaité. J'ai d'abord pensé à un soucis dans la programmation de l'impulsion et puis je me suis penchée sur le comparateur et j'ai l'impression que le programme ne capte pas le passage par 0 de l'onde secteur (sur l'oscillo, on voit l'onde secteur mais au lieu d'avoir l'impulsion de commande qui est fixe par rapport à cette onde, elle bouge.. et puis j'ai tenté le Serial.println(interrupt_var) avec interrupt_var qui est ma variable qui se met à 1 lors du passage par 0 de l'onde secteur, et elle vaut toujours 0...).
Je vous poste ici mon code. Vous constaterez dans le code que dans la fonction void loop, il y a des morceaux de programme en commentaire car j'ai fait pas mal de test d'envoi d'impulsions, certains avec des delay, d'autre sans, mais pas de différence...

Ce projet me tient vraiment à coeur et il me reste un mois pour le finir, et ce problème est vraiment bloquant.

Merci de votre aide.

volatile int interrupt_var=0; // Variable d'interruption (cette variable se met à 1 lorsque le comparateur détecte le passage par 0 de l'onde secteur)
int LED=12; // Sortie numérique (impulsion envoyée au gradateur)
byte impulse= HIGH;
unsigned long dateDernierChangement = 0;
unsigned long dateDernierChangementloop = 0;
int T=10; // période du signal de commande.

void setup() {
  Serial.begin(9600);
  pinMode(LED,OUTPUT);
  interrupt_var = 0;
  ADCSRB &= ~(1<<ACME);            // force le bit ACME à 0 sans modifier les autres: entrée AIN1(pin7, entrée -) sélectionnée
  ACSR = (1<<ACIE) | (1<<ACIS1);   // force les bits ACIE et ACIS1 à 1 et les autres à 0 (ACIE=1 / ACIS1=1 et ACIS0=0 : interruption activée déclenchée quand la sortie du comparateur passe à 0) 
  DIDR1 = (1<<AIN1D) | (1<<AIN0D); // force les bits AIN1D et AIN0D*/
}

ISR (ANALOG_COMP_vect){ //fonction d'interruption, Variable d'interruption (cette variable se met à 1 lorsque le comparateur détecte le passage par 0 de l'onde secteur)
   interrupt_var=1;
}


void loop() {
  int t=2; // variable comprise entre 0 et 10ms (2mc pour l'exemple) qui indique le retard de l'impulsion pa rapport à l'onde secteur 
  if (interrupt_var==1){
  impulse=LOW;
  digitalWrite(LED,impulse);
  delay(t); 
  impulse=HIGH;
  digitalWrite(LED,impulse);
  delay(T-t);
  }
 
  //ICI L'AUTRE BOUT DE CODE QUE J'AI FAIT POUR GENERER L'IMPULSION DE COMMANDE
  /*unsigned long dateCourante = millis();
  unsigned long intervalle = dateCourante - dateDernierChangement;
  if (interrupt_var==1){
    if (impulse == HIGH && intervalle > t) {
      impulse = LOW; // passage a l'état HAUT
      digitalWrite(LED, impulse);
      dateDernierChangement = dateCourante;
      }
    else if (impulse == HIGH && intervalle > 10-t) {
      impulse = LOW; //allumage de la DEL car elle est éteinte (LOW) et 980ms se sont écoulées
      digitalWrite(LED, impulse);
      dateDernierChangement = dateCourante;
      }
    }*/
  }

Bonjour,
il y a 2 images que je n'ai pas pu deviner ?

  • raccordement de l'entrée de l'arduino au secteur
  • principe adopté pour détecter le passage par 0

Bonjour,

Oui je suis désolée je n'ai pas précisé...

Alors pour détecter le passage par zéro, j'ai crée une carte électronique qui me permet de redresser la tension du secteur (j'utilise un pot de diode). J'utilise le comparateur analogique intégrée à la carte arduino et je fais rentrer cette tension redressée dans l'entrée 6 (AIN0). Sur la carte de synchronisation, je fais aussi un pont diviseur de tension que je fais rentrer dans l'entrée 7 (AIN1). Cette tension est de 0.1V. (Je vous joins une photo de la carte et de mon schéma)
Je précise qu'entre la carte et le secteur, j'ai un transfo 2x6V.

Comme vous voyez dans le code, je dis que si il y a detection du passage par 0 de l'onde secteur, je met interrupt_var à 1. Or j'ai l'impression que cette variable reste toujours à 0. J'ai testé hier un Serial.println de cette variable et elle est toujours à 0... Peut-être que cela explique tout?

Qu'entends-tu par "raccordement de l'entrée de l'arduino au secteur "?

Le signal que tu vois sur l'oscillo correspond au signal que je fais rentrer dans AIN0 (pin 6). Je l'ai abaissé à environ 5V grâce à un pont diviseur de tension.
La carte est la carte de synchronisation, avec les 2 pont diviseur et le pont de diode.
Merci de ta réponse.

Synchronisation.jpg

signal de synchro.jpg

De plus, j'aurais voulu voir le signal crée par le comparateur, je sais qu'il est en rapport avec le bit ACO (j'ai vu cela dans la doc de l'arduino) mais je ne sais pas comment le visualiser.

j'utilise un pot de diodes

Bonjour,
normalement 2 diodes suffisent :slight_smile:
cela dit le montage est correct, c'est un très bon départ

en rapport avec le bit ACO

on sort un peu des domaines habituels d'utilisation de l'arduino, donc on ne va pas trouver tout ce dont tu as besoin dans sa doc
en se référant au datasheet du microchip atmega328p, on peut voir que ce signal n'est pas directement accessible par une broche

il y a amha 3 méthodes pour le visualiser :

  • le scruter dans la boucle principale et le recopier sur une sortie, why not ...
  • déclencher une interruption à sa sortie (voir le module de l'AC), qui se charge de recopier ACO sur une broche
  • utiliser une partie du module timer1, (voir le module capture du timer1), déclencher une interruption qui se charge de recopier ACO sur une broche. Cette solution a l'air complexe, mais elle permet d'utiliser le Noise Canceler du timer1, donc d'éliminer quelques parasites mal venus dans ton application

Qu'entends-tu par domaine habituel?
J'avais posté il y a quelques mois une question en rapport avec la synchronisation du signal de commande sur le signal de secteur, on m'avait dit d'utiliser le comparateur, ce qui m'a semblé être une bonne idée.

Peux-tu m'expliquer plus en détails tes 2 premières méthodes s'il te plait? Car je ne vois pas comment procéder.

En tout cas je ne comprend pas pourquoi mon signal de commande bouge par rapport à mon signal de secteur :confused:

Je n'ai toujours pas trouvé la solution.

Au passage, le signal que je fais rentrer dans le pin 6 est un peu supérieur à 5V il me semble (voir photo). Peut-être que le soucis viens d'ici non?

C'est comme si le comparateur ne faisait pas son job....

Ou peut-être est-ce mon code qui n'est pas bon?

Pensez-vous que si j'utilise le pin2 de ma carte arduino pour déclencher une interruption à chaque detection par 0 cela réglera le soucis?
Puis-je faire entrer le signal en photo sur le pin 2 de la carte arduino?

Je ne pourrais pas faire les tests avant lundi.

Merci

Quelques remarques :

Où la variable interrupt_var est-t-elle remise à 0 ?

Les commentaires avec le code n'apportent pas d'information, voir un code similaire mieux commenté( reply #14):

http://forum.arduino.cc/index.php?topic=149840.0

Je pensais qu'elle se remettait à 0 automatiquement en fait :confused:
J'imaginais qu'elle était toujours à 0 et que lorsque la tension du secteur passait par 0 elle se mettait à 1 et se remettait à 0 ensuite.

Penses-tu que le soucis puisse venir de là ?

plus en détails tes 2 premières méthodes

  1. dans la boucle principale while(1), mettre

if ( (ACSR & (1 << ACO))== 0 ) { digitalWrite(probe, HIGH); }
else { digitalWrite(probe, LOW); }

  1. on prépare ACSR à la fin du setup
    // mettre en commentaire le rôle de chaque bit
    ACSR = 0b10001000

et dans la routine d'interruption
ISR(ANALOG_COMP_vect ) {
// mettre comme en 1)
// noter que " ACI is cleared by hardware when executing the corresponding interrupt handling vector"
}

Au passage, le signal que je fais rentrer dans le pin 6 est un peu supérieur à 5V il me semble (voir photo). Peut-être que le soucis viens d'ici non?

En tout cas ce n'est pas bon :
multiplie les résistances de ton diviseur par 100 ou place une 10k entre v6 et l'arduino

Bonjour, merci, je ferai le test demain à l'école et je reviendrai vers vous en cas de soucis :slight_smile:

Je souhaiterai savoir ce que veut dire cette ligne de code s'il vous plait : if(ACSR & (1 << ACO))

Je ne comprend pas son sens

(1 << ACO)

ACO est défini dans les fichiers de configuration écrit par ATMEL.
Ces fichiers sont cohérents avec les "termes" de la datasheet.
Ces fichiers sont obligatoires pour programmer les micro-contrôleur en C ou C++
Ils sont bien évidement inclus dans l'IDE comme bien d'autres fichiers et programmes provenant de la société ATMEL qui conçoit le microcontrôleur..
Pour un micro 328p le fichier s'appelle "iom328p.h"
On peut lire :
#define ACO 5

A ce sujet malgré que tu a 40 posts au compteur tu n'indique toujours pas le matériel que tu utilises.
Méfie toi nos boules de cristal ne sont pas fiables.

(1<<AC0) ou comme ACO vaut 5 (1<<5)
C'est ce qu'on appelle de la manipulation de bit. Certains qui parlent anglais disent du bitwase.

Tout bon tuto de C te donnera une explication claire sur la manipulation de bit et les décalages à droite ou à gauche.

Je ne suis pas un bon tuto de C, je vais faire de mon mieux :
Il faut raisonner en notation binaire.
Cela revient à décaler un bit 1 de 5 fois vers la gauche.

Bonjour, merci de ta réponse : )

J'utilise une arduino uno.

Bonjour,

J'ai enfin réussi ce que je souhaitais.
J'ai les bons signaux :slight_smile: Le seul soucis maintenant c'est que quand je branche mon ampoule au système, sa luminosité ne varie pas peu importe la commande mais j'ai ma petite idée dessus (soucis d'électronique).

En tout cas je tenais à vous remercier car depuis le début de mon projet je poste sur ce forum et j'obtiens toujours des réponses claires.
Cela me donne envie de continuer à me plonger dans l'univers d'Arduino.

Je partage mon code ici, cela pourrait servir :slight_smile:

int imp=12;

void setup() {
  Serial.begin(9600);
  pinMode(12, OUTPUT);

    ACSR  |=  (1<<ACI);    // clear Analog Comparator interrupt
    ACSR  |=
        (0<<ACD)   |         // Comparator ON
        (0<<ACBG)  |         // Disconnect 1.23V reference from AIN0 (use AIN0 and AIN1 pins)
        (1<<ACIE)  |         // Comparator Interrupt enabled
        (0<<ACIC)  |         // input capture disabled
        (1<<ACIS1) |         // set interrupt bit on rising edge
        (1<<ACIS0);          //    (ACIS1 and ACIS0 == 11)

}

ISR (ANALOG_COMP_vect){  //fonction d'interruption, Variable d'interruption (cette variable se met à 1 lorsque le comparateur détecte le passage par 0 de l'onde secteur)

}


void loop() {
       
  if ( (ACSR & (1 << ACO))== 0 ){ //if (ain1 > ain0)
    digitalWrite(imp, LOW); 
    delay(5);
    }
  
  else {
    digitalWrite(imp, HIGH); 
    }
}



  //http://www.realtechsupport.org/UB/CM/code/arduino/AnalogInterrupt/AnalogInterrupt.ino

Bonjour,
malheureusement je crains que les "ampoules led" en 230V AC ne soit pas graduables...
Impossible de les graduer avec un gradateur professionnel, de théâtre.
Les leds se graduent en basse tension, en PWM ou en courant.

Bonjour, pour mon projet je possède une LED 12v ac dimmable.
Je l'ai testé avec le gradateur d'un prof et elle fonctionne bien