Auteur Sujet: analogWrite qui ne fonctionne pas toujours correctement avec des LEDs  (Lu 6250 fois)

hinano70

  • Newbie
  • *
  • Messages: 18
    • Voir le profil
Bonjour
Ceci est mon 1er message, j'espère ne pas me tromper de lieu pour ma demande !
Sur les bons conseils de Locoduino, j'ai réalisé une commande de passage à niveau (capteurs IR pour la détection, SG90 pour les barrières, LEDs pour les feux clignotants). Tout fonctionne correctement pour les leds en tout ou rien (0 et 255 dans analogWrite)
Je me suis inspiré de l'article "La PWM : Qu’est-ce que c’est ?" pour faire un clignotement progressif. Débutant, j'ai adapté le programme au mien. Seul, il fonctionne très bien :

byte cycle = 0;  // cycles de clignotement
long fading = 5;  //rapidité du clignotement
byte intensite = 0;  //intensité lumineuse
long LedTime = millis();   // timer pour le clignotement

void setup() {
pinMode(10, OUTPUT);  //sortie Led
}

void loop() {
clignote();
}

void clignote()
{
if ( millis() > LedTime + fading)     // vitesse de clignotement
   {
   LedTime = millis();   // reinit le timer
 

   switch (cycle) {
           case 0 :       // croit
              intensite += 10;
              if (intensite == 250) {cycle = 1; fading=200;}
              break;
           case 1 :      // allumé
              cycle = 2; fading=5;
              break;
           case 2 :      // décroit
              intensite -= 10;
              if (intensite == 0) {cycle = 3; fading=200;} break;
           case 3 :      // éteint
              cycle = 0;
              fading=5;
              break;
                }
analogWrite(10,intensite);
   }
}


Si j'intègre cet ensemble dans mon programme (ci-dessous), la Led ne s'éclaire pas. Elle ne le fait que si l'intensite est à 255 ! (254 ne fonctionne pas !!!)
Je tourne en rond, donc si qq'un peut m'aider. Merci. Je suis sur Nano.

#include <Servo.h>
/* define a header file. Special attention here, you can call the servo function directly from Arduino's software menu  bar Sketch>Importlibrary>Servo, or input
#include <Servo.h>. Make sure there is a space between #include and  <Servo.h>. Otherwise, it will cause compile error.*/
Servo servoPNA; // servo voie A
Servo servoPNB; // servo voie B
boolean detect1A,detect1B;
boolean  olddetect1A,olddetect1B;
boolean detect2A,detect2B=1;
boolean  olddetect2A,olddetect2B=1;
boolean  lastdetect2A,lastdetect2B=1;
boolean readingPNA,readingPNB;
long lastPNATime,lastPNBTime;   // derniere fois que le detecteur a change
long PNDelay = 500; // durée maxi des micro-coupures
int avertissement = 2000; // durée avant fermeture
byte cycle = 0;  // cycles de clignotement
long fading = 10;
byte intensite = 0;
long LedTime = millis();                   // timer pour le clignotement
long PNTime = millis();                    // timer pour les moteurs d'aiguillage
boolean  ferme=0,fermeA=0,fermeB=0;
byte angleA=140;

