Bouton momentané / timer / leds adressable

Bonjour à tous,

Je suis sur une conception d'éclairage pour des boutons de borne arcade sanwa OBSF-CR 30mm, avec des leds adressable WS2812B RGB et d'un arduino UNO .

voici le type de bouton, les leds éclaire le contour.

je souhaiterai que lorsque le joueur 1 ne touche plus par exemple au bouton "A" qu'une animation se déclenche après 5 mn.
J'ai trouvé un code que j'ai adapté pour mettre la couleur fixe que je désire sous chaque bouton,
mais je ne sais pas comment codé pour y ajouté une animation après une temporisation

voici le code utilisé pour l'éclairage fixe

#include <Adafruit_NeoPixel.h>
#ifdef __AVR__
// Requis pour 16 MHz Adafruit Trinket
#include <avr/power.h>
#endif
 
// Quelle broche de l'Arduino est connectée aux NeoPixels ?
int pin         =  5;
int pin2         =  6;
 
// Combien de NeoPixels sont attachés à l'Arduino ?
int numPixels   = 32;

 
// Format de couleur et débit de données NeoPixel.
int pixelFormat = NEO_GRB + NEO_KHZ800;
 
// Plutôt que de déclarer l'ensemble de l'objet NeoPixel ici, nous créons simplement
// un pointeur pour un, que nous allouerons ensuite plus tard
Adafruit_NeoPixel *pixels;
Adafruit_NeoPixel *pixels2;
  
void setup() {
 
  // initialisation de la connexion série
  // IMPORTANT : le terminal côté PC doit être réglé sur la même valeur.
  Serial.begin(115200);
 
 // on attent que le port de communication soit pret
  while (!Serial) {
    ;
  }
 
  // créez dynamiquement un nouvel objet NeoPixel avec ces valeurs :
  pixels = new Adafruit_NeoPixel(numPixels, pin, pixelFormat);
  pixels2 = new Adafruit_NeoPixel(numPixels, pin2, pixelFormat);
 
  pixels->begin(); // INITIALISER l'objet NeoPixel (OBLIGATOIRE)
 
  // Eteint l'ensemble des led
  pixels->clear();
  // Envoyez les couleurs de pixel
  pixels->show();
  pixels->setBrightness(255); // Set BRIGHTNESS to about 1/5 (max = 255)
  delay(25);//Pause

  pixels2->begin(); // INITIALISER l'objet NeoPixel (OBLIGATOIRE)
 
  // Eteint l'ensemble des led
  pixels2->clear();
  // Envoyez les couleurs de pixel
  pixels2->show();
  pixels2->setBrightness(255); // Set BRIGHTNESS to about 1/5 (max = 255)
  delay(25);//Pause
}
 
