Réception IR inconstante dans programme

Bonjour à tous !

J'avance un peu dans mon projet, et je vous partagerai tout une fois ce dernier terminé.
Je rencontre néanmoins un problème lors de l'utilisation d'une télécommande et d'un récepteur infrarouge au sein d'un programme de manipulation de bandeaux LEDs.
En effet, "à blanc", quand je cherche le code hexa correspondant aux différentes touches, ces derniers apparaissent constants sur le moniteur série.

Cependant, lorsque je l'utilise dans mon code, les résultats (pour une même touche), changent constamment, ce qui rend l'utilisation impossible... J'ai beau jongler avec les différentes versions et syntaxes de la librairie, rien n'y fait.
Exemple en appuyant une dizaine de fois sur "2" :

Voici mon code (je mets deux codes de LEDs pour exemple) :

#include <FastLED.h>
#include <IRremote.h>

//=========================
//Definition pour IRremote
//=========================
const int RECV_PIN = 12;
IRrecv irrecv(RECV_PIN);
decode_results results;
unsigned long key_value = 0;
int currentFunction = 1; // start with function1()

//=========================
//Definition pour FastLED
//=========================
// On définit les PINS sur lesquels sont connectés les bandeaux
const int ledStrip1 = 2;
const int ledStrip2 = 4;
const int ledStrip3 = 6;
const int ledStrip4 = 8;
const int ledStrip5 = 10;

// Nombre de LEDs par bandeau
const int numLEDs = 29;

// Define the starting values
int hue = 0;
int frame = 0;

// Define the arrays of LED colors for each strip
CRGB leds1[numLEDs];
CRGB leds2[numLEDs];
CRGB leds3[numLEDs];
CRGB leds4[numLEDs];
CRGB leds5[numLEDs];


//==========================
//==========SETUP===========
//==========================
void setup() {
  delay(2000); // sanity delay
  
  //Setup pour IRremote
  //=====================
  Serial.begin(9600);
  irrecv.enableIRIn();
  irrecv.blink13(true);
  
  //Setup pour FastLED
  //=====================
  FastLED.addLeds<WS2812B, ledStrip1, GRB>(leds1, numLEDs);
  FastLED.addLeds<WS2812B, ledStrip2, GRB>(leds2, numLEDs);
  FastLED.addLeds<WS2812B, ledStrip3, GRB>(leds3, numLEDs);
  FastLED.addLeds<WS2812B, ledStrip4, GRB>(leds4, numLEDs);
  FastLED.addLeds<WS2812B, ledStrip5, GRB>(leds5, numLEDs);
}


