Sortir d'une boucle par bouton infrarouge

Bonjour à tous. Je viens solliciter votre aide. Cela fait 3 jours que je m’arrache les cheveux pour trouver une solution à mon problème sans succès. Je cherche à piloter une bande de leds WS2812B à l’aide d’une télécommande infrarouge. Je suis parvenu à les faire s’allumer de la couleur voulue et à modifier leur luminosité non sans mal mais pour cette partie ça fonctionne. Mais lorsque j’essaye d’intégrer une animation les choses se corsent. Soit je reste bloqué dans la boucle, soit l’animation ne se fait qu’une fois, soit il ne se passe rien. J’ai tenté une multitude de choses mais rien n’y fait.
Je vous joint la partie du code qui pose problème et je peux si besoin poster le code complet.

void breathFunction(int breathDelay)
{
  if (irrecv.decode(&results))
  {
    while (results.value == NULL)
    {
      for (int i=brightness; i>minBrightness; i--) 
      { 
        pixels.setBrightness(i); 
        pixels.show(); 
        delay(breathDelay); 
      }
      
      for (int i=minBrightness; i<brightness; i++) 
      { 
        pixels.setBrightness(i); 
        pixels.show(); 
        delay(breathDelay); 
      }
      
      if (results.value == &results)
      {
        break;
      }
      
 
    }
    irrecv.resume();

    irrecv.enableIRIn();
  }
}

J’ai vraiment tenté une multitude de choses et toute aide serait la bienvenue. Je ne suis pas très doué en programmation alors soyez indulgents.
Merci.
Yan.

il vous faut “casser” les séquences d’affichages en petit morceau et utilisant millis() au lieu de rester coincé dans une boucle for… → virez tous les delay()

ça pourrait ressembler à cela pour faire clignoter la LED de la carte toute les 2s (non testé, tapé ici)

#include <IRremote.h>
int RECV_PIN = 11;
IRrecv irrecv(RECV_PIN);
decode_results results;

unsigned long chrono;
bool clignote;


void setup()
{
  pinMode(LED_BUILTIN, OUTPUT);
  digitalWrite(LED_BUILTIN, LOW); // on éteint
  irrecv.enableIRIn();
  clignote = false;
}

void loop() {

  // TEST DE LA TELECOMMANDE
  if (irrecv.decode(&results)) {
    if (results.value == 0x1234) { // remplacer 0x1234 par la valeur reçue qui déclenche ou arrête 
      digitalWrite(LED_BUILTIN, LOW); // on éteint
      clignote = !clignote;
      if (clignote) chrono = millis();
    }
    irrecv.resume(); // prêt pour la prochaine valeur
  }

  // TEST POUR ANIMATION
  if (clignote) { // si on est en mode animation
    if (millis() - chrono >= 1000) { // si c'est le moment de faire la prochaine animation
      if (digitalRead(LED_BUILTIN) == HIGH) digitalWrite(LED_BUILTIN, LOW); // on éteint
      else digitalWrite(LED_BUILTIN, HIGH); // on allume
      chrono = millis(); // on se souvient du dernier moment
    }
  }

  // ICI ON PEUT FAIRE AUTRE CHOSE (SI PAS TROP LONG)


}

D'accord, je vais creuser dans cette direction. Je n'ai encore jamais utilisé millis() mais d'après ce que j'en vois ça fonctionne différemment de delay()

J'ai trouvé comment sortir de la boucle mais cela demande d'être en fin de boucle pour que ça fonctionne. millis me permettrais de rendre la sortie possible à tout moment.

Merci

oui l'idée c'est de regarder si c'est le moment de faire "une étape" de votre animation, si oui vous faites l'action, si non - vous allez faire autre chose

Bonjour. Merci beaucoup pour le coup de pouce, grâce à vous j’ai pu solutionner mon problème et garder mes cheveux :slight_smile: .
Je peux maintenant lancer mon animation et en sortir à loisir sans attendre la fin de la boucle. Je dois par contre garder en condition l’appui de la télecommande, la condition bool ne fonctionne pas et je ne m’explique pas pourquoi, mais ça fonctionne comme ça alors je ne m’en pleins pas.

