File d'attente avec afficheur Led + 1 bouton

Bonjour,

Je sors d'une formation Arduino pour le spectacle (je travaille dans le spectacle) et j'ai un projet de télécommande (avec touch OSC) qui enverrai des infos d'affichage dans un boitier. Je résume ce que je voudrai faire :

Hardware :

  • 1 télécommande Touch OSC avec 14 bouton
  • 1 boitier avec 1 afficheur Led 7 segment et un bouton poussoir

Code :
Quand on appuie sur un n° de 1 à 14 sur la télécommande, le n° correspondant s'affiche sur le boitier. On peut appuyer sur d'autres numéro qui restent en "attente". Les numéros suivants ne s'affichent que quand on appuie sur le bouton.

Ce code me permettrait de simplifier mon idée de base qui était de faire un boitier avec 14 Led et 14 bouton : quand on appuie sur le n°1, la led 1 clignote, etc...et quand on appuie sur le bouton 1 la Led 1 arrête de clignoter. Le code dans cet exemple serait à ma portée mais il implique une carte avec beaucoup de sortie (28) et j'aurais aimé construire tout ça avec un simple esp8266..

J'ai commencé à chercher et je suis tombé sur la library "queue array", est ce qu'elle pourrait m'aider à réaliser ce code ?

Merci pour vos réponses !

Théo

Pour éviter d'avoir 28 entrées sorties, tu peux déjà utiliser une bande de LEDs adressables genre ws2812. Il ne te faut qu'une seule sortie pour contrôler l'ensemble.
Reste à gérer les boutons. Il existe des multiplexeurs pour contrôler 16 (peut-être même 32) périphériques numériques avec quelques I/O seulement (4 ou 5).

C'est quoi une télécommande Touche OSC.

Édit. Je déplace le sujet dans le forum général.

Merci pour ta réponse ! Oui c'est vrai qu'une bande Led pourrait arranger mes affaires. Mais il faut que je développe un peu mon projet car ça ne répond pas entièrement à mon problème :

  • chapiteau avec 14 cabines (1 spectateur dans chaque cabine)
  • à l'entrée, 1 régisseur distribue des gobelets avec un n° de cabine (entre 1 et 14)
  • à l'intérieur du chapiteau, 1 autre régisseur gère le public pour les guider dans le chapiteau

Le projet c'est que le régisseur à l'intérieur a une commande Touch OSC (c'est une application smartphone assez géniale qui permet de créer son interface très facilement pour envoyer des infos OSC (ou MIDI) en WIFI : TouchOSC | hexler.net ). Sur cette commande (un smartphone en fait) il ya les 14 "boutons" correspondant aux cabines, l'idée c'est que quand il appuie sur un bouton, ça envoie l'info au régisseur à l'entrée (qui lui a le boitier physique avec le arduino, l'afficheur Led et 1 bouton) que la cabine correspondante est libre, il peut donc distribuer le gobelet, appuyer sur le bouton et il voit ensuite s'il y a d'autres cabines libres.

Plusieurs affichage possible donc mais il me semble que la plus claire pour les régisseurs c'est une boite avec 1 afficheur LED (affichant les n° de 1 à 14) et 1 bouton pour passer l'info suivante. Mais je ne sais pas comment écrire ce code...Et du coup je suis curieux de savoir comment écrire ce code, une idée ?

C'est pas simple ton truc... si je peux me permettre :smile:
Si je comprends bien, il y a une personne à l'accueil (appelons le Albert) qui reçoit des gens et leur attribue un numéro (de cabine). Il les dirige vers une seconde personne (appelons le Bernard) qui les installe dans leur cabine.
Ces gens peuvent quitter la cabine et Bernard doit en informer Albert : il utilise la télécommande pour cela.

Est-ce bien ça ?

Supposons qu'on ait 14 LED, numérotées avec un bouton à côté de chacune. Lorsqu'Albert attribue une cabine à un arrivant, il appuie sur le bouton et cela éteint la LED correspondante.
Lorsque Bernard voit que le spectateur part, il appuie sur le bouton correspondant sur sa télécommande ce qui envoie un message qui a pour but de rallumer le LED en question.

