Go Down

Topic: Effectuer 2 actions simultanément  (Read 453 times) previous topic - next topic

Yazid140

Bonjour,

Je voudrai savoir si il est possible de réaliser 2 actions en même temps, bien évidemment en recherchant sur internet j'ai vu qu'il n'était pas totalement possible mais ça serait plus une question de subtilité.

Le problème est qu'en réfléchissant à une éventuelle subtilité je pense bien que ce que je voudrai ne soit pas réalisable donc je viens vers vous pour m'éclairer si il est possible

Ce que je voudrai c'est :

Faire tourner un moteur continuellement et à l'appui d'une télécommande changer de couleur ma bande LEDs installé pendant que le moteur soit toujours actif

Car actuellement le moteur tourne à l'appui il finit son cycle s'arrête puis les Leds changent puis le moteur reprends.

Merci d'avance pour votre aide.

Voici mon code actuellement.
Code: [Select]
void loop() 
{
    Moteur();
   
   if (monRecepteurInfraRouge.decode(&messageRecu))
  {
      if (messageRecu.value == 0xFF18E7) 
       {
          Touche2();  // Rouge
          monRecepteurInfraRouge.resume();
       }
       if (messageRecu.value == 0xFF7A85) 
       {
          Touche3(); // Vert
          monRecepteurInfraRouge.resume();
       }
 
       else
       { monRecepteurInfraRouge.resume(); }

  }
}

dbrion06

Ou est la fonction moteur( parce ce que, si votre moteur est à courant continu ou un cerf veau, il est pratiquement autonome : on postionne une patte de l'arduino, et le moteur tourne ou s'arrête -cas du courant continu)
Ou est la fonction Touche3? (pareil: si vos leds sont commandées depuis une patte, votre problème devient assez aisé à résoudre)

Pour votre info: les exemples d'arduino (devraient servir ... d'exemples)  donnent
a) le cablage en commentaire  (avec ça, on aurait compris si votre problème est difficile ou très facile!)
b) toutes les fonctions définies pour faire tourner l'exemple

Yazid140

#2
Apr 24, 2019, 03:03 pm Last Edit: Apr 24, 2019, 03:08 pm by Yazid140
C'est un moteur pas à pas donc c'est moi qui le contrôle, ensuite pour la LEDs elles ne sont pas commandé depuis une patte (si je dis pas de bêtises)

Le câblage est assez simple j'utilise un shield moteur (tb6560) pour câbler le moteur pas à pas ensuite ses sorties de commandes 8,9 et GND, en ajoutant la bande LEDS (+,-, Pin) et le récepteur de la télécommande même principe.