void loop() {
   
 
  // BT_01 Bleu
  pixels->setPixelColor(0, pixels->Color(0, 0,255));
  pixels->setPixelColor(1, pixels->Color(0, 0,255));
  pixels->setPixelColor(14, pixels->Color(0, 0,255));
  pixels->setPixelColor(15, pixels->Color(0, 0,255));

    // BT_02 Jaune
  pixels->setPixelColor(2, pixels->Color(255, 255,0));
  pixels->setPixelColor(3, pixels->Color(255, 255,0));
  pixels->setPixelColor(12, pixels->Color(255, 255,0));
  pixels->setPixelColor(13, pixels->Color(255, 255,0));
  
  // BT_03 Orange Foncé
  pixels->setPixelColor(4, pixels->Color(255, 102,0));
  pixels->setPixelColor(5, pixels->Color(255, 102,0));
  pixels->setPixelColor(10, pixels->Color(255, 102,0));
  pixels->setPixelColor(11, pixels->Color(255, 102,0));

  // BT_04 Bleu Claire
  pixels->setPixelColor(6, pixels->Color(0, 191,255));
  pixels->setPixelColor(7, pixels->Color(0, 191,255));
  pixels->setPixelColor(8, pixels->Color(0, 191,255));
  pixels->setPixelColor(9, pixels->Color(0, 191,255));

  // BT_05 Vert Violet 153, 21,255
  pixels->setPixelColor(16, pixels->Color(0, 255, 0));
  pixels->setPixelColor(17, pixels->Color(0, 255, 0));
  pixels->setPixelColor(30, pixels->Color(0, 255, 0));
  pixels->setPixelColor(31, pixels->Color(0, 255, 0));

  // BT_06 Rouge
  pixels->setPixelColor(18, pixels->Color(255, 0,0));
  pixels->setPixelColor(19, pixels->Color(255, 0,0));
  pixels->setPixelColor(28, pixels->Color(255, 0,0));
  pixels->setPixelColor(29, pixels->Color(255, 0,0));

  // BT_07 Violet
  pixels->setPixelColor(20, pixels->Color(102, 0,204));
  pixels->setPixelColor(21, pixels->Color(102, 0,204));
  pixels->setPixelColor(26, pixels->Color(102, 0,204));
  pixels->setPixelColor(27, pixels->Color(102, 0,204));
 
  // BT_08 Orange Pale
  pixels->setPixelColor(22, pixels->Color(250, 121,35));
  pixels->setPixelColor(23, pixels->Color(250, 121,35));
  pixels->setPixelColor(24, pixels->Color(250, 121,35));
  pixels->setPixelColor(25, pixels->Color(250, 121,35));
   
  // Envoyez les couleurs de pixel mise à jour au matériel.
  pixels->show();


  // BT_01 Bleu
  pixels2->setPixelColor(0, pixels->Color(0, 0,255));
  pixels2->setPixelColor(1, pixels->Color(0, 0,255));
  pixels2->setPixelColor(14, pixels->Color(0, 0,255));
  pixels2->setPixelColor(15, pixels->Color(0, 0,255));

  // BT_02 Jaune
  pixels2->setPixelColor(2, pixels->Color(255, 255,0));
  pixels2->setPixelColor(3, pixels->Color(255, 255,0));
  pixels2->setPixelColor(12, pixels->Color(255, 255,0));
  pixels2->setPixelColor(13, pixels->Color(255, 255,0));

  // BT_03 Orange Foncé
  pixels2->setPixelColor(4, pixels->Color(255, 102,0));
  pixels2->setPixelColor(5, pixels->Color(255, 102,0));
  pixels2->setPixelColor(10, pixels->Color(255, 102,0));
  pixels2->setPixelColor(11, pixels->Color(255, 102,0));

  // BT_04 Bleu Claire
  pixels2->setPixelColor(6, pixels->Color(0, 191,255));
  pixels2->setPixelColor(7, pixels->Color(0, 191,255));
  pixels2->setPixelColor(8, pixels->Color(0, 191,255));
  pixels2->setPixelColor(9, pixels->Color(0, 191,255));

  // BT_05 Vert Violet 153, 21,255
  pixels2->setPixelColor(16, pixels->Color(0, 255, 0));
  pixels2->setPixelColor(17, pixels->Color(0, 255, 0));
  pixels2->setPixelColor(30, pixels->Color(0, 255, 0));
  pixels2->setPixelColor(31, pixels->Color(0, 255, 0));

  // BT_06 Rouge
  pixels2->setPixelColor(18, pixels->Color(255, 0,0));
  pixels2->setPixelColor(19, pixels->Color(255, 0,0));
  pixels2->setPixelColor(28, pixels->Color(255, 0,0));
  pixels2->setPixelColor(29, pixels->Color(255, 0,0));

  // BT_07 Violet
  pixels2->setPixelColor(20, pixels->Color(102, 0,204));
  pixels2->setPixelColor(21, pixels->Color(102, 0,204));
  pixels2->setPixelColor(26, pixels->Color(102, 0,204));
  pixels2->setPixelColor(27, pixels->Color(102, 0,204));
 
  // BT_08 Orange Pale
  pixels2->setPixelColor(22, pixels->Color(250, 121,35));
  pixels2->setPixelColor(23, pixels->Color(250, 121,35));
  pixels2->setPixelColor(24, pixels->Color(250, 121,35));
  pixels2->setPixelColor(25, pixels->Color(250, 121,35));
 
   
  // Envoyez les couleurs de pixel mise à jour au matériel.
  pixels2->show();
 }