void loop()
{
  if (irrecv.decode(&results)){
    
    Serial.println(results.value, HEX);
    
    if (results.value == 0XFFFFFFFF){
          results.value = key_value;}
    
      switch (results.value) {
      case 0xFF30CF:
        currentFunction = 1;
        break;
      case 0xFF18E7:
        currentFunction = 2;
        break;
      case 0xFF7A85:
        propulsion() ; // pour tester si le problème n'était pas le switch, mais ce n'est pas le cas...
        break;
      case 0xFF10EF:
        currentFunction = 4;
        break;
      case 0xFF38C7:
        currentFunction = 5;
        break;
      case 0xFF5AA5:
        currentFunction = 6;
        break;
      case 0xFF42BD:
        currentFunction = 7;
        break;
      case 0xFF4AB5:
        currentFunction = 8;
        break;
      case 0xFF52AD:
        currentFunction = 9;
        break;
      case 0xFF6897:
        currentFunction = 10;
        break;
      case 0xFFE01F:
        currentFunction--;
        if (currentFunction < 1) {
          currentFunction = 10;
        }
        break;
      case 0xFF906F:
        currentFunction++;
        if (currentFunction > 10) {
          currentFunction = 1;
        }
        break;
      }
  key_value = results.value;
  irrecv.resume();
  }

  
  // call the current function
  switch (currentFunction) {
    case 1:
      uniforme(0, 255, 255) ;
      break;
    case 2:
      uniforme_flashs(255, 255, 255) ;
      break;
    case 3:
      propulsion() ;
      break;
    case 4:
      spirale(255, 0, 0, 255, 255, 255);
      break;
    case 5:
      rainbow() ;
      break;
    case 6:
      gradBlancOrangeAlt() ;
      break;
    case 7:
      gradJauneOrangeRougeAlt() ;
      break;
    case 8:
      bizarre() ;
      break;
    case 9:
      HautBas() ;
      break;
    case 10:
      flickering();
      break;
  }


//=====================================================================
//=====================================================================
//==========================COULEUR UNIFORME===========================
//=====================================================================
//=====================================================================
void uniforme(int r, int g, int b)
{
  for (int i = 0; i < numLEDs  ; i++)
  {
    leds1[i] = CRGB(r, g, b);
    leds2[i] = CRGB(r, g, b);
    leds3[i] = CRGB(r, g, b);
    leds4[i] = CRGB(r, g, b);
    leds5[i] = CRGB(r, g, b);
    FastLED.show();
    FastLED.setBrightness(100);
    delay(10);
  }
}

//=====================================================================
//=====================================================================
//===============================RAINBOW===============================
//=====================================================================
//=====================================================================
void rainbow()
{
  // Set all LEDs to a color based on their position and the current hue value

  for (int i = 0; i < numLEDs; i++) {
    //leds[numLEDs - 1 - i] = CHSV(0 + (i * 60 / numLEDs), 255, 255);
    //leds[numLEDs - 1 - i] = CHSV((hue + 128 + (i * 256 / numLEDs)) % 256, 200, 200);
    leds1[numLEDs - 1 - i] = CHSV(hue + (i * 256 / numLEDs), 255, 200);
    leds2[numLEDs - 1 - i] = CHSV(hue + (i * 256 / numLEDs), 255, 200);
    leds3[numLEDs - 1 - i] = CHSV(hue + (i * 256 / numLEDs), 255, 200);
    leds4[numLEDs - 1 - i] = CHSV(hue + (i * 256 / numLEDs), 255, 200);
    leds5[numLEDs - 1 - i] = CHSV(hue + (i * 256 / numLEDs), 255, 200);

  }

  // Update the LED strips
  FastLED.show();

  // Increase the hue value and wrap around if necessary
  hue+=2;
  if (hue > 255) {
    hue = 0;
  }

  // Delay for a short period of time
  delay(10);
}

Il se peut que les WS2812B mettent une pression importante sur les interruptions pendant l'affichage (désactivation des interruptions) ➜ Si pendant ce temps là un bout de signal était attendu côté infra rouge il sera perdu et donc la touche ne sera pas correctement décodée

Bonjour J-M-L,

Merci pour ta réponse ! Qu'entends-tu exactement par "interruption" ? Les "break" des "case" ? :thinking:

Bonjour martin_cm

J'ai essayé ton code, sans problème.
Comment alimentes tu tes LED?

A+
Cordialement
jpbbricole

cf par exemple LOCODUINO - Les interruptions (1)

Quand vous faites FastLED.show() la bibliothèque doit mettre à jour les LEDs des 5 bandeaux (5 x 29 Leds) . Les leds de type WS2812B nécessitent un timing bien précis pour être mis à jour et les bibliothèques bien souvent désactivent les interruptions matérielles pendant le temps de la mise à jour pour être sûr de respecter le timing.

Suivant ce que fait le reste du code et de la dépendance au fait que les interruptions sont activées, cela peut poser éventuellement un souci. Dans votre cas la bibliothèque IRremote dépend d'un timer et d'une interruption qui est déclenchée toutes les 50 µs pour échantillonner le signal IR.

Bonjour jpbbricole !

Ca peut en effet être le problème... Mes 5 bandeaux sont uniquement alimentés via les 5V de la Nano ! Ce qui ne pose aucun souci quand je n'essaye pas d'ajouter le contrôle par IR.
Merci en tout cas.

D'accord, je crois que je comprends, merci !
J'ai donc un problème de timing, qui peut en plus être aggravé par le fait qu'un de mes bandeaux est sur la broche 2... Je vois pas comment m'en sortir à ce stade donc je vais sûrement utiliser un simple bouton.
Ce qui conforte votre idée est que lorsque j'essaye sur un code plus simple (seulement 2-3 bandeaux qui s'allument avec 2-3 animations), j'ai encore des "ratés" dans la réception des signaux IR, mais moins (peut-être 1/3 alors que ça ne fonctionne jamais avec le code complet).