void setup()
{
servoPNA.attach(5);// servo A
servoPNB.attach(6);// servo A
//Serial.begin(9600);
pinMode(2,INPUT); //entrée A
pinMode(3,INPUT); //sortie A
pinMode(7,INPUT); //entrée B
pinMode(8,INPUT); //sortie B
pinMode(10, OUTPUT);
pinMode(11, OUTPUT);
servoPNA.write(140);
servoPNB.write(140);

analogWrite(10,0);// Led A
analogWrite(11,0);// Led B
}
void loop()
{

detect1A=digitalRead(2); //reading=0 si train
if ((olddetect1A==1 && detect1A==0) && fermeA==0) {fermeA=1; if (fermeB==0) {PNTime = millis()+avertissement; LedTime = millis();} }  // ferme voie A
olddetect1A=detect1A;

readingPNA = digitalRead(3); //reading=0 si train
if (readingPNA != lastdetect2A) {lastPNATime = millis();}  //déclenchement chrono
if ((millis() - lastPNATime) > PNDelay) {// si le delai est atteint, le changement est valide sinon le changement est ignore (parasite ou inter-wagon)
                                        if (readingPNA != detect2A) {detect2A = readingPNA;} // changement valide                                                       
                                        }

lastdetect2A=readingPNA;
if (olddetect2A==0 && detect2A==1) {fermeA=0; lastPNATime = millis();}  // ouvre voie A
olddetect2A=detect2A;


detect1B=digitalRead(7);
if ((olddetect1B==1 && detect1B==0) && fermeB==0) {fermeB=1; if (fermeA==0) {PNTime = millis()+avertissement; LedTime = millis();} }  // ferme voie B
olddetect1B=detect1B;

readingPNB = digitalRead(8); //reading=0 si train
if (readingPNB != lastdetect2B) {lastPNBTime = millis();}  //déclenchement chrono
if ((millis() - lastPNBTime) > PNDelay) {// si le delai est atteint, le changement est valide sinon le changement est ignore (parasite ou inter-wagon)
                                        if (readingPNB != detect2B) {detect2B = readingPNB;} // changement valide                                                       
                                        }

lastdetect2B=readingPNB;
if (olddetect2B==0 && detect2B==1) {fermeB=0; lastPNBTime = millis();}  // ouvre voie B
olddetect2B=detect2B;

ferme = (fermeA || fermeB);

if ((ferme==1) || (angleA<140)) { clignote();}
else {Serial.println("ouvert");analogWrite(10,0); analogWrite(11,0);cycle = 0; intensite=0; fading = 5;}


if ((ferme==1) && (angleA>50)) {fermePN();}

if ((ferme==0) && (angleA<140)) {ouvrePN();}

//Serial.println(angleA);
}


void clignote()
{

//Serial.println(intensite);
if ( millis() > LedTime + fading)     // vitesse de clignotement
   {
   LedTime = millis();   // reinit le timer
 

   switch (cycle) {
           case 0 :       // croit
              intensite += 10;
              if (intensite == 250) {cycle = 1; fading = 200;}
              break;
           case 1 :      // allume
              cycle = 2; fading=5;
              break;
           case 2 :      // decroit
              intensite -= 10;
              if (intensite == 0) {cycle = 3; fading = 200;} break;
           case 3 :      // eteint
              cycle = 0;
              fading = 5;
              break;
                }
   analogWrite(10,intensite);
   }
}

void ouvrePN()
{
             if ((millis() - PNTime) > 20) {PNTime = millis(); angleA+=1; servoPNA.write(angleA); servoPNB.write(angleA); }
}

void fermePN()
{
             if (millis() > (20+PNTime)) {PNTime = millis(); angleA-=1; servoPNA.write(angleA); servoPNB.write(angleA);  }
}
« Modifié: septembre 20, 2020, 11:26:06 pm par hinano70 »

msport

  • Global Moderator
  • Hero Member
  • *****
  • Messages: 2218
  • HO avec DCC++ en DIY Réseaux très éphémères
    • Voir le profil
Re : analogWrite qui ne fonctionne pas toujours correctement avec des LEDs
« Réponse #1 le: septembre 20, 2020, 10:22:22 pm »
Bonsoir et bienvenue à Locoduino,
pouvez-vous modifier votre message en mettant les balises codes  ( " # " ci dessus ) autour du code pour éviter d'y glisser des smileys.
Cordialement

hinano70

  • Newbie
  • *
  • Messages: 18
    • Voir le profil
Re : analogWrite qui ne fonctionne pas toujours correctement avec des LEDs
« Réponse #2 le: septembre 20, 2020, 11:27:50 pm »
Désolé, je découvre ....

simontpellier

  • Full Member
  • ***
  • Messages: 115
    • Voir le profil
Re : analogWrite qui ne fonctionne pas toujours correctement avec des LEDs
« Réponse #3 le: septembre 21, 2020, 09:04:32 am »
bonjour,