J’ai cependant un nouveau problème. lorsque je me trouve dans la boucle while() le premier appui sur un bouton de la télécommande me rapporte une valeur aléatoire un peu farfelue et m’oblige à appuyer une deuxième fois pour avoir la bonne valeur. Problème que je ne rencontre pas dans la boucle principale.

Savez-vous si il est possible dans la librairie IRremote.h de supprimer FFFFFF lors d’un appui long?

Encore merci pour votre aide.
Yan.

void breathFunction()
{

  while (results.value == 0xf76897)
  {

    currentMillis = millis();

    if (currentMillis - startMillis >= interval) {
      fadebrightness = fadebrightness + fadeAmount;
      startMillis = millis();


      if (fadebrightness <= lowerLimit )
      {
        fadebrightness = lowerLimit;
        fadeAmount = -fadeAmount;
      }

      if (fadebrightness >= brightness )
      {
        fadebrightness = brightness;
        fadeAmount = -fadeAmount;
      }

      pixels.setBrightness(fadebrightness);
      pixels.show();
    }

    Serial.println(results.value, HEX);

    if (irrecv.decode(&results))
    {
      if (results.value != 0xf76897)
      {
        pixels.setBrightness(brightness);
      }

      irrecv.resume();
      irrecv.enableIRIn();

    }
  }

}

cette partie là est louche (ou vos constantes sont mal nommées)

      if (fadebrightness <= lowerLimit ) {
        fadebrightness = lowerLimit;
        fadeAmount = -fadeAmount;
      }

      if (fadebrightness >= brightness )
      {
        fadebrightness = brightness;
        fadeAmount = -fadeAmount;
      }

→ pourquoi comparez vous avec brightness? il ne faudrait pas plutôt une constante du genre upperLimit pour correspondre avec votre lowerLimit ?