Et oui effectivement je pensais que le code entier n'était pas necessaire mais peut-être que oui c'est pas très pro ce que j'ai fais ne me critiquez pas   :smiley-roll-sweat:
(j'ai essayé de faire un mouvement arrondis que le changement de sens ne soit pas trop brusque c'est pour ça qu'il y a autant de code d'ailleurs si vous avez une meilleure idée j'écoute également !)

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

#define LED_PIN     3
#define NUM_LEDS    100
CRGB leds[NUM_LEDS];
const char DIN_RECEPTEUR_INFRAROUGE = 2;
IRrecv monRecepteurInfraRouge (DIN_RECEPTEUR_INFRAROUGE);
decode_results messageRecu;


int Distance = 0;
int Distance2 = 0;
int P1=5000, P2=3000, P3=2000;        // Record the number of steps we've taken void setup()

void setup(){
  
FastLED.addLeds<WS2812, LED_PIN, GRB>(leds, NUM_LEDS);
pinMode(8, OUTPUT);
pinMode(9, OUTPUT);
digitalWrite(8, LOW);
digitalWrite(9, LOW);
monRecepteurInfraRouge.enableIRIn();

}


//------------------------------------------------------------------------------------


  void Moteur(){
    

    while (Distance!=10)       {                         //PHASE 1

            digitalWrite(9,HIGH);
            digitalWrite(8, HIGH);
            delayMicroseconds(P1);                   // IMPULSION
            digitalWrite(8, LOW);
            delayMicroseconds(P1);  
Distance = Distance + 1;
                            }
if (Distance == 10 ){
  //--------------------------------------------
while(Distance!=40){                                       // PHASE 2
           digitalWrite(8, HIGH);
           delayMicroseconds(P2);                           // IMPULSION
           digitalWrite(8, LOW);
           delayMicroseconds(P2);
  
Distance = Distance + 1;
}}
if (Distance == 40 ){
  //--------------------------------------------
  
while(Distance!=500)      {                               // PHASE 3
          digitalWrite(8, HIGH);
          delayMicroseconds(P3);                          // IMPULSION
          digitalWrite(8, LOW);
          delayMicroseconds(P3);
Distance = Distance + 1;
                          }}
if (Distance ==500)       {
  //--------------------------------------------
while (Distance!=520)     {                                   // PHASE 4
          
          digitalWrite(8, HIGH);
          delayMicroseconds(P1);                            // IMPULSION
          digitalWrite(8, LOW);
          delayMicroseconds(P1);
Distance = Distance + 1;
                          }}

if (Distance == 520)                                        // DISTANCE MONTEE
        {delayMicroseconds(2000);}
  
//----------------------------------------------------------------------------  
//----------------------------------------------------------------------------

 while (Distance2!=10)   {                 //DISTANCE MONTEE PHASE 1
           digitalWrite(9,LOW);
           digitalWrite(8, HIGH);
           delayMicroseconds(P1);                   // IMPULSION
           digitalWrite(8, LOW);
           delayMicroseconds(P1);
Distance2 = Distance2 + 1;
                         }
if (Distance2 == 10 ) {
  //---------------------------------------------
while(Distance2 != 40){                             // PHASE 2
          digitalWrite(8, HIGH);
          delayMicroseconds(P2);                   // IMPULSION
          digitalWrite(8, LOW);
          delayMicroseconds(P2);
 Distance2 = Distance2 + 1;
}}
if (Distance2 == 40 ){
  //--------------------------------------------
while(Distance2 != 500)        {                       // PHASE 2
        digitalWrite(8, HIGH);
        delayMicroseconds(P3);                         // IMPULSION
        digitalWrite(8, LOW);
        delayMicroseconds(500);
Distance2 = Distance2 + 1;
                                }}

if (Distance2 == 500) {  
//--------------------------------------------

while (Distance2 != 520)     {                      //¨PHASE 4
        digitalWrite(8,HIGH);
        digitalWrite(8, LOW);
        delayMicroseconds(P1);                   // IMPULSION
        digitalWrite(8, LOW);
        delayMicroseconds(P1);
Distance2 = Distance2 + 1;
                            }}

if (Distance2 == 520)                  // DISTANCE MONTEE
        {delayMicroseconds(2000);}
  
  
//----------------------------------------------------------------------------
//----------------------------------------------------------------------------
 
Distance = 0;
Distance2 = 0;


  }


  void Touche2() {
    
    
  
    for (int i = 0; i <= 100; i++) {
        leds[i] = CRGB ( 255, 0, 0);
        FastLED.show();
        delay(20);                  }
  }

  void Touche3() {
      
    for (int i = 0; i <= 100; i++) {
        leds[i] = CRGB ( 0, 255, 0);
        FastLED.show();
        delay(20);                   }
  }
    



void loop()  
{
    Moteur();
    
   if (monRecepteurInfraRouge.decode(&messageRecu))
  {
      if (messageRecu.value == 0xFF18E7)  
       {
          Touche2();  // Rouge
          monRecepteurInfraRouge.resume();
       }
       if (messageRecu.value == 0xFF7A85)  
       {
          Touche3(); // Vert
          monRecepteurInfraRouge.resume();
       }
      
       else
       { monRecepteurInfraRouge.resume();}

  }
}

biggil

#3
Apr 24, 2019, 04:05 pm Last Edit: Apr 24, 2019, 04:06 pm by biggil
si messageRecu.value == 0xFF18E7
alors tu appelles 2 fois monRecepteurInfraRouge.resume()

il manque un else devant le second if

dbrion06

J'ai été un peu inquiet à la lecture desdeux premières lignes de votre code:
fastLED et IRremote utilisent tous les deux des interruptions ou les invalident pour garantir un timing précis;
or, à la lecture de http://marc.merlins.org/perso/arduino/post_2017-04-03_Arduino-328P-Uno-Teensy3_1-ESP8266-ESP32-IR-and-Neopixels.html#IRneopixels, fastLED et IRemote sont compatibles ... sur des 32 bits (ESP8266 disons; moins chers que les arduini avr). l'auteur n'a pas testé sur des arduini 8 bits...
Je vois aussi que Touchexxx() mangent 100 (nombre de leds) *20 millisecondes, rendant le pilotage du reste difficile pendant ce laps de temps -ça fait 100x20x16000 : 32 millions de cycles de perdus sur un arduino 8 bits ....- (je pense au moteur, qui ne gâche rien en terme de complexité)
J'espère que je me trompe en étant pessimiste.

Yazid140

Merci Biggil cependant je ne comprends pas trop ce que vous voulez dire pourquoi est-il appelé 2 fois?

Dbrion06 merci pour votre message mais je débute sur Arduino donc je ne comprends pas trop ce que vous voulez dire ou du moins conclure, vous êtes inquiet par rapport à quoi ? le fait de perdre des cycles engendre quels problèmes ?

dbrion06

Le fait de perdre des cycles engendre 2 problèmes
l'un vient de ma façon de calculer de tête : on ne perd que 3.2 millions de cycles
l'autre, plus grave, vient que l'on est déjà assez contraint et que la commande infra rouge devient inoperante lors des animations sur le rouge (Touche2), le vert ou le bleu du fait que chaque action sur une LED donnée est accompagnée d'un delai de 20 ms.)
Elle sera en particulier incapable de gérer le moteur , tel que c'est programmé, pendant deux secondes.
Est ce acceptable ou pas?

Un autre problème vient du fait qu'on ne sait pas, avec les arduini 8 bits, si les deux bibliothèques utilisées (fastLED et IRremote) seront toujours compatibles, du fait d'une gestion fine des temps dans chacune des bibliothèques. Le lien que vous ai donné explore plus à fond ces problèmes de compatibilité (qui peuvent se traduire par des bizarreries), mais pas pour ces bibliothèque dans cette configuration (le passage à un arduino 32 bits, plus rapide et ... moins cher... semble conseillé en cas de bizarrerie).

Yazid140

Effectivement c'est ce que j'essaye de régler, gérer les Leds en même temps que les moteurs !
Je suis actuellement sur une Uno et je prévois de passer sur une Nano le problème serait encore pire du coup?

Et si je décide de supprimer la partie télécommande car c'est juste un test je voudrai passer ensuite sur une détection sonore qui ferait changer la couleur des Leds ecce mieux ou même problème ou bien pire ?

dbrion06

Vous feriez bien de commencer par vérifier que les télécommandes fonctionnent correctement avec les LEDs; ça règlerait un des deux gros problèmes que j'ai signalés.
Ensuite, toujours en ignorant le moteur pour le moment (s'il fonctionne correctement à part, c'est tant mieux), changer le squelette du pilotage des LEDs
Pour les leds vertes; vous allez avoir besoin de 3 variables globales supplémentaires
etatVert ayant deux valeurs (actif ou pas) -> un bool, initialisé à faux;
numeroVert : le numéro de la LED; initialisé à -1 (aura au maximum 100 comme valeur: un entier sur 8 bits suffit)


tempsVert : sert à gérer  le délay de 20 ms sans bloquer; ititialisé à 0; necessite 32 bits;

lors de l'appui de la télécommande verte:
etatVert devient vrai;
numeroVert devient -1 ; (on se prépare à allumer la 0 ième LED)
si

plus loin, dans la boucle, on a un bloc qui va gérer les diodes vertes:
si etatVert est vrai
si (tempsVert -millis) > 20UL alors
  numeroVert++; // on incrémente le numéro de la de
  si numeroVert >= 100
    etatVert devient faux ; on a fini de faire défiler
    numeroVert redevient -1
sinon
    colorier la numeroVert -ième LED avec
    leds[numeroVert] = CRGB ( 255, 0, 0);
        FastLED.show();


Je sais que ce changement (non testé est désagréable, mais il fait gagner des milliers de cycles, rendant la réponse à la télécommande plus rapide; Naturellement, si ça marche (j'ai fait mon pseudo code à la volée), il faudra faire pareil ... pour les rouges et les bleues, et le moteur devra voir sa gestion du temps modifiée suivant le même principe -mais c'est un peu plus compliqué pour gérer les accélérations comme vous l'avez fait sans utiliser delay, qui est bloquant: autant débugguer ce bout de squelette que je vous ai esquissé pour un cas simple)

Yazid140

Désolé pour la réponse tardive.

Vu la complexité du problème etant donné comme je vous l'ai expliqué c'est un truc temporaire jvais pas me casser la tête à tout refaire merci beaucoup pour les informations.

Comme j'ai expliqué je veux passer à une détection sonore, le moteur tourne...clap des mains changements couleur du bandeau LEDs..clap des mains changement encore.. avec le moteur en action continue,
ecce possible ?

Merci de me débloquer dans cette impasse... je tourne en rond





dbrion06

Du point de vue materiel, gérer un microphone qui réagisse au clap des mains -et pas au bruit du moteur- de façon fiable n'est pas évident; du point de vue logiciel, c'est aussi un peu comploqué.
Vous auriez interet à rendre très réactives vos gestions logicielles
a) des bandeaux
b) du moteur
(par ordre de complexité croissante)
En effet, vous avez tout plein de delays qui introduisent des blocages, et que je propose de remplacer par des comparaisons, en fonction de l'état, à l'horloge systeme.
C'est pour ça que je vous ai passé une esquisse d'ebauche de squelette logiciel (que je ne peux tester, n'ayant pas d'arduino avant jeudi).
J'ai l'impression que, quelle que soit la solution que vous allez retenir définitivement, vous deriez regarder un peu deux sujets:
a) comment passer de delays à une solution sans delays (libérant des centaines de milliers  de cycles, donc la possibilité d'être plus réactif): dans l'IDE d'arduino,  un exemple s'appelle .... blinkWithoutDelay et est très clair et très concis...
b) ce qu'est une machine d'état: un excellent tutoriel en français, riche, clair et ayant de bons liens -vor mon point a) une ligne plus haut!) , est disponible en https://forum.arduino.cc/index.php?topic=470879.0