Merci d'avance :slight_smile:

C'est une sorte de bouton poussoir ? J'ai trouvé cette image :
image

Si je comprends bien, tu veux mettre un ou plusieurs leds WS2812B sous chacun de tes boutons.

Tu veux dire que, au bout de 5 minutes de non utilisation du bouton, les leds situées sous le bouton doivent jouer une animation ?

Avant de te lancer dans le code final, commence par un code simple, avec un bouton et un seul ensemble de leds, associées au bouton.

Pour déclarer le bouton, sur la pin 4 par exemple :

// Bouton
int bouton = 4;

et dans le setup :

// bouton déclaré en INPUT_PULLUP : renvoie LOW si appuyé
// connecter entre la pin et GND
  pinMode(bouton, INPUT_PULLUP);

Ensuite, dans la loop, tu lis l'état du bouton :

  // lecture du bouton
  bool etatBouton = digitalRead(bouton);

Le bouton renvoie LOW s'il est enfoncé : si la valeur lue est LOW, tu initialises un chrono, déclaré au préalable en haut du sketch :
unsigned long chrono = 0;

Dans la loop :

  // lecture du bouton
  bool etatBouton = digitalRead(bouton);
  if (!etatBouton) { // lecture LOW
    delay(30);  // anti-rebond
    chrono = millis();
  }

Puis tu vérifies le temps passé depuis la dernière fois que le bouton a été enfoncé : si le 'timeout' est dépassé, tu lances l'animation.
if (millis() - chrono > timeout) animation();

timeout doit être défini en variable globale :

#define SECONDE 1000
#define MINUTE (60*SECONDE)
unsigned_long timeout = 5 * MINUTE;

et il faut bien sûr écrire la fonction qui fait l'animation.

Tu dois aussi décider de ce qui se passe après avoir joué l'animation. On repart pour une attente ou on rejoue l'animation sans arrêt ?
L'animation doit être aussi courte que possible, car si elle est bloquante, on risque de ne pas détecter des appuis sur le bouton pendant ce temps.

Bref, c'est juste une base pour te montrer ce que tu peux faire, mais plus tu creuseras et plus tu verras qu'il y a des problèmes à régler...

PS : tu devrais aussi déplacer les lignes que tu as écrites pour allumer les leds dans une fonction, ce qui rendra plus facilement lisible le contenu de la llop.

pour affecter des couleurs à tous les boutons utilisez un tableau puisque les boutons ont une couleur donnée.

par exemple ➜ à voir ici

#include <Adafruit_NeoPixel.h>
const byte neoPin = 5;
const byte numPixels = 32;
Adafruit_NeoPixel pixels(numPixels, neoPin, NEO_GRB + NEO_KHZ800);

const uint32_t couleurs[] = {
  0x0000FF, 0x0000FF, 0x0000FF, 0x0000FF, // 4 en bleu
  0x00FF00, 0x00FF00, 0x00FF00, 0x00FF00, // 4 en vert
  0xFF0000, 0xFF0000, 0xFF0000, 0xFF0000, // 4 en rouge
  0xFF00FF, 0xFF00FF, 0xFF00FF, 0xFF00FF, // 4 en rouge+bleu = violet
  0x00FFFF, 0x00FFFF, 0x00FFFF, 0x00FFFF, // 4 en vert+bleu = turquoise
  0xFFFF00, 0xFFFF00, 0xFFFF00, 0xFFFF00, // 4 en rouge+vert = jaune
  0x000000, 0x000000, 0x000000, 0x000000, // 4 en noir
  0xFFFFFF, 0xFFFFFF, 0xFFFFFF, 0xFFFFFF, // 4 en rouge+vert/bleu = blanc
};

void setup() {
  Serial.begin(115200);
  pixels.begin();
  pixels.setBrightness(255); // Set BRIGHTNESS to about 1/5 (max = 255)
  pixels.clear();
  pixels.show();

  for (byte i = 0; i < numPixels; i++) pixels.setPixelColor(i, couleurs[i]);
  pixels.show();
}

void loop() {}