Entrer dans le code d'autrui demande un sacré effort! En coup d'œil rapide, le problème ne se voit pas (d'autant moins que l'écriture est compactée à l'horizontale!) mais...

il est possible, ça arrive!, que les surprises ne viennent pas du code. Par exemple, qu'est ce qui est branché sur les input 2,3,7,8 ? des poussoirs? des détecteurs ? de quel type ? Dans tous les cas, une entrée aime généralement être fixée sur son sort par un pullup (de préférence). A voir peut-être?
(Une autre remarque d'ordre général en passant : les variables de temps ont tout intérêt à être déclarées en "unsigned long")
Bon courage, ça va marcher

Thierry

  • Global Moderator
  • Hero Member
  • *****
  • Messages: 744
    • Voir le profil
Re : analogWrite qui ne fonctionne pas toujours correctement avec des LEDs
« Réponse #4 le: septembre 21, 2020, 10:07:37 am »
La première chose à faire serait d'ajouter un Serial.println de la valeur envoyée à chaque analogWrite pour vérifier que toutes les étapes sont bien réalisées...

chris_bzg

  • Global Moderator
  • Sr. Member
  • *****
  • Messages: 310
    • Voir le profil
Re : analogWrite qui ne fonctionne pas toujours correctement avec des LEDs
« Réponse #5 le: septembre 21, 2020, 10:49:57 am »
Si le petit programme du haut fonctionne seul, c'est déjà une bonne chose. reste à savoir pourquoi il ne fonctionne plus quand il est intégré dans un programme plus vaste.
Cependant, voici quelques conseils pour débutant :
- initialiser les durées avec unsigned long comme cela a été dit par simontpellier
- définir les broches de votre carte plutôt que d'utiliser les numéros ; ainsi si dans l'avenir vous devez changer, ce sera plus facile que de reprendre l'ensemble du code. Pour cela, vous pouvez faire appel à #define sortie_Led 10 ou bien à const byte sortie_Led = 10;
- certains commentaires ne sont pas en accord avec l'instruction comme par exemple pinMode(3, INPUT); // sortie A (si c'est réellement une sortie, ce devrait être OUTPUT !)
- mettre un commentaire de début /* */ pour rappeler comment votre carte est branchée par rapport aux capteurs et actuateurs  ; cela facilite la lecture par d'autres programmeurs (ou alors, faites un schéma de câblage avec le logiciel Fritzing et joignez le pour demander de l'aide).
- initialisez vos booleans avec true (ou bien false) car c'est plus logique que de donner la valeur 1 (même si au final, c'est bien ce qui se passe)
- bien qu'on puisse mettre plusieurs instructions sur une seule ligne, je vous déconseille de le faire car c'est bien plus lisible pour un autre programmeur d'avoir une seule instruction par ligne (avis personnel mais qui risque d'être partagé dans notre communauté)

Il n'y a sans doute pas grand chose à corriger, mais c'est effectivement difficile de réfléchir sur le programme de quelqu'un d'autre. L'utilisation de Serial.println() comme l'a dit Thierry vous permettra d'afficher ce qui se passe réellement et de comprendre pourquoi quelque chose déraille. Mais vous y arriverez.

msport

  • Global Moderator
  • Hero Member
  • *****
  • Messages: 2218
  • HO avec DCC++ en DIY Réseaux très éphémères
    • Voir le profil
Re : analogWrite qui ne fonctionne pas toujours correctement avec des LEDs
« Réponse #6 le: septembre 21, 2020, 03:29:27 pm »
Bonjour,
 analogWrite fonctionne mais un problème de logique le fait passer du mini au maxi sans qu'on voit les niveaux intermédiaires.
Des println pour voir ce qui se passe.
Cordialement

hinano70

  • Newbie
  • *
  • Messages: 18
    • Voir le profil
Re : analogWrite qui ne fonctionne pas toujours correctement avec des LEDs
« Réponse #7 le: septembre 21, 2020, 03:47:43 pm »
Merci pour les conseils, j'ai tenu compte des remarques.
Voici le montage joint
J'ai effectivement mis des tests un peu partout :
Serial.println(intensite); pour tester la valeur envoyée sur la sortie 10 PWM de la Led, ça augmente 0>250, puis ça diminue 250>0..., le timing est correct.
Serial.println(angle); pour vérifier la valeur envoyée aux servomoteurs, les barrières se ferment et s'ouvrent.
Tout est normal

