Sequenceur Led et interruption

Bonjour à tous voila je travail sur un projet comportant 2 leds de 10w que je veux commander via une arduino et un signal rc.

Voila j'ai fait ma première interruption qui calcul le signal pwm du recepteur et en fonction de ce signal j'essaye de basculer d'un programme à l'autre ....

Le problème c'est que je n'arrive pas à charger mes sequences depuis !!!

Voila j'ai fait ceci :

Je rentre bien dans ma fonction chargement mais rien du tt !!!
Sequence[][] est un tableau de int qui me sert à stocker les valeurs pwm des 2 leds une rgb et une blanche ... ainsi que le delai

volatile unsigned long timer_start;
volatile int pulse_time; 


volatile int last_time;


int ledGreen = 11;
int ledBlue = 9;
int ledRed = 10;
int ledWhite = 5;
int rcPin = 2;


// qd je mets cette sequence ici mon sequenceur fonctionne bien l'interruption aussi mais aucun chargement des autres sequences ...
// j'ai mis volontairement cette sequence ici normalement elle n'y est pas ...

int Sequence[][5] = {
    {255, 0  , 0 , 0  , 50},
    {0, 0  , 0 , 0  , 200},
    {255, 0  , 0 , 0  , 50},
    {0, 0  , 0 , 0  , 200},
    {255, 0  , 0 , 0  , 50},
    {0, 0  , 0 , 0  , 200},
    {0, 255  , 0 , 0 , 50},
    {0, 0  , 0 , 0  , 50},
    {0, 255  , 0 , 0 , 50},
    {0, 0 , 0 , 0 , 500},
    };


unsigned long top,delai;
int tache=0;  // tache en cours
boolean tacheDone=false;  // indique si la tache a été executé ou pas encore




int prog;
void chargement()
{
Serial.print("Programme :");
Serial.println(prog);


    if (prog==0){
    Serial.println("PRG 00000"); // je rentre bien dans le chargement 
    int Sequence[][5] = {
    {0, 0  , 0 , 0 , 1000},
    {0, 0 , 0 , 0 , 1000},
    };
    
    }
    if (prog==1){
    int Sequence[][5] = {
    {255, 0  , 0 , 0  , 50},
    {0, 0  , 0 , 0  , 200},
    {255, 0  , 0 , 0  , 50},
    {0, 0  , 0 , 0  , 200},
    };
    }
    if (prog==2){
    int Sequence[][5] = {
    {0, 255  , 0 , 0 , 1000},
    {0, 0 , 0 , 0 , 1000},
    };
    }


}




void calcSignal()
{
      if(digitalRead(rcPin) == HIGH)
          {
              timer_start = micros();
          }


          else
          {
            
            if(timer_start > 0)
            {
                
                pulse_time = ((volatile int)micros() - timer_start);
                timer_start = 0;
            
            }
          }
    
  if(pulse_time >1850 && last_time <=1100){
    prog++;
    if (prog>2){prog=0;}
    chargement();
    last_time = pulse_time;
  }
  else
  {
    last_time = pulse_time;
  }
}


void setup()
{
    timer_start = 0;
    prog = 0;
    pinMode(ledGreen, OUTPUT);     
    pinMode(ledBlue, OUTPUT); 
    pinMode(ledRed, OUTPUT);
    pinMode(ledWhite, OUTPUT);
    pinMode(rcPin, INPUT);
    
    top = millis();
    
    attachInterrupt(0, calcSignal, CHANGE);
    Serial.begin(9600);




}


void loop()
{
// gestionnaire du sequenceur de taches
  if((top+delai)<=millis()) {
    tache +=1;
    if (tache > (sizeof(Sequence)/10)-1){tache=0;}
    tacheDone = false;
    top=millis();
  }
  
// sequenceur de taches
  if (tacheDone == false){
      analogWrite(ledWhite,Sequence[tache][0]);
      analogWrite(ledRed,Sequence[tache][1]);
      analogWrite(ledGreen,Sequence[tache][2]);
      analogWrite(ledBlue,Sequence[tache][3]);
      delai=Sequence[tache][4];
      tacheDone =true;


}


}

Merci bcp pour votre aide
cdlt,
bypbop

hello
peux tu tester avec ces changements

volatile unsigned long timer_start;
volatile unsigned long pulse_time;//*********************************************
volatile unsigned long last_time;//*********************************************

et en ligne 79

if (timer_start > 0)
    {
      pulse_time = ((volatile unsigned long)micros() - timer_start); //***************************
      timer_start = 0;
    }