ça simplifie quand même le code :slight_smile:

Comme tu es susceptible d'avoir plusieurs animations en même temps, il faudrait que tu t'oriente sur un code sans l'utilisation de delay.
une machine à état serait je pense bien indiquée, avec un indicateurs d''état de l'animation pour chaque bouton.

C'est exactement ça , il faut que je test .
Pour l'animation je vais utilisé une toute faite Adafruit NeoPixel "standtest_wheel", il faut que je vois comment l'intégrés , et donc voir comme tu le précise voir si lorsque j'appuis a nouveau sur le bouton si l'animation ce stop pour a nouveau affiché l'éclairage de base des boutons.

Merci beaucoup j'espère y arrivé :slight_smile: :+1:

Merci pour cette simplification :ok_hand: , je vais d'abord testé le code que lesept m'a fournis av ec le code que j'ai déjà quand ça fonctionnera je m'amuserai avec le tiens :wink:

La tu me pose une colle ^^ je m'y connais pas en codage, j'ai bien vu en cherchent un peu qu'il y a différente manière de codé entre millis et delay , mais je comprends pas trop.Je pense y aller a tâtons. j'aurai en fais qu'un seul bouton pour lancé l'animation.
Je test tout ça et je vous tiens au courant

Le soucis avec une animation toute faite, c'est si tu as en plusieurs elle doivent fonctionner en parallèle de l'autre, surement que Adafruit à prévus ce cas.