Le problème c'est que la Led ne s'allume que si la valeur envoyée est 255 !!! (ce qui n'est pas atteint dans le programme puisque ça va de 0 à 250 par pas de 10, mais que je produis dans mes tests). Alors que le programme clignotement fonctionne très bien tout seul !!!

Est-ce un problème de typage incorrect avec des octets qui viennent en écraser d'autres ?

Je remets le code plus clair :

#include <Servo.h>
/* PN double voie A et B
détection par capteur IR de l'arrivée : detect1 passe de 1 à 0
et du passage du dernier wagon : detect2 passe de 0 à 1 avec delai de micro-coupure
*/
Servo servoPNA; // servo voie A
Servo servoPNB; // servo voie B
boolean detect1A,detect1B;  //détection des capteurs en entrée du PN (0 si train)
boolean  olddetect1A,olddetect1B;  //dernière détection prise en compte
boolean detect2A,detect2B=1;   // en sortie du PN
boolean  olddetect2A,olddetect2B=1;
boolean  lastdetect2A,lastdetect2B=1;  //dernière détection lue, pas forcément prise en compte (micro coupure due aux inter-wagons)
boolean readingPNA,readingPNB;
unsigned long lastPNATime,lastPNBTime;   // derniere fois que les detecteurs ont changes
unsigned long PNDelay = 500; // durée maxi des micro-coupures
int avertissement = 2000; // durée avant fermeture
byte phase = 0;  // phase de clignotement (4 phases : croissance-max-decroissance-nulle)
unsigned long fading = 5;  // durée initiale entre 2 éclairages
byte intensite = 0;  //intensite de l'éclairement
unsigned long LedTime = millis();       // timer pour le clignotement
unsigned long PNTime = millis();        // timer pour les moteurs d'aiguillage
boolean  ferme=false,fermeA=false,fermeB=false;
byte angle=140;   // angle initial barrières ouvertes

void setup()
{
servoPNA.attach(5);// servo A
servoPNB.attach(6);// servo B
//Serial.begin(9600);
pinMode(2,INPUT); // détecteur entrée PN voie A
pinMode(3,INPUT); // détecteur sortie PN voie A
pinMode(7,INPUT); // détecteur entrée PN voie B
pinMode(8,INPUT); // détecteur sortie PN voie B
pinMode(10, OUTPUT); // 2 Leds clignotantes
pinMode(11, OUTPUT); // 2 Leds clignotantes
servoPNA.write(140); // barrière A ouverte
servoPNB.write(140); // barrière B ouverte

analogWrite(10,0);// 2 Leds coté A éteintes
analogWrite(11,0);// 2 Leds coté B éteintes
}
void loop()
{

detect1A = digitalRead(2); //reading=0 si train
if ((olddetect1A==1 && detect1A==0) && fermeA==0) {fermeA=1;
                                                  if (fermeB==0) {PNTime = millis()+avertissement;
                                                  LedTime = millis();} }  // ferme voie A
olddetect1A = detect1A;

readingPNA = digitalRead(3); //reading=0 si train
if (readingPNA != lastdetect2A) {lastPNATime = millis();}  //déclenchement chrono
if ((millis() - lastPNATime) > PNDelay) {// si le delai est atteint, le changement est valide sinon le changement est ignore (parasite ou inter-wagon)
                                        if (readingPNA != detect2A) {detect2A = readingPNA;} // changement valide                                                       
                                        }

lastdetect2A = readingPNA;
if (olddetect2A==0 && detect2A==1) {fermeA=0; lastPNATime = millis();}  // ouvre voie A
olddetect2A=detect2A;


detect1B=digitalRead(7);
if ((olddetect1B==1 && detect1B==0) && fermeB==0) {fermeB=1;
                                                  if (fermeA==0) {PNTime = millis()+avertissement;
                                                  LedTime = millis();} }  // ferme voie B
olddetect1B=detect1B;

readingPNB = digitalRead(8); //reading=0 si train
if (readingPNB != lastdetect2B) {lastPNBTime = millis();}  //déclenchement chrono
if ((millis() - lastPNBTime) > PNDelay) {// si le delai est atteint, le changement est valide sinon le changement est ignore (parasite ou inter-wagon)
                                        if (readingPNB != detect2B) {detect2B = readingPNB;} // changement valide                                                       
                                        }

lastdetect2B=readingPNB;
if (olddetect2B==0 && detect2B==1) {fermeB=0; lastPNBTime = millis();}  // ouvre voie B
olddetect2B=detect2B;

ferme = (fermeA || fermeB);
if ((ferme==1) || (angle<140)) { clignote();}
else {Serial.println("ouvert");
      analogWrite(10,0);
      analogWrite(11,0);
      phase = 0;
      intensite=0;
      fading = 5;}

if ((ferme==1) && (angle>50)) {fermePN();}

if ((ferme==0) && (angle<140)) {ouvrePN();}

//Serial.println(angle);
}


void clignote()
{

//Serial.println(intensite);
if ( millis() > LedTime + fading)     // vitesse de clignotement
   {
   LedTime = millis();   // reinit le timer
 

   switch (phase) {
           case 0 :       // croit
              intensite += 10;
              if (intensite == 250) {phase = 1; fading = 200;}
              break;
           case 1 :      // allume
              phase = 2; fading=5;
              break;
           case 2 :      // decroit
              intensite -= 10;
              if (intensite == 0) {phase = 3; fading = 200;} break;
           case 3 :      // eteint
              phase = 0;
              fading = 5;
              break;
                }
   analogWrite(10,intensite);
   }
}

void ouvrePN()
{
if ((millis() - PNTime) > 20) {PNTime = millis();
                               angle+=1;
                               servoPNA.write(angle);
                               servoPNB.write(angle); }
}

void fermePN()
{
if (millis() > (20+PNTime)) {PNTime = millis();
                             angle-=1;
                             servoPNA.write(angle);
                             servoPNB.write(angle);  }
}

hinano70

  • Newbie
  • *
  • Messages: 18
    • Voir le profil
Re : analogWrite qui ne fonctionne pas toujours correctement avec des LEDs
« Réponse #8 le: septembre 21, 2020, 05:10:22 pm »
Je progresse:
Lorsque je neutralise les servomoteurs (il faut que je neutralise les 2):
//Servo servoPNA; // servo voie A
//Servo servoPNB; // servo voie B , etc.....
et bien ça marche ??!!
Par contre si je les enlève physiquement en laissant le code, ça ne marche pas.

8 lignes où ça intervient:
Servo servoPNA; // servo voie A
Servo servoPNB; // servo voie B
....
servoPNA.attach(5);// servo A
servoPNB.attach(6);// servo B
servoPNA.write(140); // barrière A ouverte
servoPNB.write(140); // barrière B ouverte
....
servoPNA.write(angle);  //pour ouvrir ou fermer lentement
servoPNB.write(angle);

Je suis un peu dépassé, donc si qq'un a une idée, merci....
Un passage à niveau sans barrière, c'est quand même embêtant !

Thierry

  • Global Moderator
  • Hero Member
  • *****
  • Messages: 744
    • Voir le profil
Re : analogWrite qui ne fonctionne pas toujours correctement avec des LEDs
« Réponse #9 le: septembre 21, 2020, 06:14:03 pm »
Je me suis permis de rendre le code lisible pour le commun des mortels. C'est bien sûr une proposition, vous en faites ce que vous voulez.

#include <Servo.h>

/* PN double voie A et B
détection par capteur IR de l'arrivée : detect1 passe de 1 à 0
et du passage du dernier wagon : detect2 passe de 0 à 1 avec delai de micro-coupure
*/
Servo servoPNA; // servo voie A
Servo servoPNB; // servo voie B

#define CAPTEUR_ENT_A 2 // détecteur entrée PN voie A
#define CAPTEUR_SOR_A 3 // détecteur sortie PN voie A
#define CAPTEUR_ENT_B 7 // détecteur entrée PN voie B
#define CAPTEUR_SOR_B 8 // détecteur sortie PN voie B

#define LED1  10
#define LED2  11

#define SERVOPNA  5
#define SERVOPNB  6

#define PHASE_CROIT 0
#define PHASE_ALLUME 1
#define PHASE_DECROIT 2
#define PHASE_ETEINT 3

#define ANGLEFERME 50
#define ANGLEOUVERT 140

bool detect1A = false;  //détection des capteurs en entrée du PN (0 si train)
bool detect1B = false;
bool olddetect1A = false;  //dernière détection prise en compte
bool olddetect1B = false;
bool detect2A = false;   // en sortie du PN
bool detect2B = true;
bool olddetect2A = false;
bool olddetect2B = true;
bool lastdetect2A = false;  //dernière détection lue, pas forcément prise en compte (micro coupure due aux inter-wagons)
bool lastdetect2B = true;
bool readingPNA = false;
bool readingPNB = false;
unsigned long lastPNATime = 0;   // derniere fois que les detecteurs ont changes
unsigned long lastPNBTime = 0;
unsigned long PNDelay = 500; // durée maxi des micro-coupures
int avertissement = 2000; // durée avant fermeture
byte phase = 0;  // phase de clignotement (4 phases : croissance-max-decroissance-nulle)
unsigned long fading = 5;  // durée initiale entre 2 éclairages
byte intensite = 0;  //intensite de l'éclairement

unsigned long LedTime = millis();       // timer pour le clignotement
unsigned long PNTime = millis();        // timer pour les moteurs d'aiguillage
bool ferme = false;
bool fermeA = false;
bool fermeB = false;
byte angle = ANGLEOUVERT;   // angle initial barrières ouvertes

void setup()
{
  servoPNA.attach(5);// servo A
  servoPNB.attach(6);// servo B
  //Serial.begin(9600);

  pinMode(CAPTEUR_ENT_A, INPUT); // détecteur entrée PN voie A
  pinMode(CAPTEUR_SOR_A, INPUT); // détecteur sortie PN voie A
  pinMode(CAPTEUR_ENT_B, INPUT); // détecteur entrée PN voie B
  pinMode(CAPTEUR_SOR_B, INPUT); // détecteur sortie PN voie B
  pinMode(LED1, OUTPUT); // 2 Leds clignotantes
  pinMode(LED2, OUTPUT); // 2 Leds clignotantes

  servoPNA.write(ANGLEOUVERT); // barrière A ouverte
  servoPNB.write(ANGLEOUVERT); // barrière B ouverte

  analogWrite(LED1, 0); // 2 Leds coté A éteintes
  analogWrite(LED2, 0); // 2 Leds coté B éteintes
}

void loop()
{
  detect1A = digitalRead(CAPTEUR_ENT_A); //reading=0 si train
  if ((olddetect1A == HIGH && detect1A == LOW) && fermeA == false)
  {  // ferme voie A
    fermeA = true;
    if (fermeB == false)
    {
      PNTime = millis() + avertissement;
      LedTime = millis();
    }
  }
  olddetect1A = detect1A;

  readingPNA = digitalRead(CAPTEUR_SOR_A); //reading=0 si train
  if (readingPNA != lastdetect2A)
  {  //déclenchement chrono
    lastPNATime = millis();
  }

  if ((millis() - lastPNATime) > PNDelay)
  { // si le delai est atteint, le changement est valide sinon le changement est ignore (parasite ou inter-wagon)
    if (readingPNA != detect2A)
    {
      detect2A = readingPNA;
    } // changement valide
  }

  lastdetect2A = readingPNA;
  if (olddetect2A == LOW && detect2A == HIGH)
  {  // ouvre voie A
    fermeA = false;
    lastPNATime = millis();
  }
  olddetect2A = detect2A;

  detect1B = digitalRead(CAPTEUR_ENT_B);
  if ((olddetect1B == HIGH && detect1B == LOW) && fermeB == false)
  {  // ferme voie B
    fermeB = true;
    if (fermeA == fasle)
    {
      PNTime = millis() + avertissement;
      LedTime = millis();
    }
  }
  olddetect1B = detect1B;

  readingPNB = digitalRead(CAPTEUR_SOR_B); //reading=0 si train
  if (readingPNB != lastdetect2B)
  {  //déclenchement chrono
    lastPNBTime = millis();
  }

  // si le delai est atteint, le changement est valide sinon le changement est ignore (parasite ou inter-wagon)
  if ((millis() - lastPNBTime) > PNDelay)
    if (readingPNB != detect2B)
      detect2B = readingPNB; // changement valide

  lastdetect2B = readingPNB;
  if (olddetect2B == LOW && detect2B == HIGH)
  {  // ouvre voie B
    fermeB = false;
    lastPNBTime = millis();
  }

  olddetect2B = detect2B;

  ferme = (fermeA || fermeB);
  if (ferme == true || angle < ANGLEOUVERT)
    clignote();
  else
  {
    Serial.println("ouvert");
    analogWrite(LED1, 0);
    analogWrite(LED2, 0);
    phase = PHASE_CROIT;
    intensite = 0;
    fading = 5;
  }

  if (ferme == true && angle > ANGLEFERME)
    fermePN();

  if (ferme == false && angle < ANGLEOUVERT)
    ouvrePN();

  //Serial.println(angle);
}

void clignote()
{
  //Serial.println(intensite);
  if (millis() > LedTime + fading)     // vitesse de clignotement
  {
    LedTime = millis();   // reinit le timer
 
    switch (phase)
    {
      case PHASE_CROIT:       // croit
        intensite += 10;
        if (intensite == 250)
        {
          phase = PHASE_ALLUME;
          fading = 200;
        }
        break;

      case PHASE_ALLUME:      // allume
        phase = PHASE_DECROIT;
        fading = 5;
        break;

      case PHASE_DECROIT:      // decroit
        intensite -= 10;
        if (intensite == 0)
        {
          phase = PHASE_ETEINT;
          fading = 200;
        }
        break;

      case PHASE_ETEINT:      // eteint
        phase = PHASE_CROIT;
        fading = 5;
        break;
    }
    analogWrite(LED1, intensite);
  }
}

void ouvrePN()
{
  if ((millis() - PNTime) > 20)
  {
    PNTime = millis();
    angle += 1;
    servoPNA.write(angle);
    servoPNB.write(angle);
  }
}

void fermePN()
{
  if (millis() > 20 + PNTime)
  {
    PNTime = millis();
    angle -= 1;
    servoPNA.write(angle);
    servoPNB.write(angle);
  }
}

Le problème vient sans doute de la logique d'enchaînement des phases. En tout cas, la fonction 'clignote' par exemple ne s'occupe que d'une seule led, normal ?
Bien sûr, tout ça n'est ni compilé, ni testé...

chris_bzg

  • Global Moderator
  • Sr. Member
  • *****
  • Messages: 310
    • Voir le profil
Re : analogWrite qui ne fonctionne pas toujours correctement avec des LEDs
« Réponse #10 le: septembre 21, 2020, 06:32:37 pm »
Sur votre schéma, il manque un câble rouge qui reprend l'alimentation 5 V de la ligne rouge d'alimentation du bas de la breadboard pour alimenter la ligne rouge d'alimentation du haut de la breadboard, mais ce câble doit exister sur votre montage puisque les servos fonctionnent (sur le schéma, ils ne sont pas alimentés en +5 V).

La bibliothèque Servo utilise le timer 1 ; justement celui qui délivre la PWM sur la broche 10. Il y a donc incompatibilité.
Branchez votre LED sur la broche 11 du Nano et dites moi si cela fonctionne mieux.
Si oui, il faudra brancher la première LED sur broche 11 et la deuxième LED sur une autre broche PWM sauf la 9 (timer 1 également).
C'est là que vous verrez l'importance de ne pas utiliser les numéros de broches dans un programme !  ;)