Donc:
l'idée de commander par des claps des mains peut être plus compliquée que par télécommande IR (risque de parasitage çonore par le bruit du moteur).
pour faire une structure un peu plus compliquée, mais plus réactive que les exemples que vous avez combinés, vous avez interet à vous documenter, puis à gérér par états le défilement des bandeaux de LEDs -je vous l'ai esquissé-, puis, une fois que vous aurez compris ce qui se passe,  celui du moteur (plus compliqué, à cause des variateurs de vitesse...

Yazid140

Pour l'instant avec mes petits test le bruit extérieur ne dérange pas car je dois vraiment faire un bon clap pour que les LEDs change d'état

Je vais regarder tous les documentations que vous m'avez apporté. Ma dernière question en faisant

Moteur();
If(digitalRead(DigitalPin)) //PinCapteur
 Leds();
(Programme non complet)

Ça ne marche pas le moteur tourne continuellement sans prendre en compte la détection du capteur sonore .. Je suppose qu'il reste dans la boucle du moteur comment sortir de la je ne trouve rien sur internet

Merci pour toute votre aide, ça s'annonce vraiment plus dure que prévu..

dbrion06

Quote
(Programme non complet)
Mettez au moins la fonction loop() complète, qu'on ait une idée -partielle- du squelette.
Enfait, vous devriez faire
uint8_t etat =0;
// etat peut avoir 5  (< 255) valeurs:
0 : on ne fait rien
1 : le moteur est actif
2: le ruban vert est agité
3 le ruban rouge est agite
4 le ruban bleu est agité

