Go Down

Topic: [Aide] Comment structurer mon programme (Read 1 time) previous topic - next topic

Vortof

Feb 18, 2012, 10:53 pm Last Edit: Feb 18, 2012, 10:56 pm by Vortof Reason: 1
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)

Code: [Select]

...
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 ;-)

Merci à vous.

zoroastre

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.

Veuillez indiquer [RESOLU] dans l'entête du titre en éditant votre premier message ;)

Vortof

#2
Feb 18, 2012, 11:28 pm Last Edit: Feb 18, 2012, 11:36 pm by Vortof Reason: 1
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.

Jean-François

#3
Feb 19, 2012, 07:51 am Last Edit: Feb 19, 2012, 07:55 am by Jean-François Reason: 1
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 ()
{
}
MacBook intel core 2 duo  os X snow Leopard 10.6
 eMac PPc G4  os X Leopard 10.5
powerbook G4 os X Leopard 10.5
imac PPC G3 os X Pa

zoroastre

Yep!

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

Code: [Select]
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.
Veuillez indiquer [RESOLU] dans l'entête du titre en éditant votre premier message ;)

Vortof

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

Vortof

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

Code: [Select]

...
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 :-(

osaka

#7
Feb 19, 2012, 05:13 pm Last Edit: Feb 19, 2012, 06:31 pm by osaka Reason: 1
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

Code: [Select]

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 == ...)
 {
   ...
 }

...

}

Vortof

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.

fdufnews

#9
Mar 04, 2012, 12:21 pm Last Edit: Mar 04, 2012, 12:25 pm by fdufnews Reason: 1
en variable globale tu déclares un pointeur vers une fonction
Code: [Select]
void (*func)(void);  // pointeur vers une fonction qui ne reçoit pas d'argument et ne retourne rien


dans loop tu appelles func

Code: [Select]
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

Code: [Select]
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)

fdufnews

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

Vortof

#11
Mar 04, 2012, 03:30 pm Last Edit: Mar 05, 2012, 09:08 am by Vortof Reason: 1
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.


Code: [Select]
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 ?
Code: [Select]
void AA() {
 analogWrite (ledR, 255);
 analogWrite (ledG, 0);
 analogWrite (ledB, 0);



OK pour la fonction par défaut.


fdufnews

Code: [Select]
void AA(void) {
  analogWrite (ledR, 255);
  analogWrite (ledG, 0);
  analogWrite (ledB, 0);
...
}

Vortof

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

Vortof

Ca ne fonctionne toujours pas :-(
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
Code: [Select]

#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'

Go Up