Enfin, et contrairement à ce que vous dites, je ne trouve pas que votre programme soit plus clair. Inspirez-vous du programme qu'a fait Thierry : celui-ci est clair et adoptez les bonnes pratiques dès maintenant. Bon, j'ai tout de même compris grâce à vous que "capteur sortie de PN" est bien une entrée. Mais pourquoi ne pas l'écrire en toute lettre puisque c'est en commentaire ? Croyez-moi, en perdant un peu de temps à décrire en détail un programme, on gagne énormément de temps pour sa mise au point (surtout si on reprend le programme un an plus tard pour l'améliorer : du genre "qu'est ce que j'ai bien voulu dire ?"  ???).
« Modifié: septembre 21, 2020, 06:44:50 pm par chris_bzg »

chris_bzg

  • Global Moderator
  • Sr. Member
  • *****
  • Messages: 310
    • Voir le profil
Re : analogWrite qui ne fonctionne pas toujours correctement avec des LEDs
« Réponse #11 le: septembre 21, 2020, 06:55:20 pm »
Voici d'ailleurs ce qui est dit au sujet de la bibliothèque Servo sur le site arduino.cc (j'ai simplement fait traduire la page en français par mon navigateur) :
Pour voir l'image, il faut être connecté. Pour la lire, il faut l'agrandir en cliquant dessus.
« Modifié: septembre 21, 2020, 06:58:08 pm par chris_bzg »