si (0 == etat)
 si clap detecte etat = 1; erreter de tester l'etat
si (etat == 1)
 si clap detecte etat = 2; erreter de tester l'etat
si (etat == 2)
 si clap detecte etat = 3; erreter de tester l'etat
si (etat == 3)
 si clap detecte etat = 4; erreter de tester l'etat

si (etat == 4)
 si clap detecte etat = 0; erreter de tester l'etat

et , plus loin dans la boucle, en fonction de l'etat
switch (etat){
  case 0: Moteur = inactif; rubanBleu = inactif; rubanVert=inactif; rubanRouge=inactif; break;
 case 1: Moteur=actif; break;
 case 2: Moteur= inactif; rubanBleu = inactif; rubanVert= actif; rubanRouge=inactif; break;
 case 3 :  Moteur= inactif;rubanBleu = inactif; rubanVert=inactif; rubanRouge=actif; break;
 case 4 :  Moteur= inactif;rubanBleu = actif; rubanVert=inactif; rubanRouge=inactif; break;
}
 (codage très naîf

Yazid140

#13
Apr 30, 2019, 11:52 am Last Edit: Apr 30, 2019, 11:55 am by Yazid140
D'accord merci beaucoup je vais essayer ça, je vous fais un retour dès que possible !

Petite question comment je fais pour contrôler l'etat de mon bandeau de led ? car en essayant LOW et HIGH pour faire allumer/éteindre tout d'un coup je n'y arrivais pas je veux bien savoir comment lire son état merci encore !!

dbrion06

Lisez d'abord le tutoriel de JML.... (j'ai "codé" à la volée sans tester: JML a fait son tutoriel très soigneusement)

Go Up