d'autre part, comment est déclenchée ton interruption ?
en effet dans ta routine d'interruption INT0, tu teste une entrée digitale???

je crois comprendre que ton signal RC devrait être sur INT0, pin 2
et ton code devrait etre:
void calcSignal()
{
timer_start = micros();
if (timer_start > 0)

de plus, dans une routine d'interruption, on en fait le moins possible, pour qu'elle se fasse très vite.
en principe, la routine fait seulement monter un volatile flag
et l'état du flag est testé dans la loop

  if(pulse_time >1850 && last_time <=1100){
    prog++;
    if (prog>2){prog=0;}
    chargement();
    last_time = pulse_time;
  }
  else
  {
    last_time = pulse_time;
  }

Je pense qu'il y a un pb avec last_time :
pour que prog s'incrémente il faut que le signal radio passe directement de <1100µs à >1850µs... il faudrait afficher la valeur de pulse pour voir si c'est possible!

Ps. : une interruption doit être la plus courte possible!

Bonjour fablath,

Alors merci pour ces précisions mais mon interruption fonctionne plutot bien j'ai bien dans la console programme 1, 2, et 000 ....

Effectivment pin 2 sur une arduino nano ...

Je viens de modifier pour faire un petit test j'ai remis tache à 0 aprés l'interruption

et mon programme reviens bien à 0 si j'appuie rapidement sur mon inter de radio ca revient bien à 0

Je pense que cela vient des tableaux qui "ne s'ecrase pas avec le nouveau "

Par la suite je pourrais revenir sur l'interruption car c'est deja assez complexe pour moi :wink:

Cordialement,
bypbop

volatile unsigned long timer_start;
volatile unsigned long pulse_time;//*********************************************
volatile unsigned long last_time;//*********************************************

Je viens de tester en changeant je ne rentre pas dans mes programmes ! je n'ai plus le serial print programme 1 et programme 2 ....

Ok!!
int Sequence au debut du prog créé un tableau global. int Sequence dans l'interruption créé un tableau local, qui est un objet different! La fonction chargement() utilise le tableau global,qui n'est jamais modifié.
Je pense qu'il faut que l'interruption donne volatile int pulse_time et que tout le reste se passe dans loop.

bizarre je ne reçois pas les mails du forum ... alors que je suis le sujet !!!

merci je comprends mieux !!! je reste sur le mm tableau !!!

Aurais tu une idée de comment faire plusieurs tableau et que je puisse via ma fonction chargement changer de programme ???

A la base j'ai mis la sequence en debut de code car cela ne fonctionnait plus !!! qd je la mets uniquement dans chargement();

Cordialement,
bypbop

Bonjour,
pour moi le plus simple est de faire 1 seul tableau Sequence qui contient tout les programmes. J'ai bricolé un peu ton code à ma façon... dis moi si ça fonctionne!

/*
    Séquenceur
*/

const int ledWhite = 5;
const int ledRed = 10;
const int ledGreen = 11;
const int ledBlue = 9;
const int rcPin = 2;

const int Sequence[][6] = {    // Num prog,   ledWhite,   ledRed,   ledGreen,   ledBlue,   delai //
    {0, 0,   0,   0,   0,   0   },    // Prog 0
    
    {1, 255, 0,   0,   0,   50  },    // Prog 1
    {1, 0,   0,   0,   0,   200 },
    {1, 255, 0,   0,   0,   50  },
    {1, 0,   0,   0,   0,   200 },
    {1, 255, 0,   0,   0,   50  },
    {1, 0,   0,   0,   0,   200 },
    {1, 0,   255, 0,   0,   50  },
    {1, 0,   0,   0,   0,   50  },
    {1, 0,   255, 0,   0,   50  },
    {1, 0,   0,   0,   0,   0   },
    
    {2, 0,   255, 0,   0,   50  },    // Prog 2
    {2, 0,   0,   0,   0,   50  },
    {2, 0,   255, 0,   0,   50  },
    {2, 0,   0,   0,   0,   0   },
    };                                

volatile unsigned long timer_start = 0;
volatile unsigned long pulse_time = 0; 
unsigned long last_time = 0;

unsigned long top, delai;
int prog = 0;
int tache = 0;  // tache en cours
boolean tacheDone = false;  // indique si la tache a été executé ou pas encore


void setup()
{
  pinMode(ledGreen, OUTPUT);     
  pinMode(ledBlue, OUTPUT); 
  pinMode(ledRed, OUTPUT);
  pinMode(ledWhite, OUTPUT);
  pinMode(rcPin, INPUT);

  top = millis();

  attachInterrupt(0, calcSignal, CHANGE);
  Serial.begin(9600);
}


void loop()
{
  // gestion du numéro de programme
  if(pulse_time >1850 && last_time <=1100)
  {
    prog++;
    if (prog > 2) 
    {
      prog = 0;
    }
    last_time = pulse_time;
    tacheDone = false;
    top = millis();
    Serial.print("Programme ");
    Serial.print(prog);
    Serial.print(" ...");
  }
  else
  {
    last_time = pulse_time;
  }

  // sequenceur de taches
  if (tacheDone == false && Sequence[tache][0] == prog)
  {
    analogWrite(ledWhite, Sequence[tache][1]);
    analogWrite(ledRed, Sequence[tache][2]);
    analogWrite(ledGreen, Sequence[tache][3]);
    analogWrite(ledBlue, Sequence[tache][4]);
    delai = Sequence[tache][5];
  }
  
  // gestionnaire du sequenceur de taches
  if((millis() - top) >= delai && tacheDone == false)
  {
    tache += 1;
    top = millis();
    if (tache > (sizeof(Sequence)/sizeof(Sequence[0])) || Sequence[tache][0] > prog)
    {
      tache=0;
      tacheDone = true;
      delai = 0;
      Serial.println(" OK ");
    }
  }
}


/***************** INTERRUPTION ***************************/

void calcSignal()
{
  if(digitalRead(rcPin) == HIGH)
  {
    timer_start = micros();
  }
  else
  {
    if(timer_start > 0)
    {
      pulse_time = (micros() - timer_start);
      timer_start = 0;
    }
  }
}

Merci je fais le test et je te tiens au jus !!!

Cordialement,
bypbop

Bonjour Fablath, j'ai testé ton code alors on avance :wink:

cela joue le programme à chaque fois que j'appuie sur le bouton mais cela ne boucle plus dessus !!

j'arrive à jouer un fois le prog 0 , le 1 et le 2 à chaque fois en appuyant sur mon inter !!

le sequenceur ne jour plus le programme en boucle si il n'y pas de changement !

Cordialement,
bypbop

Je n'avais pas compris que la séquence devais se répéter...
enlève la ligne

      tacheDone = true;

dans le dernier if du loop(), et ça devrais boucler!

ok oui cela boucle bien par contre si je comprends bien comme cela on fait la boucle sur tt le tableau à chaque fois ?

C'est surement à cause de ca que j'ai un delai à chaque répétition sur un programme ... sur le programme 4 par exemple j'ai au moins une demi seconde ....

/*
    Séquenceur
*/

const int ledWhite = 5;
const int ledRed = 10;
const int ledGreen = 11;
const int ledBlue = 9;
const int rcPin = 2;

const int Sequence[][6] = {    // Num prog,   ledWhite,   ledRed,   ledGreen,   ledBlue,   delai //
    {0, 0,   0,   0,   0,   0   },    // Prog 0
    
    {1, 255, 0,   0,   0,   50  },    // Prog 1
    {1, 0,   0,   0,   0,   200 },
    {1, 255, 0,   0,   0,   50  },
    {1, 0,   0,   0,   0,   200 },
    {1, 255, 0,   0,   0,   50  },
    {1, 0,   0,   0,   0,   200 },
    {1, 0,   255, 0,   0,   50  },
    {1, 0,   0,   0,   0,   50  },
    {1, 0,   255, 0,   0,   50  },
    {1, 0,   0,   0,   0,   0   },
    
    {2, 0,   255, 0,   0,   100  },    // Prog 2
    {2, 0,   0,   0,   0,   100  },
    {2, 0,   255, 0,   0,   100  },
    {2, 0,   0,   0,   0,   100  },
    
    {3, 0,   255, 0,   255, 100  },    // Prog 3
    {3, 0,   0,   0,   0,   100  },
    {3, 0,   255, 0,   255, 100  },
    {3, 0,   0,   0,   0,   100  },
    
    {4, 0,   255, 0,   0,   50  },    // Prog 4
    {4, 0,   0,   0,   0,   50  },
    {4, 0,   0,   255, 0,   50  },
    {4, 0,   0,   0,   0,   50  },
    {4, 0,   0,   0,  255,  50  },
    {4, 0,   0,   0,   0,   50  },
    {4, 0,   255, 255, 0,   50  },
    {4, 0,   0,   0,   0,   50  },
    {4, 0,   0,   255,  255,50  },
    {4, 0,   0,   0,   0,   50  },
    {4, 0,   255,   0, 255, 50  },
    {4, 0,   0,   0,   0,   50  },
    {4, 0,   255, 255, 255, 50  },
    {4, 0,   0,   0,   0,   50  },
    };                                

volatile unsigned long timer_start = 0;
volatile unsigned long pulse_time = 0; 
unsigned long last_time = 0;

unsigned long top, delai;
int prog = 0;
int tache = 0;  // tache en cours
boolean tacheDone = false;  // indique si la tache a été executé ou pas encore


void setup()
{
  pinMode(ledGreen, OUTPUT);     
  pinMode(ledBlue, OUTPUT); 
  pinMode(ledRed, OUTPUT);
  pinMode(ledWhite, OUTPUT);
  pinMode(rcPin, INPUT);

  top = millis();

  attachInterrupt(0, calcSignal, CHANGE);
  Serial.begin(9600);
}


void loop()
{
  // gestion du numéro de programme
  if(pulse_time >1850 && last_time <=1100)
  {
    prog++;
    if (prog > 4) 
    {
      prog = 0;
    }
    last_time = pulse_time;
    tacheDone = false;
    top = millis();
    Serial.print("Programme ");
    Serial.print(prog);
    Serial.print(" ...");
  }
  else
  {
    last_time = pulse_time;
  }

  // sequenceur de taches
  if (tacheDone == false && Sequence[tache][0] == prog)
  {
    analogWrite(ledWhite, Sequence[tache][1]);
    analogWrite(ledRed, Sequence[tache][2]);
    analogWrite(ledGreen, Sequence[tache][3]);
    analogWrite(ledBlue, Sequence[tache][4]);
    delai = Sequence[tache][5];
  }
  
  // gestionnaire du sequenceur de taches
  if((millis() - top) >= delai && tacheDone == false)
  {
    tache += 1;
    top = millis();
    if (tache > (sizeof(Sequence)/sizeof(Sequence[0])) || Sequence[tache][0] > prog)
    {
      tache=0;
      //tacheDone = true;
      //delai = 0;
    }
  }
}


/***************** INTERRUPTION ***************************/

void calcSignal()
{
  if(digitalRead(rcPin) == HIGH)
  {
    timer_start = micros();
  }
  else
  {
    if(timer_start > 0)
    {
      pulse_time = (micros() - timer_start);
      timer_start = 0;
    }
  }
}

je vois 3 possibilités :

  1. il faut laisser la ligne
delai = 0;
  1. pour être sur de ne pas prendre en compte le delai :
 // gestionnaire du sequenceur de taches
  if((millis() - top) >= delai || Sequence[tache][0] != prog)
  {
  1. on dépasse peut être la taille du tableau et il faut utiliser
    if (tache >= (sizeof(Sequence)/sizeof(Sequence[0])) || Sequence[tache][0] > prog)
    {

(il faut vérifier avec Serial.println(tache); pour être sur de ne pas pointer une ligne qui n'existe pas...)

ca tourne nickel :wink: !!!

un grand merci fablath !!!

J'ai modifié par ce que tu as dit :

if((millis() - top) >= delai || Sequence[tache][0] != prog)
  {

Cool!

je fais une petite vidéo et je te montre le résultat :wink:

Par contre je pensais faire qques fonctions pour generer par exemple un couleur alétoire ...

Je voulais faire une fonction fade in , fade out sur une couleur ...

maintenant que c'est dans un tableau unique ca va etre un peu compliqué non ?

Cordialement,
bypbop

j'ai fait une petite vidéo vite fait !

cela donne ca :

bypbop:
maintenant que c'est dans un tableau unique ca va etre un peu compliqué non ?

pas forcement, il suffit de gérer différemment en fonction du num de programme :

/*
    Séquenceur
 */

const int ledWhite = 5;
const int ledRed = 10;
const int ledGreen = 11;
const int ledBlue = 9;
const int rcPin = 2;

const int Sequence[][6] = {    // Num prog,   ledWhite,   ledRed,   ledGreen,   ledBlue,   delai //
    {0, 0,   0,   0,   0,   0   },    // Prog 0
    
    {1, 255, 0,   0,   0,   50  },    // Prog 1
    {1, 0,   0,   0,   0,   200 },
    {1, 255, 0,   0,   0,   50  },
    {1, 0,   0,   0,   0,   200 },
    {1, 255, 0,   0,   0,   50  },
    {1, 0,   0,   0,   0,   200 },
    {1, 0,   255, 0,   0,   50  },
    {1, 0,   0,   0,   0,   50  },
    {1, 0,   255, 0,   0,   50  },
    {1, 0,   0,   0,   0,   0   },
    
    {2, 0,   255, 0,   0,   100  },    // Prog 2
    {2, 0,   0,   0,   0,   100  },
    {2, 0,   255, 0,   0,   100  },
    {2, 0,   0,   0,   0,   100  },
    
    {3, 0,   255, 0,   255, 100  },    // Prog 3
    {3, 0,   0,   0,   0,   100  },
    {3, 0,   255, 0,   255, 100  },
    {3, 0,   0,   0,   0,   100  },
    
    {4, 0,   255, 0,   0,   50  },    // Prog 4
    {4, 0,   0,   0,   0,   50  },
    {4, 0,   0,   255, 0,   50  },
    {4, 0,   0,   0,   0,   50  },
    {4, 0,   0,   0,  255,  50  },
    {4, 0,   0,   0,   0,   50  },
    {4, 0,   255, 255, 0,   50  },
    {4, 0,   0,   0,   0,   50  },
    {4, 0,   0,   255,  255,50  },
    {4, 0,   0,   0,   0,   50  },
    {4, 0,   255,   0, 255, 50  },
    {4, 0,   0,   0,   0,   50  },
    {4, 0,   255, 255, 255, 50  },
    {4, 0,   0,   0,   0,   50  },
    };                                

volatile unsigned long timer_start = 0;
volatile unsigned long pulse_time = 0; 
unsigned long last_time = 0;

unsigned long top, delai;
int prog = 0;
int tache = 0;  // tache en cours


void setup()
{
  pinMode(ledGreen, OUTPUT);     
  pinMode(ledBlue, OUTPUT); 
  pinMode(ledRed, OUTPUT);
  pinMode(ledWhite, OUTPUT);
  pinMode(rcPin, INPUT);

  top = millis();

  attachInterrupt(0, calcSignal, CHANGE);
  Serial.begin(9600);
  randomSeed(analogRead(0));
}


void loop()
{
  // gestion du numéro de programme
  if(pulse_time >1850 && last_time <=1100)
  {
    prog++;
    if (prog > 8)     // nombre de programme TOTAL
    {
      prog = 0;
    }
    last_time = pulse_time;
    top = millis();
    Serial.print("Programme ");
    Serial.print(prog);
    Serial.print(" ...");
  }
  else
  {
    last_time = pulse_time;
  }

  if(prog <= 4)       // nombre de programme du tableau Sequence
  {

    // sequenceur de taches
    if(Sequence[tache][0] == prog)
    {
      analogWrite(ledWhite, Sequence[tache][1]);
      analogWrite(ledRed, Sequence[tache][2]);
      analogWrite(ledGreen, Sequence[tache][3]);
      analogWrite(ledBlue, Sequence[tache][4]);
      delai = Sequence[tache][5];
    }

    // gestionnaire du sequenceur de taches
    if((millis() - top) >= delai || Sequence[tache][0] != prog)
    {
      tache += 1;
      top = millis();
      if (tache > (sizeof(Sequence)/sizeof(Sequence[0])) || Sequence[tache][0] > prog)
      {
        tache=0;
        //tacheDone = true;
        //delai = 0;
      }
    }
  }
  else
  {
    // ici les fonctions pour affichage différent du tableau Sequence
    if(prog == 5)
    {
      FlashWhite();
    }
    if(prog == 6)
    {
      FadeInOut(ledRed, 10);
    }
    if(prog == 7)
    {
      FadeInOut(ledGreen, 20);
    }
    if(prog == 8)
    {
      randColor();
    }
  }
}


/***************** INTERRUPTION ***************************/

void calcSignal()
{
  if(digitalRead(rcPin) == HIGH)
  {
    timer_start = micros();
  }
  else
  {
    if(timer_start > 0)
    {
      pulse_time = (micros() - timer_start);
      timer_start = 0;
    }
  }
}


/***************** FONCTIONS ***************************/

void FlashWhite(void)
{
  for(int i = 1; i <= 256; i = i*2)
  {
    analogWrite(ledWhite, constrain(i,0,255));
    analogWrite(ledRed, 0);
    analogWrite(ledGreen, 0);
    analogWrite(ledBlue, 0);
  }
  analogWrite(ledWhite, 0);
}


void FadeInOut(int ledPin, int vitesse)
{
  for(int i = -255; i <= 255; i += vitesse)
  {
    analogWrite(ledPin, 255 - abs(i));
  }
  analogWrite(ledPin, 0);
}


void randColor(void)
{
  analogWrite(ledWhite, random(255));
  analogWrite(ledRed, random(255));
  analogWrite(ledGreen, random(255));
  analogWrite(ledBlue, random(255));
}

Merci bcp fablath pour ton aide sur mon projet ....