hinano70

  • Newbie
  • *
  • Messages: 18
    • Voir le profil
Re : analogWrite qui ne fonctionne pas toujours correctement avec des LEDs
« Réponse #12 le: septembre 21, 2020, 09:03:52 pm »
Merci Thierry, je n'ai pas trop l'habitude de travailler ainsi (flemme d'écrire du code), les commentaires sont tout à fait justes, au bout de quelques temps on ne sait plus trop ce qu'on voulait faire. J'ai bien sûr pris le code et je vais tâcher de suivre les conseils.
Super chris_bzg, ça fonctionne parfaitement (avec le code de Thierry), je n'aurais jamais trouvé ça ! On doit pouvoir mettre les 4 leds de 2mm + R=470ohm en parallèle sur la sortie 11. Sinon il faut que je réaffecte mes sorties, dommage, j'avais fait un "shield" pour monter le nano et brancher aisément les capteurs, moteurs ...
Encore merci à tous.

Thierry

  • Global Moderator
  • Hero Member
  • *****
  • Messages: 744
    • Voir le profil
Re : analogWrite qui ne fonctionne pas toujours correctement avec des LEDs
« Réponse #13 le: septembre 22, 2020, 09:23:42 am »
Content que ça marche, c'est bien.
C'est vrai que cela peut sembler fastidieux de coder tout de suite avec des define, plein de lignes, etc... Mais si j'ai retenu une chose de mon métier de programmeur, c'est que la probabilité qu'un programme fonctionne du premier coup est extrêmement faible, aussi simple soit-il ! Alors coder avec les bonnes pratiques rend le debugguage bien plus facile, même longtemps après. Et je ne parle même pas de partager son code avec d'autres, ce que nous pratiquons abondamment ici.

chris_bzg

  • Global Moderator
  • Sr. Member
  • *****
  • Messages: 310
    • Voir le profil
Re : analogWrite qui ne fonctionne pas toujours correctement avec des LEDs
« Réponse #14 le: septembre 22, 2020, 09:30:31 am »
Si, vous auriez fini par trouver de vous-même !  ;)