J'ai encore bon là ?

Si oui, pas besoin de file d'attente, il suffit de connecter un Arduino à la bande de LEDs. L'Arduino surveille les boutons et éteint les LEDs si les boutons sont actionnés. L'Arduino écoute le Wifi et rallume la LED (en vérifiant qu'elle bien éteinte) correspondant au numéro reçu de la télécommande.

Pas très compliqué à écrire, en pseudo code ça donnerait ça :

Pour i entre 0 et 13 : 
  si le bouton i est enfoncé et la LED i est allumée : éteindre la LED i
Ecouter le Wifi : si message reçu, extraire le numéro de la LED
  si la LED est éteinte, allumer la LED.

Reste bien sûr à écrire ça en C/C++...

Je te conseille, si tu débutes, d'y aller pas à pas, en séparant les problèmes :

  • d'abord apprends à te servir d'un bouton poussoir, achète un multiplexeur et apprends à te servir de 14 boutons
  • teste une bande de LEDs
  • apprends à te servir du Wifi et à recevoir des messages.

Enfin, je te conseillerais bien un ESP32 au lieu d'un ESP8266, version plus récente et plus puissante, peut-être même capable de gérer les 14 boutons et la bande de LEDs sans multiplexeur...

Oui c'est ça tu as bien compris les missions d'Albert et de Bernard. Effectivement écrire le code comme ça, je pense que je peux m'en sortir, on a déjà fait marcher tout ça pendant ma formation, bien que je ne n'ai jamais utilisé de multiplexeur...Je découvre aussi qu'il y a d'autres type de montage électronique pour utiliser plusieurs bouton (ou Led ? ) sur une même entrée / sortie de l'arduino :

Reste maintenant à monter le boitier d'Albert et faire correspondre chaque Led de la bande de Led à un numéro de cabine..C'est vrai que l'option avec afficheur Led me plaisait bien car le montage électronique était plus facile mais bon si j'arrive à faire ça ça sera déjà pas mal !

Merci beaucoup pour tes conseils !

C'est bien, mais l'ESP8266 fonctionne en 3.3V, donc il y a moins de dynamique et du coup moins de boutons possibles. Je te (re) conseille l'ESP32 :

Il ne manque d'IO, et tu en as besoin de 14 pour les boutons plus une pour la bande de LEDs.

Oui l'esp32 m'a l'air bien. Le problème c'est plus le ws2812 (ou autre bande Led) j'ai peur que le boitier d'Albert soit illisible avec de si petites Led si rapprochées. Est ce qu'on peut utiliser le protocole NeoPixel (ou autre type bande led) avec des des led "indépendantes" pour faire un boitier plus sur mesure, avec des led plus espacées ?

Oui, il existe des neopixel indépendantes.

Oui, ou tu peux les couper une par une et les relier avec des fils et de la soudure

Merci pour vos réponses ! J'ai commencé mon projet avec une carte esp8266 (j'en avais déjà une), des led et des boutons pour le boitier et Touch Osc sur un iphone, ça marche nickel ! Je vais quand même m'orienter vers un afficheur led 7 seg mais je galère un peu avec la library "sevseg" qui m'aiderait bien. Malgré les nombreux tutos, je n'arrive pas à comprendre comment câbler mon aff led HD1133 O (à priori cathode commune mais pas sur j'ai du mal à trouver une notice claire... ) :

En "direct", ça marche donc je suis pas si loin :

int A = 2; // 7
int B = 3; // 6
int C = 4; // 4
int D = 5; // 2
int E = 6; // 1
int F = 7; // 9
int G = 8; // 10

void setup() {
  // put your setup code here, to run once:

  pinMode (A, OUTPUT);
  pinMode (B, OUTPUT); 
  pinMode (C, OUTPUT);
  pinMode (D, OUTPUT);
  pinMode (E, OUTPUT);
  pinMode (F, OUTPUT);
  pinMode (G, OUTPUT);

 // Numéro 8, tous les segments allumés
 
  digitalWrite (A, HIGH);
  digitalWrite (B, HIGH);
  digitalWrite (C, HIGH);
  digitalWrite (D, HIGH);
  digitalWrite (E, HIGH);
  digitalWrite (F, HIGH);
  digitalWrite (G, HIGH);
  
}