Delay, arrête le fonctionnement de ton microcontrôleur pendant le temps donnée en paramètre.
Millis, donne le temps en milliseconde(je crois :slight_smile: ) depuis le démarrage du microcontrôleur(l'heure machine en gros).

En gros ne pas trop utiliser de delay, mais plutot surveiller lh'eure machine pour effectuer une action.

Une machine à état permet justement de faire ça avec un algorithme qui reste relativement lisible.

Ok je comprends ce que tu expliques mais je suis incapable de le mettre en place :sleepy:
Deja avec ce que lesept ma fournit je n’arrive pas a le faire fonctionner, j’ai une erreur que j’arrive pas a regler :upside_down_face:

Ca c'est ce que tu dis, rien ne m'oblige à croire que tu en es incapable :slight_smile:

En faite c'est relativement assez simple, c'est juste que c'est difficile à s'imaginer quand on ne connait pas.
Règle une chose à la fois et fait des tests unitaire de chaque problématique.

Quel est cet erreur.

Si tu veux je peux te passer un programme qui n'a rien à voir mini horloge, mais qui utilise des états pour ne pas faire de delay.

L’erreur viens sûrement du fait que je n’arrive pas a indiqué le chemin du fichier pour l’animation, j’ai mis le fichier qui est un “.ino” dans le meme répertoire.
Je veux bien ton programme sur l’horloge, si ca peut m’aider a comprendre un peu plus ^^.

Tu as mis un .ino avec loop et setup, que tu veux appeler depuis le .ino de ton projet ???

je sais pas ce que je dois mettre ni dans loop ni dans setup, mais le fichier .ino que je souhaite appellé c'est le fichier qui contient l'animation, c'est le fichier qui fait l'animation :grimacing:

Je viens de trouvé une explication pour inclure un fichier .h et .cpp, mais je ne sais pas comment modifier mon fichier "anime.ino" pour en faire un . et un .cpp
Voici le contenu du fichier anime.ino que je voudrai appeler

// A basic everyday NeoPixel strip test program.

// NEOPIXEL BEST PRACTICES for most reliable operation:
// - Add 1000 uF CAPACITOR between NeoPixel strip's + and - connections.
// - MINIMIZE WIRING LENGTH between microcontroller board and first pixel.
// - NeoPixel strip's DATA-IN should pass through a 300-500 OHM RESISTOR.
// - AVOID connecting NeoPixels on a LIVE CIRCUIT. If you must, ALWAYS
//   connect GROUND (-) first, then +, then data.
// - When using a 3.3V microcontroller with a 5V-powered NeoPixel strip,
//   a LOGIC-LEVEL CONVERTER on the data line is STRONGLY RECOMMENDED.
// (Skipping these may work OK on your workbench but can fail in the field)

#include <Adafruit_NeoPixel.h>
#ifdef __AVR__
 #include <avr/power.h> // Required for 16 MHz Adafruit Trinket
#endif

// Which pin on the Arduino is connected to the NeoPixels?
// On a Trinket or Gemma we suggest changing this to 1:
#define LED_PIN    5

// How many NeoPixels are attached to the Arduino?
#define LED_COUNT 32

// Declare our NeoPixel strip object:
Adafruit_NeoPixel strip(LED_COUNT, LED_PIN, NEO_GRB + NEO_KHZ800);
// Argument 1 = Number of pixels in NeoPixel strip
// Argument 2 = Arduino pin number (most are valid)
// Argument 3 = Pixel type flags, add together as needed:
//   NEO_KHZ800  800 KHz bitstream (most NeoPixel products w/WS2812 LEDs)
//   NEO_KHZ400  400 KHz (classic 'v1' (not v2) FLORA pixels, WS2811 drivers)
//   NEO_GRB     Pixels are wired for GRB bitstream (most NeoPixel products)
//   NEO_RGB     Pixels are wired for RGB bitstream (v1 FLORA pixels, not v2)
//   NEO_RGBW    Pixels are wired for RGBW bitstream (NeoPixel RGBW products)


// setup() function -- runs once at startup --------------------------------

void setup() {
  // These lines are specifically to support the Adafruit Trinket 5V 16 MHz.
  // Any other board, you can remove this part (but no harm leaving it):
#if defined(__AVR_ATtiny85__) && (F_CPU == 16000000)
  clock_prescale_set(clock_div_1);
#endif
  // END of Trinket-specific code.

  strip.begin();           // INITIALIZE NeoPixel strip object (REQUIRED)
  strip.show();            // Turn OFF all pixels ASAP
  strip.setBrightness(50); // Set BRIGHTNESS to about 1/5 (max = 255)
}


// loop() function -- runs repeatedly as long as board is on ---------------

void loop() {
  // Fill along the length of the strip in various colors...
  colorWipe(strip.Color(255,   0,   0), 50); // Red
  colorWipe(strip.Color(  0, 255,   0), 50); // Green
  colorWipe(strip.Color(  0,   0, 255), 50); // Blue

  // Do a theater marquee effect in various colors...
  theaterChase(strip.Color(127, 127, 127), 50); // White, half brightness
  theaterChase(strip.Color(127,   0,   0), 50); // Red, half brightness
  theaterChase(strip.Color(  0,   0, 127), 50); // Blue, half brightness

  rainbow(10);             // Flowing rainbow cycle along the whole strip
  theaterChaseRainbow(50); // Rainbow-enhanced theaterChase variant
}


// Some functions of our own for creating animated effects -----------------

// Fill strip pixels one after another with a color. Strip is NOT cleared
// first; anything there will be covered pixel by pixel. Pass in color
// (as a single 'packed' 32-bit value, which you can get by calling
// strip.Color(red, green, blue) as shown in the loop() function above),
// and a delay time (in milliseconds) between pixels.
void colorWipe(uint32_t color, int wait) {
  for(int i=0; i<strip.numPixels(); i++) { // For each pixel in strip...
    strip.setPixelColor(i, color);         //  Set pixel's color (in RAM)
    strip.show();                          //  Update strip to match
    delay(wait);                           //  Pause for a moment
  }
}

// Theater-marquee-style chasing lights. Pass in a color (32-bit value,
// a la strip.Color(r,g,b) as mentioned above), and a delay time (in ms)
// between frames.
void theaterChase(uint32_t color, int wait) {
  for(int a=0; a<10; a++) {  // Repeat 10 times...
    for(int b=0; b<3; b++) { //  'b' counts from 0 to 2...
      strip.clear();         //   Set all pixels in RAM to 0 (off)
      // 'c' counts up from 'b' to end of strip in steps of 3...
      for(int c=b; c<strip.numPixels(); c += 3) {
        strip.setPixelColor(c, color); // Set pixel 'c' to value 'color'
      }
      strip.show(); // Update strip with new contents
      delay(wait);  // Pause for a moment
    }
  }
}

// Rainbow cycle along whole strip. Pass delay time (in ms) between frames.
void rainbow(int wait) {
  // Hue of first pixel runs 5 complete loops through the color wheel.
  // Color wheel has a range of 65536 but it's OK if we roll over, so
  // just count from 0 to 5*65536. Adding 256 to firstPixelHue each time
  // means we'll make 5*65536/256 = 1280 passes through this loop:
  for(long firstPixelHue = 0; firstPixelHue < 5*65536; firstPixelHue += 256) {
    // strip.rainbow() can take a single argument (first pixel hue) or
    // optionally a few extras: number of rainbow repetitions (default 1),
    // saturation and value (brightness) (both 0-255, similar to the
    // ColorHSV() function, default 255), and a true/false flag for whether
    // to apply gamma correction to provide 'truer' colors (default true).
    strip.rainbow(firstPixelHue);
    // Above line is equivalent to:
    // strip.rainbow(firstPixelHue, 1, 255, 255, true);
    strip.show(); // Update strip with new contents
    delay(wait);  // Pause for a moment
  }
}

// Rainbow-enhanced theater marquee. Pass delay time (in ms) between frames.
void theaterChaseRainbow(int wait) {
  int firstPixelHue = 0;     // First pixel starts at red (hue 0)
  for(int a=0; a<30; a++) {  // Repeat 30 times...
    for(int b=0; b<3; b++) { //  'b' counts from 0 to 2...
      strip.clear();         //   Set all pixels in RAM to 0 (off)
      // 'c' counts up from 'b' to end of strip in increments of 3...
      for(int c=b; c<strip.numPixels(); c += 3) {
        // hue of pixel 'c' is offset by an amount to make one full
        // revolution of the color wheel (range 65536) along the length
        // of the strip (strip.numPixels() steps):
        int      hue   = firstPixelHue + c * 65536L / strip.numPixels();
        uint32_t color = strip.gamma32(strip.ColorHSV(hue)); // hue -> RGB
        strip.setPixelColor(c, color); // Set pixel 'c' to value 'color'
      }
      strip.show();                // Update strip with new contents
      delay(wait);                 // Pause for a moment
      firstPixelHue += 65536 / 90; // One cycle of color wheel over 90 frames
    }
  }
}

Un fichier ino est un programme autonome qui utilise la framework Arduino.
Si on résume, un fichier .cpp est un fichier ino sans setup et loop, qui contient des fonctions pouvant être appelé par le fichier principal qui contient la fonction d'entrée (en Arduino c'est le fichier ino, qui contient loop et setup).