Il y a deux choses à retenir : d'abord, écrire le programme en suivant les normes de présentation et en commentant de façon précise. On le fait pour soi et aussi pour ceux qui doivent apporter de l'aide. Définir les entrées-sorties par des noms et non par des numéros permet de modifier aisément le montage si celui-ci doit évoluer.

Deuxièmement, quand un programme fonctionne seul mais ne fonctionne plus quand on lui rajoute du code, c'est que le dysfonctionnement vient du code rajouté et c'est donc là qu'il faut chercher. Les PWM sont générées par les timers du microcontrôleur (voir les articles que j'ai écrits sur les timers). Or, certaines bibliothèques utilisent aussi les timers donc il peut y avoir incompatibilité. C'est pourquoi il est nécessaire de toujours se référer à la documentation qu'on trouve sur le site d'Arduino et on peut la traduire si on n'est pas familier de la langue de Newton (restons dans la science !).

Quatre LED sur une sortie, c'est un peu beaucoup. Le mieux est de se limiter à 2, donc il faudra deux sorties si vous voulez avoir quatre feux clignotants. Ce sont les PN modernes qui ont 4 feux clignotants, visibles de toute part. Il y a quelques années, on ne trouvait que deux feux, un de chaque côté de la voie. Selon l'époque de votre réseau, à vous de voir... Mais vous pouvez aussi trouver une sortie PWM pour les deux LED quitte à réaffecter un servo ailleurs. Quant au shield, il faut l'élaborer quand le prototype est au point, pas avant. Mais celui-ci peut facilement se modifier en rajoutant un fil ou en coupant une piste.

Tenez-nous au courant de votre montage : photos ou vidéos bienvenues.
« Modifié: septembre 22, 2020, 09:32:04 am par chris_bzg »