Go Down

Topic: boucle en attente action telecommande [Résolu] (Read 6600 times) previous topic - next topic

infobarquee

Nov 03, 2011, 11:02 am Last Edit: Nov 04, 2011, 10:27 pm by infobarquee Reason: 1
bonjour,
j'ai fait mumuse avec la télécommande infrarouge.

j'ai fait une petite série de fonctions suivant l'appuie des différents boutons, mais je n'arrive pas a stopper une boucle si j'appuie sur un autre bouton.
donc appuie sur le bouton 0, lance une boucle, comment la stopper.
merci d'avance

le bout de code en question
Code: [Select]

void loop() {
 if (irrecv.decode(&results)) {
   Serial.println(results.value, HEX);
   test=results.value, HEX;
   Serial.println(test);
if (test == 12495) {
     for ( int i = -1;i < 3024; i++) {
       digitalWrite(redPin, i);
       digitalWrite(greenPin, i + 12);
       digitalWrite(bluePin, i + 56);
        irrecv.resume(); // Receive the next value
       delay (5);
     }
AUCUNE AIDE PAR MP

skywodd

Bonjour,

tu parle d'appui sur des boutons mais je ne voie aucun digitalRead, aucune condition dans ton code !?

Si tu postait le code complet ce serai plus simple de t'aider ;)
Des news, des tutos et plein de bonnes choses sur http://skyduino.wordpress.com !

infobarquee

c'est pas un code de pro

Code: [Select]
#include <IRremote.h>

int RECV_PIN = 2;
int test = 1;
int test1 = 255;
int redPin = 11;
int greenPin = 10;
int bluePin = 9;
// Indicates what color we are reading next; 0 = red, 1 = green, 2 = blue
int pos = 0;

// red PWM value
int red = 0;
// green PWM value
int green = 0;
// blue PWM value
int blue = 0;

// indicates if next byte should be unescaped
boolean escape = false;
IRrecv irrecv(RECV_PIN);

decode_results results;

void setup()
{
  pinMode(redPin, OUTPUT);
  pinMode(greenPin, OUTPUT);   
  pinMode(bluePin, OUTPUT);
  // turn on LED on low brightness 
  digitalWrite(redPin, HIGH);
  digitalWrite(greenPin,LOW);
  digitalWrite(bluePin, HIGH);
  Serial.begin(9600);
  irrecv.enableIRIn(); // Start the receiver
}

void loop() {
  if (irrecv.decode(&results)) {
    Serial.println(results.value, HEX);
    test=results.value, HEX;
    Serial.println(test);
    if (test == test1) // bouton ON OFF
    {
      Serial.println(test1);
      digitalWrite(redPin, HIGH);
      digitalWrite(greenPin, HIGH);
      digitalWrite(bluePin, HIGH);
      irrecv.resume(); // Receive the next value
    }
    else if (test == 12495) {  // bouton 0
      for ( int i = -1;i < 3024; i++) {
        digitalWrite(redPin, i);
        digitalWrite(greenPin, i + 12);
        digitalWrite(bluePin, i + 56);
        irrecv.resume(); // Receive the next value
        delay (5);
      }
    }
    else if (test == 2295 || test == 'FD08F7') {  // bouton 1

      digitalWrite(redPin, HIGH);
      digitalWrite(greenPin,LOW);
      digitalWrite(bluePin, HIGH);
      irrecv.resume(); // Receive the next value

    }
    else if (test == -30601  || test == 'FD8877') {  // bouton 2

      digitalWrite(redPin, HIGH);
      digitalWrite(greenPin, HIGH);
      digitalWrite(bluePin, LOW);
      irrecv.resume(); // Receive the next value

    }
    else if (test == 18615   || test == 'FD48B7') {  // bouton 3

      digitalWrite(redPin, LOW);
      digitalWrite(greenPin, HIGH);
      digitalWrite(bluePin, HIGH);
      irrecv.resume(); // Receive the next value


    }
    else if (test == 10455   || test == 'FD28D7') {  // bouton 4

      digitalWrite(redPin, LOW);
      digitalWrite(greenPin, LOW);
      digitalWrite(bluePin, LOW);
      irrecv.resume(); // Receive the next value

    }
    else{ // allume aléatoire des rgb piranha
      Serial.println(test);
      int rando = random(500);
      analogWrite(redPin, rando);
      Serial.println(rando);
      analogWrite(greenPin, rando +12);
      Serial.println(rando + 12);
      analogWrite(bluePin, rando + 56);
      Serial.println(rando + 56);
      irrecv.resume(); // Receive the next value
    }
  }

}
AUCUNE AIDE PAR MP

skywodd

D'accord j'avais pas compris que le bouton "0" était sur la télécommande IR ^^

Donc en gros quand on appui sur "0" une boucle for démarre et tu veux pouvoir l'arrêter ?
Code: [Select]
if (test == 12495) {  // bouton 0
      for ( int i = -1;i < 3024; i++) {
        digitalWrite(redPin, i);
        digitalWrite(greenPin, i + 12);
        digitalWrite(bluePin, i + 56);
        irrecv.resume(); // Receive the next value
        delay (5);
      }
    }


Code: [Select]
irrecv.resume(); // Receive the next value
aprés cette ligne il faudrait que tu fasse un if pour tester si tu dois sortir de la boucle :
Code: [Select]
if(irrecv.decode(&results) && results.value != 12495) break; // si on appui sur un bouton autre que "0" break -> sort du for

Je sais pas si c'est ce que tu voulais faire ?
Des news, des tutos et plein de bonnes choses sur http://skyduino.wordpress.com !

infobarquee

si, mais cela n'arrête pas la boucle.
j'ai essayé avec une boucle while aussi en affichant le résultat, mais c'est comme si aucune réception ne se faisait de la télécommande.

je bute sur ce petit truc qui doit être d'une simplicité enfantine.
AUCUNE AIDE PAR MP

osaka

#5
Nov 03, 2011, 03:47 pm Last Edit: Nov 03, 2011, 04:01 pm by osaka Reason: 1
Peut être en n'utilisant pas de boucle tout simplement ?
Je sais pas vraiment quel est la condition d'arrêt ? je suppose que c'est temps que le dernier appuis bouton est = 12495 ?

test et i serait global
Code: [Select]

.
.
.
    if (test == 12495)
    {  // bouton 0
      if(i < 3024)
      {
        digitalWrite(redPin, i);
        digitalWrite(greenPin, i + 12);
        digitalWrite(bluePin, i + 56);
        irrecv.resume(); // Receive the next value
        delay (5);
        ++i;
      }
      else
      {
        test = 0;
        i = -1;
      }
    }
    else
    {
      i = -1;
    }

    if (test == 2295 || test == 'FD08F7')
    {  // bouton 1

      digitalWrite(redPin, HIGH);
      digitalWrite(greenPin,LOW);
      digitalWrite(bluePin, HIGH);
      irrecv.resume(); // Receive the next value
      test = 0; // remettre a 0 pour pas qu'il soit de nouveau pris en compte

    }
.
.
.


C'est sens doute pas exactement ça mais c'est le principe pour ne pas ce retrouver bloquer par une boucle empêchant le reste du code.

infobarquee

mon but est de pouvoir interrompre la boucle for à n'importe quel moment.
une fois que la boucle for est terminée, pas de problème, je peux appuyer sur un autre bouton de la télécommande pour lancer une autre phase.

j'aimerai mettre un while, même si déjà testé pour que le clignotement des leds continue tant que je n'appuie pas sur un autre touche.
d'après ce que je comprends avec les tests effectués, tant que le for est en route, aucune réception IR ne se fait.
donc si je mets un while, ca va tourner en boucle sans moyen d'interrompre cette boucle.

question :
en travaillant aec des case 1.2.3.etc... et break;
cela pourrait il simplifier la chose?
   
AUCUNE AIDE PAR MP

osaka

#7
Nov 03, 2011, 04:40 pm Last Edit: Nov 03, 2011, 04:47 pm by osaka Reason: 1

mon but est de pouvoir interrompre la boucle for à n'importe quel moment.

Le problème c'est qu'il faut un évènement pour pouvoir sortir de ta boucle à n'importe quel moment et cet évènement doit ce situer dans ta boucle comme le fait skywood.
Le seul problème que je vois ici c'est qu'une fois sorti de la boucle le dernier appuis à disparut puisque capté dans la boucle, voir aussi la condition du if je sais pas trop bien comment fonctionne cette lib ir.
results.value renvoie quoi comme valeur lorsqu'il n'y a pas d'appuis ?
result est une structure ?
test=results.value, HEX; bizarerie ?


une fois que la boucle for est terminée, pas de problème, je peux appuyer sur un autre bouton de la télécommande pour lancer une autre phase.

j'aimerai mettre un while, même si déjà testé pour que le clignotement des leds continue tant que je n'appuie pas sur un autre touche.
d'après ce que je comprends avec les tests effectués, tant que le for est en route, aucune réception IR ne se fait.
donc si je mets un while, ca va tourner en boucle sans moyen d'interrompre cette boucle.


ne pas oublier que loop est déjà une boucle (infinie), le code que je t'ai montré est presque identique à faire un for ou while dedans sauf qu'il n'empêche pas le reste de fonctionné.


question :
en travaillant aec des case 1.2.3.etc... et break;
cela pourrait il simplifier la chose?


Sans doute plus propre mais ce genre de condition multiple "if (test == 2295 || test == 'FD08F7') " je pense pas que ça marcherais.
tu pourais également plutôt créer des fonctions pour les actions (répétitif ?) genre :

Code: [Select]

void action1()
{
     digitalWrite(redPin, HIGH);
     digitalWrite(greenPin,LOW);
     digitalWrite(bluePin, HIGH);
     irrecv.resume(); // Receive the next value
}

skywodd


test=results.value, HEX; bizarerie ?

Tient je l'avais pas vu ça ... effectivement c'est bizarre.
C'est une tentative conversion en hexa ?!



question :
en travaillant aec des case 1.2.3.etc... et break;
cela pourrait il simplifier la chose?


Sans doute plus propre mais ce genre de condition multiple "if (test == 2295 || test == 'FD08F7') " je pense pas que ça marcherais.

Je devais pas avoir les yeux en face des trous pour pas voir ça non plus :
if (test == 2295 || test == 'FD08F7'), une valeur en hexa entre simple quote ... hein!?
Ce serait pas plutôt 0xFD08F7 par hasard ...

Sinon en soi c'est faisable comme ça :
Code: [Select]
case 2295 :
case 'FD08F7':
//quelquechose
break;

Que test soit égale à 2295 ou 'FD08F7' le code sera exécuté.

@infobarquee tu aurai pas fait un gros mélange entre valeur numérique, hexa et caractères !?
Des news, des tutos et plein de bonnes choses sur http://skyduino.wordpress.com !

taddot

Et pourquoi pas utiliser une interruption ?


infobarquee

je me suis inspiré du code démo de IRrevDemo
Code: [Select]
void loop() {
  if (irrecv.decode(&results)) {
    Serial.println(results.value, HEX);
    irrecv.resume(); // Receive the next value

ce qui me renvoie par exemple
Code: [Select]
FD8877
FD30CF
FFFFFFFF

donc ca coince quelque part pour récupérer une bonne valeur si on appuie trop longtemps sur une touche.
en ajoutant ma bidouille
Code: [Select]
Serial.println(results.value, HEX);
     test=results.value, HEX;
      Serial.println(test);

ca me renvoie plus d'infos
Code: [Select]
FD30CF

12495




pour la valeur hexa dont j'ai pas trop l'habitude, je me suis servit du php en supposant que l'appuie sur une touche était en fait une requete.
d'ou le
test=results.value, HEX; =>>renvoie 12495 par exemple pour une touche 0
if (test == 2295 || test == 'FD08F7')

donc, pour en revenir à mon problème, tout fonctionne bien, par contre si je veux lancer le clignotement en continu, je peux plus rien faire.
dans la console, lorsque le for est lancé, je n'ai que le 12495 qui tourne, même si j'appuie sur une autre touche pour arrêter la boucle.
un if (irrecv.decode(&results)) && (results.value, HEX) != 1495){break;}
me bloque le clignotement carrément et se met en attente, même avec un else{delay(5);}
une interruption, pourquoi pas, il me faut juste quelque chose qui puisse déclencher la réception de la commande pour stopper.

en php, ca pose pas de problème, on fait la boucle avec un for ou while et si pression de touche, ca bascule ailleurs.
là, je vois pas trop pourquoi l'appuie n'est pas pris en compte dans la boucle.




AUCUNE AIDE PAR MP

osaka

#11
Nov 03, 2011, 06:47 pm Last Edit: Nov 03, 2011, 07:35 pm by osaka Reason: 1

je me suis inspiré du code démo de IRrevDemo
Code: [Select]
void loop() {
  if (irrecv.decode(&results)) {
    Serial.println(results.value, HEX);
    irrecv.resume(); // Receive the next value

ce qui me renvoie par exemple
Code: [Select]
FD8877
FD30CF
FFFFFFFF



attention ce que tu vois sur le port série n'est que l'interprétation ascii hexa de la valeur ressue.
Donc ce n'est pas 'FD08F7' que tu dois comparé mais 0x08f7 (! je sais pas d'où il vient mais il y a un FD en trop dans ta sortie série)


donc ca coince quelque part pour récupérer une bonne valeur si on appuie trop longtemps sur une touche.
en ajoutant ma bidouille
Code: [Select]
Serial.println(results.value, HEX);
     test=results.value, HEX;
      Serial.println(test);

ca me renvoie plus d'infos
Code: [Select]
FD30CF

12495


HEX n'est pas une fonction, mais une constante. 
dans ton cas ici elle n'a aucun effet.
Pour ton problème c'est plutôt la gestion d'attente entre deux commande le problème, il me semble qu'une télécommande envoie un code appui et un au relâchement ? (vraiment pas certain mais ça me dit quelque chose)


pour la valeur hexa dont j'ai pas trop l'habitude, je me suis servit du php en supposant que l'appuie sur une touche était en fait une requete.
d'ou le
test=results.value, HEX; =>>renvoie 12495 par exemple pour une touche 0
if (test == 2295 || test == 'FD08F7')



J'ai du mal a voir le lien entre valeur hexa et requête (ici il s'agit d'évenement) ?
Tu peux recevoir 2295 ou 0x08f7 c'est pareil, mais ton 'FD08F7' en sortie série est une chaine de caractère et ne correspondra jamais à la valeur reçue.
(! contrairement à php 'a' n'est pas la même chose que "a", ' a' est un caractère "a" pour une chaine)


donc, pour en revenir à mon problème, tout fonctionne bien, par contre si je veux lancer le clignotement en continu, je peux plus rien faire.
dans la console, lorsque le for est lancé, je n'ai que le 12495 qui tourne, même si j'appuie sur une autre touche pour arrêter la boucle.
un if (irrecv.decode(&results)) && (results.value, HEX) != 1495){break;}
me bloque le clignotement carrément et se met en attente, même avec un else{delay(5);}
une interruption, pourquoi pas, il me faut juste quelque chose qui puisse déclencher la réception de la commande pour stopper.

en php, ca pose pas de problème, on fait la boucle avec un for ou while et si pression de touche, ca bascule ailleurs.
là, je vois pas trop pourquoi l'appuie n'est pas pris en compte dans la boucle.



La raison est que ton arduino ne gère pas les thread, tu ne peux pas faire 2 action en simultané.
http://fr.wikipedia.org/wiki/Multithreading
Ici on va dire que tu n'a qu'un seul thread la fonction loop (qui est une boucle infinie) si tu fais une boucle dedans le reste du code ne sera exécute qu'une fois sorti de ta boucle, même les événements ne seront vu qu'une fois le reste du code effectué d’où mon exemple sans boucle.
Dans la fonction loop chaque ligne de code que tu mets sont exécuté l'une après l'autre à chaque, une fois arrivé à la fin c'est reparti pour un tour et on reviens au début de la fonction et ainsi de suite indéfiniment.
http://www.mon-club-elec.fr/pmwiki_reference_arduino/pmwiki.php?n=Main.Loop
Donc arrivé à ta boucle be rien ne se passe même le "test=results.value" plus haut, temps que tu n'as pas fini.
php c'est bien joli ça te prémâche même tes type de variables mais tu peux passer ton tour concernant le code de l'arduino, je dirais que c'est vraiment pas le langage de référence quand tu veux vraiment apprendre la programmation même les base.
Oublie php, ton pc, ton clavier, windows,  etc ... il y a trop de différence que pour t'en servir comme référence.

infobarquee

#12
Nov 03, 2011, 07:58 pm Last Edit: Nov 03, 2011, 09:01 pm by Jean-François Reason: 1
Quote
Donc ce n'est pas 'FD08F7' que tu dois comparé mais 0x08f7 (! je sais pas d'où il vient mais il y a un FD en trop dans ta sortie série)

c'est ce que renvoit l'exemple dans l'IDE arduino, avec la télécommande de ma tv, ca renvoit 0 pour chaque touches.
celle que j'utilise est la même que celle ci http://www.robotshop.com/dfrobot-ir-kit-arduino.html
comme je l'ais dit, l'hexa, n'est pas mon fort.

Quote
La raison est que ton arduino ne gère pas les thread, tu ne peux pas faire 2 action en simultané.

voila, j'ai ma réponse, donc impossible d'arrêter une boucle ou un évènement qui est en route.
c'est une "fonction" après l'autre, mais pas 2 en même temps.

Quote
php c'est bien joli ça te prémâche même tes type de variables mais tu peux passer ton tour concernant le code de l'arduino, je dirais que c'est vraiment pas le langage de référence quand tu veux vraiment apprendre la programmation même les base.

c'est pas forcément la référence, mais ca peut aider dans des conditions ou un schéma de programmation logique.
ca ne fait qu'une semaine que je suis sur l'arduino, donc on ne peut tout connaitre du jour au lendemain, certaines questions se posent, même en lisant les docs récupérées sur internet.

Quote
Oublie php, ton pc, ton clavier, windows

on va éviter d'oublier le pc et le clavier, ca sert pour programmer quand même :), par contre, windows, ca fait un bail que je l'ai oublié et bien content ;)

donc pas de solution à ce problème qui n'est pas prévu dans l'utilisation de l'arduino.
AUCUNE AIDE PAR MP

osaka

#13
Nov 03, 2011, 08:36 pm Last Edit: Nov 03, 2011, 09:11 pm by Jean-François Reason: 1

comme je l'ais dit, l'hexa, n'est pas mon fort.


Ce n'est pas vraiment une question d'être fort en hexa ou pas, c'est juste une interprétation d'un type de donnée.
Ici si utilisé l'hexa te dérange rien ne t'empêche d'afficher ta valeur en décimale, donc tu ignores les '08F7' et tu utilises son équivalent en base10 2295.
Serial.println(test, DEC) et non Serial.println(test, HEX)


Quote
La raison est que ton arduino ne gère pas les thread, tu ne peux pas faire 2 action en simultané.

voila, j'ai ma réponse, donc impossible d'arrêter une boucle ou un évènement qui est en route.
c'est une "fonction" après l'autre, mais pas 2 en même temps.

La seule façon d'arrêter ta boucle est de capturer cet événement dans ta boucle même, comme l'a fait skywood.


Quote
php c'est bien joli ça te prémâche même tes type de variables mais tu peux passer ton tour concernant le code de l'arduino, je dirais que c'est vraiment pas le langage de référence quand tu veux vraiment apprendre la programmation même les base.

c'est pas forcément la référence, mais ca peut aider dans des conditions ou un schéma de programmation logique.
ca ne fait qu'une semaine que je suis sur l'arduino, donc on ne peut tout connaitre du jour au lendemain, certaines questions se posent, même en lisant les docs récupérées sur internet.

C'est pour cette dernière raison que je dit d'oublier php et qu'il n'est pas adapté même pour les base.
Pour un schéma de programmation logique, les premiers mois de mon graduat c'était pseudo code sur papier obligatoire, aucun pc allumé   :smiley-sweat:.


Quote
Oublie php, ton pc, ton clavier, windows

on va éviter d'oublier le pc et le clavier, ca sert pour programmer quand même :), par contre, windows, ca fait un bail que je l'ai oublié et bien content ;)


Là tu me piège  :smiley-mr-green:


donc pas de solution à ce problème qui n'est pas prévu dans l'utilisation de l'arduino.


Des solutions on t'en a donné skywood et moi, soit tu intègres un évènement dans ta boucle soit tu la supprimes et tu agis avec la "boucle" loop .
Réfléchis bien, prend ton temps ça va venir , on a pas tous la science infuse. (moi je suis une buse en électronique)  
;)

infobarquee

Code: [Select]
La seule façon d'arrêter ta boucle est de capturer cet événement dans ta boucle même, comme l'a fait skywood.
si tu parle de la solution donnée dans le #3 ca ne fonctionne pas
j'ai placé à tous les endroits possibles cette ligne dans ma boucle for
Code: [Select]
if(irrecv.decode(&results) && results.value != 12495) break; // si on appui sur un bouton autre que "0" break -> sort du for

la solution case idem.
j'ai pensé à utiliser la lib scheduler, mais sans résultat probant non plus. elle permet de vérifier à interval de temps un autre void qui lui pourrait contenir cet arrêt si un appuie sur une touche de la telecommande a eu lieu et est gardé en mémoire.

:smiley-mr-green: hé oui, même si je dois me tenir au courant sur windows pour les dépannages que je fais, je préfère largement mon nunux depuis plusieurs années.
tous mes servers sont sont debian et bsd, pas sous windaub server ;)
AUCUNE AIDE PAR MP

Go Up