ça ce n'est pas bon, c'est sûr... il faut une alim dédiée.
ensuite si @jpbbricole a pu tester avec le montage et 5 bandeaux, c'est que ça passe quand même

Bonjour

La longeur des salves IR émises peut avoir son effet, j'ai le souvenir de salves nettement plus longues que d'autres selon la marque et le modèle de la télécommande.
Une salve longue risquant davantage d'interférer avec la commande des bandeaux (ceci dit je n'ai pas mis le nez dans les bibibiothèques...)

Bonjour martin_cm

Fait un test en mettant

FastLED.setBrightness(10);
ainsi, les LED consomment moins, pour voir si c'est ça.

A+
Cordialement
jpbbricole

Bonjour al1fch

Dans le cas du sketch de @martin_cm, FastLED.show(); n'est invoqué qu'une fois la touche IR décodée, donc FastLed ne devrai pas influencer?

Cordialement
jpbbricole

Bonsoir @jpbbricole

tu as sans doute raison..... je suis rarement affirmatif quand je ne fais que survoler un sujet ! ( ce qui est le cas des deux librairies en cause que j'utilse rarement pour l'une IRremote et jamais pour l'autre Fastled)

la piste d'un 5V perturbé est tentante, je ne connais pas la tolérance des TSOP au bruit sur l'alimentation

hum non, le code sépare les 2, la loop fait cela:

void loop()
{
  if (irrecv.decode(&results)) {
    // attribution de currentFunction
  }

  switch (currentFunction) {
      // appel de l'animation en fonction de current function
  }
}

donc on appelle en boucle l'animation choisie même s'il n'y a pas de nouvelles demande et la télécommande permet d'en choisir une nouvelle ➜ il faut bien que l'IR soit dispo pendant l'animation

Bonsoir J-M-L

Oui, je viens de découvrir ça.
En fait, mon premier test "positif" était faussé du fait que, comme le programme n'était pas au complet, j'avais mis switch (currentFunction) en remarque :woozy_face:

Cordialement
jpbbticole

ceci explique cela donc :slight_smile:

ces soucis de timing précis sont la raison qui me font préférer des APA102 au lieu des WS2812B (mais si c'est plus cher). Les APA102 n'ont pas de timing imposé.

1 Like

J'ai essayé de diminuer la luminosité à 10. A priori, ça ne change rien...

Le "currentFunction" a pour seul but de pouvoir utiliser les touches + et - de la télécommande pour passer d'une animation à l'autre. Si c'est effectivement le problème, je peux m'en passer. Je vais essayer directement.

Bonsoir martin_cm

currentFunction sert pour toutes les touches de la télécommande. Ton problème vient du fait que la sélection switch (currentFunction) { le show sélectionné est appelé en permanence ce qui ne laisse pas beaucoup d'espace temps pour le récepteur de la télécommande.
Il faudrait séparer cette partie et ne l'appeler que de temps en temps et ceci avec une temporisation avec millis().
Je peux essayer ça.

A+
Cordialement
jpbbricole

Il faudrait séparer cette partie et ne l'appeler que de temps en temps et ceci avec une temporisation avec millis() .

Je vais essayer de regarder ça, mais je ne vois pour l'instant pas comment sortir du switch sans arrêter l'animation en cours.

En me ramenant effectivement à un seul switch-case (sans "currentFunction", en appelant directement l'animation), je parviens à passer d'une animation à l'autre grâce aux touches numérotées directement. Cependant, ce n'est pas le cas pour toutes les animations. Quand certaines sont actives, il est très difficile voire impossible de changer à une autre. Ca rejoint ce que vous disiez avec les interruptions, il me semble.
Pour le coup, je ne sais pas du tout comment régler ce problème et je suppose qu'un bouton ne le règlerait pas... :saluting_face:

Je ne savais pas du tout, j'y penserai à l'avenir ! Merci encore.

Bonsoir martin_cm

L'idéal serait d'avoir un interrupt sur la réception IR.

A+
Cordialement
jpbbricole