sinon

  • currentMillis ne sert à rien, utilisez directement millis() dans la formule    if (millis() - startMillis >= interval) {ou alors au lieu de startMillis = millis();faites un startMillis = currentMillis;

  • pourquoi avez vous un irrecv.enableIRIn();? vous ne l’avez pas fait dans le setup() ? vous désactivez l’IR ?

  • je ne vois pas pourquoi il y a un while() en haut? si vous appuyez sur une mauvaise touche, est-ce que ça fait ce que vous voulez ?

Faudrait voir le code global mais pour moi c’est pas idéal ce que vous avez fait. il faut vraiment séparer la réception IR de l’animation.

Bonjour.

En fait j’utilise brightness pour que la luminosité maximum de l’animation soit celle réglée précédemment.

Je vous avoue que pour millis() et l’utilisation de la bibliothèque je vais avoir besoin de creuser encore un peut le sujet pour tout comprendre.

Pour irrecv.enableIRIn(); le déclarer dans le setup suffit pour qu’il soit actif tout le temps?

Pour le while() si je ne l’utilise pas l’animation ne se produit qu’une seule fois.

Je vous joint le code. Ne soyez pas trop dur, je débute dans l’exercice :slight_smile:

A savoir que tout ça va encore beaucoup évoluer puisque je compte aussi piloter les ventilateurs qui seront éclairés par ces leds et y intégrer l’écran qui me rapporte la température et les fréquences CPU et GPU

#include <Adafruit_NeoPixel.h>
#include <IRremote.h>

#define PIXEL_PIN 5
#define PIXEL_COUNT 11

Adafruit_NeoPixel pixels = Adafruit_NeoPixel(PIXEL_COUNT, PIXEL_PIN, NEO_GRB + NEO_KHZ800);

int RECV_PIN = 11;

unsigned long lastCode;

float up = 12.75;
float down = 12.75;
int upperLimit = 255;
int lowerLimit = 1;
int brightness = 255;
int minBrightness = 20;


int fadeAmount = 1;
int interval = 10;
int fadebrightness = 50;
int flashInterval = 1000;
int flashLowerLimit = 1;
int flashBrightness;
int currentMillis;
int startMillis;

int RED[3] = {255, 0, 0};
int GREEN[3] = {0, 255, 0};
int BLUE[3] = {0, 0, 255};
int MAGENTA[3] = {255, 0, 255};
int ORANGE[3] = {255, 40, 0};
int CYAN[3] = {0, 255, 255};
int PINK[3] = {255, 0, 100};
int YELLOW[3] = {255, 125, 0};
int PURPLE[3] = {128, 0 , 128};
int WHITE[3] = {255, 255, 255};
int OFF[3] = {0, 0, 0};

IRrecv irrecv(RECV_PIN);

decode_results results;

void setup()
{
  Serial.begin(9600);
  irrecv.enableIRIn();

  pixels.begin();
  pixels.setBrightness(85);
  pixels.clear();
  startMillis = millis();
}

void loop()
{

  if (irrecv.decode(&results)) {

    if (results.value == 0xFFFFFFFF)
    {
      results.value = lastCode;
    }

    if (results.value == 0xf710ef)
    {
      lastCode = results.value;
      colorChange(20, RED);
    }

    if (results.value == 0xf7906f)
    {
      lastCode = results.value;
      colorChange(20, GREEN);
    }

    if (results.value == 0xf750af)
    {
      lastCode = results.value;
      colorChange(20, BLUE);
    }

    if (results.value == 0xf730cf)
    {
      lastCode = results.value;
      colorChange(20, MAGENTA);
    }

    if (results.value == 0xf7b04f)
    {
      lastCode = results.value;
      colorChange(20, ORANGE);
    }

    if (results.value == 0xf7708f)
    {
      lastCode = results.value;
      colorChange(20, CYAN);
    }

    if (results.value == 0xf708f7)
    {
      lastCode = results.value;
      colorChange(20, PINK);
    }

    if (results.value == 0xf78877)
    {
      lastCode = results.value;
      colorChange(20, YELLOW);
    }

    if (results.value == 0xf748b7)
    {
      lastCode = results.value;
      colorChange(20, PURPLE);
    }

    if (results.value == 0xf7c837)
    {
      lastCode = results.value;
      colorChange(20, WHITE);
    }

    if (results.value == 0xf740bf)
    {
      lastCode = results.value;
      colorChange(20, OFF);
    }

    if (results.value == 0xf700ff)
    {
      lastCode = results.value;
      increaseFunction();
    }

    if (results.value == 0xf7807f)
    {
      lastCode = results.value;
      decreaseFunction();
    }

    if (results.value == 0xf728d7)
    {
      lastCode = results.value;
      flashFunction();
    }

    if (results.value == 0xf7a857)
    {
      lastCode = results.value;
      sparkleFunction();
    }

    irrecv.resume();

    irrecv.enableIRIn();

    Serial.println(results.value, HEX);


  }
}

void increaseFunction() {

  brightness += up;
  if (brightness > upperLimit) brightness = upperLimit;
  for (int i = 0; i < PIXEL_COUNT ; i++)
  {
    pixels.setBrightness(brightness);
  }
  pixels.show();
}

void decreaseFunction()
{
  brightness -= down;
  if (brightness < lowerLimit) brightness = lowerLimit;
  for (int i = 0; i < PIXEL_COUNT ; i++)
  {
    pixels.setBrightness(brightness);
  }
  pixels.show();
}

void colorChange(int delayTime, int COLOR[])
{
  for (int i = 0 ; i < PIXEL_COUNT ; i++)
  {
    pixels.setPixelColor(i, COLOR[0], COLOR[1], COLOR[2]);
    pixels.show();
    delay(delayTime);
  }
}

void sparkleFunction()
{

  while (results.value == 0xf7a857 || results.value == 0xffffffff)
  {

    currentMillis = millis();

    if (currentMillis - startMillis >= interval) {
      fadebrightness = fadebrightness + fadeAmount;
      startMillis = millis();


      if (fadebrightness <= lowerLimit )
      {
        fadebrightness = lowerLimit;
        fadeAmount = -fadeAmount;
      }

      if (fadebrightness >= brightness )
      {
        fadebrightness = brightness;
        fadeAmount = -fadeAmount;
      }

      pixels.setBrightness(fadebrightness);
      pixels.show();
    }

    Serial.println(results.value, HEX);

    if (irrecv.decode(&results))
    {
      if (results.value != 0xf7a857)
      {
        pixels.setBrightness(brightness);
      }

      irrecv.resume();
      irrecv.enableIRIn();

    }
  }

}

void flashFunction()
{
  while (results.value == 0xf728d7 || results.value == 0xffffffff)
  {

    currentMillis = millis();

    if (currentMillis - startMillis >= flashInterval) {
      startMillis = millis();

      if (flashBrightness <= flashLowerLimit )
      {
        flashBrightness = brightness;
      }

      else
      {
        flashBrightness = flashLowerLimit;
      }

      pixels.setBrightness(flashBrightness);
      pixels.show();
    }

    Serial.println(results.value, HEX);

    if (irrecv.decode(&results))
    {
      if (results.value != 0xf728d7)
      {
        pixels.setBrightness(brightness);
      }

      irrecv.resume();
      irrecv.enableIRIn();

    }
  }
}

Pour le while vous dépendez de la mémorisation de la dernière commande reçue. Si vous tapez une mauvaise touche ça va mettre le bazar, vaudrait mieux avoir un booléen qui dit si vous êtes en mode animation ou pas

Pour le nom de variable, si c’est une borne Max alors le nom est mal choisi

Pour le irrecv.enableIRIn(), vous avez essayé? (La doc dit « Begin the receiving process. This will enable the timer interrupt which consumes a small amount of CPU every 50 µs.)

Bonjour, désolé pour la réponse tardive. J’ai mis un peu de temps à comprendre mais je pense que c’est bon. Tout fonctionne bien maintenant, mis à part les commandes farfelues qui arrivent aléatoirement de la télécommande. Il me reste à trouver un moyen de fixer un temps de cycle d’animation quelle que soit la luminosité maximum préréglée.
Encore merci, sans votre aide j’aurais surement abandonné.

#include <Adafruit_NeoPixel.h>
#include <IRremote.h>

#define PIXEL_PIN 5
#define PIXEL_COUNT 14

Adafruit_NeoPixel pixels = Adafruit_NeoPixel(PIXEL_COUNT, PIXEL_PIN, NEO_GRB + NEO_KHZ800);

int RECV_PIN = 11;

unsigned long lastCode;

float up = 12.75f;
float down = 12.75f;
int upperLimit = 255;
int lowerLimit = 1;
int brightness = 85;
int minBrightness = 20;

int currentMillis;

int fadeAmount = 1;
int interval = 10;
int fadebrightness = 50;
int sparkleUpperLimit;
unsigned long startMillisSparkle;

int flashInterval = 1000;
int flashLowerLimit = 1;
int flashUpperLimit;
int flashBrightness;
int startMillisFlash;

int RED[3] = {255, 0, 0};
int GREEN[3] = {0, 255, 0};
int BLUE[3] = {0, 0, 255};
int MAGENTA[3] = {255, 0, 255};
int ORANGE[3] = {255, 40, 0};
int CYAN[3] = {0, 255, 255};
int PINK[3] = {255, 0, 100};
int YELLOW[3] = {255, 125, 0};
int PURPLE[3] = {128, 0 , 128};
int WHITE[3] = {255, 255, 255};
int OFF[3] = {0, 0, 0};

bool sparkle;
bool flash;

IRrecv irrecv(RECV_PIN);

decode_results results;

void setup()
{
  Serial.begin(9600);
  irrecv.enableIRIn();

  pixels.begin();
  pixels.setBrightness(85);
  pixels.clear();
  startMillisSparkle = millis();
  sparkle = false;
}

void loop()
{
//IR Input
  if (irrecv.decode(&results)) {

    if (results.value == 0xFFFFFFFF)
    {
      results.value = lastCode;
    }

    if (results.value == 0xf710ef)
    {
      lastCode = results.value;
      colorChange(20, RED);
      pixels.setBrightness(brightness);
      pixels.show();
    }

    if (results.value == 0xf7906f)
    {
      lastCode = results.value;
      colorChange(20, GREEN);
      pixels.setBrightness(brightness);
      pixels.show();
    }

    if (results.value == 0xf750af)
    {
      lastCode = results.value;
      colorChange(20, BLUE);
      pixels.setBrightness(brightness);
      pixels.show();
    }

    if (results.value == 0xf730cf)
    {
      lastCode = results.value;
      colorChange(20, MAGENTA);
      pixels.setBrightness(brightness);
      pixels.show();
    }

    if (results.value == 0xf7b04f)
    {
      lastCode = results.value;
      colorChange(20, ORANGE);
      pixels.setBrightness(brightness);
      pixels.show();
    }

    if (results.value == 0xf7708f)
    {
      lastCode = results.value;
      colorChange(20, CYAN);
      pixels.setBrightness(brightness);
      pixels.show();
    }

    if (results.value == 0xf708f7)
    {
      lastCode = results.value;
      colorChange(20, PINK);
      pixels.setBrightness(brightness);
      pixels.show();
    }

    if (results.value == 0xf78877)
    {
      lastCode = results.value;
      colorChange(20, YELLOW);
      pixels.setBrightness(brightness);
      pixels.show();
    }

    if (results.value == 0xf748b7)
    {
      lastCode = results.value;
      colorChange(20, PURPLE);
      pixels.setBrightness(brightness);
      pixels.show();
    }

    if (results.value == 0xf7c837)
    {
      lastCode = results.value;
      colorChange(20, WHITE);
      pixels.setBrightness(brightness);
      pixels.show();
    }

    if (results.value == 0xf740bf)
    {
      lastCode = results.value;
      colorChange(20, OFF);
    }

    if (results.value == 0xf700ff)
    {
      lastCode = results.value;
      increaseFunction();
    }

    if (results.value == 0xf7807f)
    {
      lastCode = results.value;
      decreaseFunction();
    }

    if (results.value == 0xf728d7)
    {
      lastCode = results.value;
      flash = true;
    }

    if (results.value != 0xf728d7)
    {
      lastCode = results.value;
      flash = false;
    }

    if (results.value == 0xf7a857)
    {
      lastCode = results.value;
      sparkle = true;
      pixels.setBrightness(brightness);

    }

    if (results.value != 0xf7a857)
    {
      lastCode = results.value;
      sparkle = false;
      pixels.setBrightness(brightness);

    }

    irrecv.resume();

    Serial.println(results.value, HEX);

  }

  // Animation Sparkle
  if (sparkle)
  {
    sparkleUpperLimit = brightness;

    if (millis() - startMillisSparkle >= interval) {
      fadebrightness = fadebrightness + fadeAmount;
      startMillisSparkle = millis();


      if (fadebrightness <= lowerLimit )
      {
        fadebrightness = lowerLimit;
        fadeAmount = -fadeAmount;
      }

      if (fadebrightness >= sparkleUpperLimit )
      {
        fadebrightness = sparkleUpperLimit;
        fadeAmount = -fadeAmount;
      }

      pixels.setBrightness(fadebrightness);
      pixels.show();
    }
  }

//Animation Flash
  if (flash)
  {
    currentMillis = millis();
    flashUpperLimit = brightness;

    if (currentMillis - startMillisFlash >= flashInterval) {
      startMillisFlash = millis();

      if (flashBrightness <= flashLowerLimit )
      {
        flashBrightness = flashUpperLimit;
      }

      else
      {
        flashBrightness = flashLowerLimit;
      }

      pixels.setBrightness(flashBrightness);
      pixels.show();
    }
  }
}


void increaseFunction() {

  brightness += up;
  if (brightness > upperLimit) brightness = upperLimit;
  for (int i = 0; i < PIXEL_COUNT ; i++)
  {
    pixels.setBrightness(brightness);
  }
  pixels.show();
}

void decreaseFunction()
{
  brightness -= down;
  if (brightness < lowerLimit) brightness = lowerLimit;
  for (int i = 0; i < PIXEL_COUNT ; i++)
  {
    pixels.setBrightness(brightness);
  }
  pixels.show();
}

void colorChange(int delayTime, int COLOR[])
{
  for (int i = 0 ; i < PIXEL_COUNT ; i++)
  {
    pixels.setPixelColor(i, COLOR[0], COLOR[1], COLOR[2]);
    pixels.show();
    delay(delayTime);
  }
}

Bravo!