[Aide] Comment structurer mon programme

Bonjour (bonsoir) à vous,
j’aurais besoin de vos lumière pour structurer mon programme parce que je tourne un peu en rond…

Voici a quoi ça doit ressembler (version courte pour le principe)

...
switch (results.value) {
  case 175: AA(); 
  break;
  case 695: BB(); 
  break;
}

void AA() {
  analogWrite (ledA, 0);
  analogWrite (ledB, 255);
  delay(1000);
  analogWrite (ledA, 255);
  analogWrite (ledB, 0);
  delay(1000);
}

void BB() {
 ...
}

Je souhaiterai que quand j’appelle la fonction AA, elle s’exécute en boucle tant que je ne fais pas appel à une autre fonction.
Idem si j’appelle la fonction BB.

Si une âme charitable veut bien me donner une solution :wink:

Merci à vous.

Yep!

Cà depend si tu veux rester dans la boucle ou si tu veux que ton programme continue les instructions suivantes.

Dans le premier cas, un simple while devrait suffire. Dans le second, il faudra gérer une ou plusieurs interruptions.

Decris nous un peu la nature de la condition qui doit te faire sortir de la boucle : digital, analogique, serial, tempo, compteur ???

@+

Zoroastre.

Description du système:

une télécommande IR envoie le code de la touche pressée sur la Pin digitale 11 (-> results.value) à chaque code IR correspond une fonction qui doit s'exécuter en boucle tant qu'un autre code IR n'est pas reçu. à la réception d'un nouveau code IR, on passe à une autre fonction, en boucle jusqu’au prochain code IR.

merci pour ton aide.

Dans la boucle principale qui va gérer l'IR, je mettrais une variable en char et qui changerait avec l'IR. Ensuite tu appelles tes fonctions comme ça :

Void loop() { IR; char(); }

Void char () { }

Yep!

L'idée de Jean-François (simple et efficace) est de renvoyer le resultat dans une fonction à chaque cycle (loop).

void loop() {

  // Récuperation de results.value via Ir
...
  routine(results.value);
...
}

void routine(int value) {
  switch(value) {
    case 175 : ...; break;
    case 695 : ...; break;
  }
}

@+

Zoroastre.

hmm... merci à vous deux. je vais essayer de tester ça cet après-midi et je vous tiens au courant.

bon j'ai suivi l'exemple, ça donne si je ne me suis pas trompé:

...
void loop() {

if (irrecv.decode(&results)) {
  routine(results.value);
...
}

void routine(int value) {
  switch(value) {
    case 175 : 
      analogWrite (ledA, 0);
      analogWrite (ledB, 255);
      delay(1000);
      analogWrite (ledA, 255);
      analogWrite (ledB, 0);
      delay(1000);
    break;
    case 695 : ...; break;
  }
}

Dans le cas où le récepteur IR reçoit la valeur 175, on exécute bien case 175 mais qu'une seule fois. Il faudrait que case 175 tourne en boucle jusqu'à ce que le récepteur reçoive une autre valeur.

J'ai essayé avec des while. Ca boucle bien, mais j'arrive plus à sortir de la boucle du coup :-(

utilise plutôt une variable global pour conservé la dernière valeur reçue ("if (irrecv.decode(&results))" bloque un second appel à "routine()") de ton récepteur comme ça tu peux comparé la dernière valeur tout au long et partout dans ton programme et donc ici boucler cette valeur via loop. Utilise également des if plutôt que du switch case (ça revient au même) , ça te permettra également d'ajouter d'autres critères dans tes conditions if si besoin. Évite également la fonction delay qui risque de bloqué ton code (dans ce delay), donc la bonne réception de commandes. Voir: http://arduino.cc/en/Tutorial/BlinkWithoutDelay

int value // en global
...
void setup()
{
  ...
}

void loop() 
{
  if(irrecv.decode(&results)) 
  {
    value = results.value;
  }
  routine();
...
}

void routine() 
{
  if(value == 175)
  {
      analogWrite (ledA, 0);
      analogWrite (ledB, 255);
      delay(1000);
      analogWrite (ledA, 255);
      analogWrite (ledB, 0);
      delay(1000);
  }
  else if(value == 695)
  {
    ...
  }
  else if(value == ...)
  {
    ...
  }

...

}

Ne trouvant pas de solution à mon problème, je vais le laisser un peu de coté et poursuivre sur le reste de mon projet.

Je pense qu'il doit y avoir un problème avec irrecv.resume(); dans le loop(), ça doit bloquer un truc... Plus tard donc.

Merci quand même.

en variable globale tu déclares un pointeur vers une fonction

void (*func)(void);  // pointeur vers une fonction qui ne reçoit pas d'argument et ne retourne rien

dans loop tu appelles func

void loop() {

if (irrecv.decode(&results)) {
  routine(results.value);
}

func();
...
}

et dans ta gestion du code reçu tu affectes les fonction AA, BB, .... à func en fonction du code reçu

void routine(int code){
   switch(code){
      case xx: func=(void*)AA;break;
      case xx: func=(void*)BB;break;
      case xx: func=(void*)CC;break;
   }
}

edit ATTENTION: il ne faut pas oublier de faire pointer func vers une fonction par défaut (une fonction qui ne fait rien par exemple)

On peut aussi imaginer une variante utilisant un tableau de pointeurs vers des fonctions. Cela permets des "fantaisies" comme la création de séquences par exemple

merci fdufnews pour ton aide, je vais tenter ton exemple. J'ai du mal avec les pointeurs, je n'ai toujours pas compris comment ça fonctionne, comment ça s'écrit... pourquoi * est des fois dans la parenthèse des fois non... enfin c'est un truc obscur pour moi.

void routine(long code){
   switch(code){
      case 16775175: func=(void*)AA; break;
      case 16750695: func=(void*)BB; break; 
      case 16767015: func=(void*)CC; break;

error: invalid conversion from 'void*' to 'void (*)()' pour les 3 lignes

je dois bien déclarer AA comme ça ?

void AA() {
  analogWrite (ledR, 255);
  analogWrite (ledG, 0);
  analogWrite (ledB, 0);

OK pour la fonction par défaut.

void AA(void) {
  analogWrite (ledR, 255);
  analogWrite (ledG, 0);
  analogWrite (ledB, 0);
...
}

hmmm… la subtilité…
je teste en rentrant, merci.

Ca ne fonctionne toujours pas :frowning:
fdufnews si t’as une idée et un peu de temps, merci à toi.

Voici le code, c’est juste pour tester et quand ça fonctionnera… pour un projet plus gros

#include <IRremote.h>

int receiver = 11; // pin Data du recepteur IR
int ledR = 3; // pin led Rouge
int ledG = 5; // pin led Verte
int ledB = 6; // pin led Bleue

IRrecv irrecv(receiver); // crée une intance de 'irrecv'
decode_results results;

// pointeur vers une fonction qui ne reçoit pas d'argument et ne retourne rien
void (*func)(void);

void setup(){
  Serial.begin(9600); 
  irrecv.enableIRIn(); // démarre le receiver
  
  pinMode(ledR, OUTPUT); // pin en sortie
  pinMode(ledG, OUTPUT);
  pinMode(ledB, OUTPUT);
}

void loop() {

  if (irrecv.decode(&results)) {
    routine(results.value);
    
    Serial.println(results.value); // affiche le code en décimal
    
    irrecv.resume(); // reçoit la valeur suivante
  }

  func();

}

void routine(long code){
   switch(code){
      case 16775175: func=(void*)AA; break; 
      case 16750695: func=(void*)BB; break;
      case 16767015: func=(void*)CC; break; 
      case 16746615: func=(void*)DD; break;
      case 16734375: func=(void*)EE; break;
      defaut: RGB(0,0,0);
   }
}

// affichage RGB
void RGB(int R, int G, int B) {
  analogWrite (ledR, R);
  analogWrite (ledG, G);
  analogWrite (ledB, B);
}
  
void AA(void){ RGB(0,0,0);}
void BB(void){ RGB(255,0,0);}
void CC(void){ RGB(0,255,0);}
void DD(void){ RGB(0,0,255);}

void EE(void){ 
  RGB(0,0,255);
  RGB(0,255,0);
  RGB(0,255,255);
  RGB(255,0,0);
  RGB(255,0,255);
  RGB(255,255,0);
  RGB(255,255,255);
  RGB(0,0,255);
  RGB(0,255,0);
  RGB(0,255,255);
  RGB(255,0,0);
  RGB(255,0,255);
  RGB(255,255,0);
}

Et les erreurs:
In function ‘void routine(long int)’
error: invalid conversion from ‘void*’ to ‘void (*)()’ → pour les 5 lignes commençant par ‘case’

En fait il ne doit pas être nécessaire de faire de changement de type puisque func et les fonctions AA, BB... sont définies de manières identiques

void routine(long code){
   switch(code){
      case 16775175: func=AA; break; 
      case 16750695: func=BB; break;
      case 16767015: func=CC; break; 
      case 16746615: func=DD; break;
      case 16734375: func=EE; break;
      defaut: RGB(0,0,0);
   }
}

avec routine comme ci-dessus le code compile correctement. Mais je n'ai rien pour l'essayer.

Ça compile mais par contre rien ne fonctionne même pas l'affichage sur le moniteur série du code reçu.

func n’est pas initialisé au démarrage et ne pointe sur rien ce qui entraine un plantage du programme.
Tu n’initialises func qu’à l’intérieur de routine(). Tant que tu n’as pas reçu un code func ne pointe sur rien.
Il faut donc faire pointer func sur une fonction à l’initialisation.

#include <IRremote.h>

int receiver = 11; // pin Data du recepteur IR
int ledR = 3; // pin led Rouge
int ledG = 5; // pin led Verte
int ledB = 6; // pin led Bleue

IRrecv irrecv(receiver); // crée une intance de 'irrecv'
decode_results results;

// pointeur vers une fonction qui ne reçoit pas d'argument et ne retourne rien
void (*func)(void);

void setup(){
  Serial.begin(9600); 
  irrecv.enableIRIn(); // démarre le receiver
  
  func=funcDefaut;   // initialise le pointeur sur la fonction

  pinMode(ledR, OUTPUT); // pin en sortie
  pinMode(ledG, OUTPUT);
  pinMode(ledB, OUTPUT);
}

void loop() {

  if (irrecv.decode(&results)) {
    routine(results.value);
    
    Serial.println(results.value); // affiche le code en décimal
    
    irrecv.resume(); // reçoit la valeur suivante
  }

  func();

}

void routine(long code){
   switch(code){
      case 16775175: func=AA; break; 
      case 16750695: func=BB; break;
      case 16767015: func=CC; break; 
      case 16746615: func=DD; break;
      case 16734375: func=EE; break;
      defaut: funcDefaut; // <---------------- là tu ne changes pas func est-ce volontaire? j'ai conservé ton écriture
//      defaut: func = funcDefaut;  // dé-commenter cette ligne pour modifier func lorsque tu reçois un code erroné
   }
}

void funcDefaut(void){RGB(0,0,0);}

// affichage RGB
void RGB(int R, int G, int B) {
  analogWrite (ledR, R);
  analogWrite (ledG, G);
  analogWrite (ledB, B);
}
  
void AA(void){ RGB(0,0,0);}
void BB(void){ RGB(255,0,0);}
void CC(void){ RGB(0,255,0);}
void DD(void){ RGB(0,0,255);}

void EE(void){ 
  RGB(0,0,255);
  RGB(0,255,0);
  RGB(0,255,255);
  RGB(255,0,0);
  RGB(255,0,255);
  RGB(255,255,0);
  RGB(255,255,255);
  RGB(0,0,255);
  RGB(0,255,0);
  RGB(0,255,255);
  RGB(255,0,0);
  RGB(255,0,255);
  RGB(255,255,0);

Alors ça fonctionne, merci beaucoup. Sauf un détail: au départ je voulais que EE() tourne en boucle tant que l'on appui pas sur autre touche.

https://www.w3.org/community/d-tasks/simple-page/

au départ je voulais que EE() tourne en boucle tant que l'on appui pas sur une autre touche.

Ce devrait être le cas puisque si on envoie pas de code on exécute func en boucle. Donc on exécute toujours la dernière commande en boucle. Maintenant si tu veux que par défaut on exécute EE() il suffit de remplacer dans setup() funcDefaut par EE dans l'initialisation de func. ou bien veux-tu dire que lorsqu'on appui sur une touche on exécute la fonction demandée et ensuite on revient automatiquement à EE. Dans ce cas il suffirait de mettre un else dans le if de la boucle principale pour refaire func=EE

Par contre une remarque, dans EE() il n'y a aucun delay() donc la suite de valeur doit s'enchainer à toute vitesse. Mais peut être est-ce ton souhait.