C'est le setup de la library que je comprends pas..

#include "SevSeg.h"
SevSeg sevseg; //Instantiate a seven segment object

void setup() {
  byte numDigits = 4;
  byte digitPins[] = {2, 3, 4, 5};
  byte segmentPins[] = {6, 7, 8, 9, 10, 11, 12, 13};
  bool resistorsOnSegments = false; // 'false' means resistors are on digit pins
  byte hardwareConfig = COMMON_ANODE; // See README.md for options
  bool updateWithDelays = false; // Default 'false' is Recommended
  bool leadingZeros = false; // Use 'true' if you'd like to keep the leading zeros
  bool disableDecPoint = false;

Merci pour vos réponses !

Ca y est j'ai enfin compris comment câbler tout ça..

Donc tout va bien ?

Et bien maintenant il me reste le plus compliqué à faire ! Là j'ai donc ma télécommande OSC avec 14 boutons pour les cabines. Quand j'appuie sur le 3, ça affiche 3 sur l'aff. led, etc... jusqu'à 9 (pour le moment je n'ai qu'un seul Digit Pin donc je vais jusqu'à 9). Voici mon code pour le moment :

#include <ESP8266WiFi.h>
#include <WiFiUdp.h>
#include <OSCBundle.h>                 // for receiving OSC messages

#include "SevSeg.h"
SevSeg sevseg; 

char ssid[] = "***";                 // your network SSID (name)
char pass[] = "***";              // your network password

WiFiUDP Udp;                           // A UDP instance to let us send and receive packets over UDP
const unsigned int localPort = 8000;   // local port to listen for UDP packets at the NodeMCU (another device must send OSC messages to this port)
const unsigned int destPort = 9000;    // remote port of the target device where the NodeMCU sends OSC to

void setup() {
    Serial.begin(115200);

     // Specify a static IP address for NodeMCU
     // If you erase this line, your ESP8266 will get a dynamic IP address
    //WiFi.config(IPAddress(192,168,0,123),IPAddress(192,168,0,1), IPAddress(255,255,255,0)); 

    // Connect to WiFi network
    Serial.println();
    Serial.print("Connecting to ");
    Serial.println(ssid);
    WiFi.begin(ssid, pass);

    while (WiFi.status() != WL_CONNECTED) {
        delay(500);
        Serial.print(".");
    }
    
    Serial.println("");
    Serial.println("WiFi connected");
    Serial.println("IP address: ");
    Serial.println(WiFi.localIP());

    Serial.println("Starting UDP");
    Udp.begin(localPort);
    Serial.print("Local port: ");
    Serial.println(Udp.localPort());

    // AFF LED sevseg HD1133 O

    byte numDigits = 1;
    byte digitPins[] = {};
    byte segmentPins[] = {5, 4, 0, 2, 14, 12, 13};   // de D1 à D7 sur l'ESP12
    bool resistorsOnSegments = true;

    byte hardwareConfig = COMMON_CATHODE; 
    sevseg.begin(hardwareConfig, numDigits, digitPins, segmentPins, resistorsOnSegments);
    sevseg.setBrightness(100);

}

void loop() {

  OSCMessage msgIN;
  int size;
  if((size = Udp.parsePacket())>0){
    while(size--)
      msgIN.fill(Udp.read());
    if(!msgIN.hasError()){
      
      msgIN.route("/1/push1",push1);
      msgIN.route("/1/push2",push2);
      msgIN.route("/1/push3",push3);
      msgIN.route("/1/push4",push4);
      msgIN.route("/1/push5",push5);
      msgIN.route("/1/push6",push6);
      msgIN.route("/1/push7",push7);
      msgIN.route("/1/push8",push8);
      msgIN.route("/1/push9",push9);
    }
  }
}

  // LES PUSH OSC ALLUMENT LES LEDS
    
  void push1(OSCMessage &msg, int addrOffset){
    sevseg.setNumber(1);
    sevseg.refreshDisplay();
  }

  void push2(OSCMessage &msg, int addrOffset){
    sevseg.setNumber(2);
    sevseg.refreshDisplay();
  }

  void push3(OSCMessage &msg, int addrOffset){
    sevseg.setNumber(3);
    sevseg.refreshDisplay();
  }

  void push4(OSCMessage &msg, int addrOffset){
    sevseg.setNumber(4);
    sevseg.refreshDisplay();
  }

  void push5(OSCMessage &msg, int addrOffset){
    sevseg.setNumber(5);
    sevseg.refreshDisplay();
  }
  
  void push6(OSCMessage &msg, int addrOffset){
    sevseg.setNumber(6);
    sevseg.refreshDisplay();
  }

  void push7(OSCMessage &msg, int addrOffset){
    sevseg.setNumber(7);
    sevseg.refreshDisplay();
  }

  void push8(OSCMessage &msg, int addrOffset){
    sevseg.setNumber(8);
    sevseg.refreshDisplay();
  }

  void push9(OSCMessage &msg, int addrOffset){
    sevseg.setNumber(9);
    sevseg.refreshDisplay();
  }

Simple..Maintenant j'aimerais essayer le fameux code "file d'attente" :

  • le 1er numéro activé s'affiche sur l'afficher Led
  • les numéros activés ensuite sont "stocké" en mémoire mais ne s'affichent pas. Ils s'affichent quand on appuie sur un bouton physique sur le boitier d'Albert.

Albert a un boitier avec 1 aff led (qui affiche les num de cabine de 1 à 14 activés par l'osc) et un bouton pour passer les numéros suivants, comme ça il distribue le numéro de cabine, puis il appuie sur le bouton pour voir les cabines libres au fur et à mesure.

C'est pas gagné, c'est un autre niveau de code, je regarde du coté des QueueArray , FIFO, circular.buffer...

Ok bon, c'est chaud pour moi..est ce que je suis dans la bonne direction avec le freeRTOS ?

Non, pas besoin de FreeRTOS pour ça. Il existe plein de façons de le faire en C.
Une solution simple serait d'utiliser les vecteurs.
https://en.cppreference.com/w/cpp/container/vector
Les fonctions push_back et pop_back sont tes amies. Tu crées un vecteur vide au début de ton code
A chaque arrivée d'un numéro, tu l'empiles dans le vecteur (push_back) et régulièrement tu vérifies que ton vecteur n'est pas vide (size). Si Albert appuie sur son bouton et que le vecteur n'est pas vide, tu en sors le numéro (pop_back pour le dernier arrivé, front pour le premier arrivé) et tu l'affiches.

Mais il y a peut-être plus simple.

Merci ! J'essaye ça !

Ca a l'air trop compliqué pour moi, je n'arrive pas à trouver une base de code sur laquelle je pourrais commencer..

Tu commences par déclarer une variable globale, avant le setup :

std::vector<byte> jetons;

Lorsque tu reçois un message de la télécommande avec le numéro N, tu ajoutes dans la vecteur :
jetons.push_back(N);

Ca, c'est le plus simple. Lorsque Albert appuie sur le bouton, il faut sortir un jeton : pour sortir le dernier (pile FIFO : first in first out), c'est pop_back :

N = jetons.back(); // on met le numéro dans la variable N
jetons.pop_back(); // on efface le dessus du vecteur

A tester...

Merci ! J'ai essayé de caler ça dans mon code mais je ne sais pas où les placer. J'ai l'impression qu'il me manque une library, les push_back et pop_back ne s'affichent pas comme des "fonctions", et surtout je comprends pas comment les utiliser..

Voici mon code :

// VECTOR

#include <Vector.h>
std::vector<byte> jetons;

// SevSeg
#include "SevSeg.h"
SevSeg sevseg; 

// WIFI et OSC
#include <ESP8266WiFi.h>
#include <WiFiUdp.h>
#include <OSCBundle.h>                 // for receiving OSC messages

char ssid[] = "***";                 // your network SSID (name)
char pass[] = "***";              // your network password

WiFiUDP Udp;                           // A UDP instance to let us send and receive packets over UDP
const unsigned int localPort = 8000;   // local port to listen for UDP packets at the NodeMCU (another device must send OSC messages to this port)
const unsigned int destPort = 9000;    // remote port of the target device where the NodeMCU sends OSC to


// CONSTANTE DU BOUTON 
int bouton = 3;   // RX (sous D8) sur l'ESP12

void setup() {
    Serial.begin(115200);

     // Specify a static IP address for NodeMCU
     // If you erase this line, your ESP8266 will get a dynamic IP address
    //WiFi.config(IPAddress(192,168,0,123),IPAddress(192,168,0,1), IPAddress(255,255,255,0)); 

    // Connect to WiFi network
    Serial.println();
    Serial.print("Connecting to ");
    Serial.println(ssid);
    WiFi.begin(ssid, pass);

    while (WiFi.status() != WL_CONNECTED) {
        delay(500);
        Serial.print(".");
    }
    
    Serial.println("");
    Serial.println("WiFi connected");
    Serial.println("IP address: ");
    Serial.println(WiFi.localIP());

    Serial.println("Starting UDP");
    Udp.begin(localPort);
    Serial.print("Local port: ");
    Serial.println(Udp.localPort());

    // AFF LED sevseg HD1133 O

    byte numDigits = 1;
    byte digitPins[] = {};
    byte segmentPins[] = {5, 4, 0, 2, 14, 12, 13};   // de D1 à D7 sur l'ESP12
    bool resistorsOnSegments = true;

    byte hardwareConfig = COMMON_CATHODE; 
    sevseg.begin(hardwareConfig, numDigits, digitPins, segmentPins, resistorsOnSegments);
    sevseg.setBrightness(100);

    // LE BOUTON

    pinMode (bouton, INPUT_PULLUP);    

}

void loop() {

  OSCMessage msgIN;
  int size;
  if((size = Udp.parsePacket())>0){
    while(size--)
      msgIN.fill(Udp.read());
    if(!msgIN.hasError()){
      
      msgIN.route("/1/push1",push1);
      msgIN.route("/1/push2",push2);
      msgIN.route("/1/push3",push3);
      msgIN.route("/1/push4",push4);
      msgIN.route("/1/push5",push5);
      msgIN.route("/1/push6",push6);
      msgIN.route("/1/push7",push7);
      msgIN.route("/1/push8",push8);
      msgIN.route("/1/push9",push9);
    }
  }

  int val;
  val = digitalRead(bouton);
  if (val == LOW) {
    sevseg.setNumber(10);
    sevseg.refreshDisplay();
  }
}

 
  // LES PUSH OSC ALLUMENT LES LEDS

  int a = 1;
  void push1(OSCMessage &msg, int addrOffset){
    sevseg.setNumber(a);
    sevseg.refreshDisplay();
  }


  int b = 2;
  void push2(OSCMessage &msg, int addrOffset){
    sevseg.setNumber(b);
    sevseg.refreshDisplay();
  }

  int c = 3;
  void push3(OSCMessage &msg, int addrOffset){
    sevseg.setNumber(c);
    sevseg.refreshDisplay();
  }

  void push4(OSCMessage &msg, int addrOffset){
    sevseg.setNumber(4);
    sevseg.refreshDisplay();
  }

  void push5(OSCMessage &msg, int addrOffset){
    sevseg.setNumber(5);
    sevseg.refreshDisplay();
  }
  
  void push6(OSCMessage &msg, int addrOffset){
    sevseg.setNumber(6);
    sevseg.refreshDisplay();
  }

  void push7(OSCMessage &msg, int addrOffset){
    sevseg.setNumber(7);
    sevseg.refreshDisplay();
  }

  void push8(OSCMessage &msg, int addrOffset){
    sevseg.setNumber(8);
    sevseg.refreshDisplay();
  }

  void push9(OSCMessage &msg, int addrOffset){
    sevseg.setNumber(9);
    sevseg.refreshDisplay();
  }

Edite ton code pour ne pas mettre d'information confidentielle sur un forum public...