Si tu fais un include d'un fichier ino ou si tu copie un fichier ino dans un autre, tu aura alors deux fonction loop et deux fonction setup.
Le compilateur ne pourra pas alors déterminer la quelle il doit utiliser.

La fonction setup, sert à initialiser la configuration que tu souhaite pour ton Arduino(en gros), la fonction loop est une fonction qui est appelé en boucle par le framework Arduino et qui contient le corps du programme.

lorsque tu as dans deux programmes Arduino (avec donc deux fichier ino), il faut que tu fusionne les deux fichiers, pour avoir plus qu'une seul fonction setup et loop

le soucis majeur est que ton animation contient des delay(mise en pause de processeur), donc même si tu fusionne les deux fonctions loop, il y a fort à parier que les delay contenu dans les deux loop, s'interfère que cela ne produise pas ce que tu veux.

Pour répondre à ta question, tu renomme ton fichier ino en .cpp, tu supprime les fonctions loop et setup.
Il faudra créer un fichier .h qui contiendra la déclaration des fonctions implémentées dans le fichier .cpp, qui faudra

Comment je pourrai m'y prendre pour réalisé ce que je souhaite ?
Au plus simple ^^

C’est une simplification limite mensongère :cold_face::innocent::thinking::man_shrugging:

Pourquoi limite? :slight_smile:

Tu as quoi dans autre fichier ino, du coup.

En fait le fichier Eclairage fixe que j'ai mis en haut et celui que je viens de mettre qui est l'animation