Problème pour stopper un code lancé

Bonjour à tous !

Je n'utilise jamais Arduino habituellement. J'en ai besoin pour activer des haut-parleurs odorants qui fonctionnent avec des paires de ventilateurs. Pour activer les ventilateurs, j'ai un code Arduino avec lequel j'appuie sur "1" par exemple pour lancer la première paire de ventilateurs. J'appuie sur "0" pour les arrêter. Mon problème est que je veux que les ventilateurs soient activés de manière cyclique, avec par exemple 10 secondes de fonctionnement, puis une pause de 7 secondes, et ainsi de suite (ceci est un exemple, je changerai les paramètres de temps directement dans le code). J'ai un code où j'arrive à faire un cycle, mais le problème est qu'une fois lancé, ce code ne s'arrête pas, une fois le cycle lancé il n'est pas possible de lancer une autre commande, ou de stopper les ventilateurs avec la commande censée les arrêter (0). Il faut donc que je modifie ce code pour pouvoir l'arrêter. J'ai aussi un code où je peux démarrer et arrêter les ventilateurs, mais il n'y a pas de cycles. Je ne sais pas s'il est plus facile d'ajouter le cycle sur le code où je peux arrêter les ventilateurs, ou s'il est plus facile d'ajouter l'arrêt sur celui où j'ai le cycle. Je vous envoie donc ces deux codes, si vous trouvez le problème et comment le résoudre, je vous en serais infiniment reconnaissant.

Juste pour précision, je n'y connais vraiment rien en Arduino et en C++, je ne suis pas issu de l'informatique, donc si possible si vous pouvez m'indiquer directement la partie problématique dans mon code, ainsi que le nouveau code a remplacé, cela m'aiderait grandement.

Désolé pour le long message, et merci d'avance pour votre aide et votre temps.

Voici les 2 codes :
Le premier (sans le cycle, mais qui peut s'arrêter) :

// Commande de 12 ventilateurs
// Commandes : 1 à 6 pour actionner les ventilateurs et 0 pour tout arrêter.
// 1 actionne les ventilateurs V1 et V7,
// 2 actionne V2 et V8,
// 3 actionne V3 et V9,
// 4 actionne V4 et V10,
// 5 actionne V5 et V11,
// et 6 actionne les ventilateurs V6 et V12.
//
// Schéma de la disposition des ventilateurs par colonne : (colonne V1 à V6 et colonne V7 à V12)
//  ____        ____
// | V1 |------| V7 |
// | V2 |------| V8 |
// | V3 |------| V9 |
// | V4 |------| V10|
// | V5 |------| V11|
// | V6 |------| V12|
// |____|------|____|

// Pin des 12 ventilateurs :
// Pins Digitales
const int V1 = 7;   // ventilateur n°1
const int V2 = 8;   // ventilateur n°2
const int V3 = 9;   // ventilateur n°3
const int V4 = 10;   // ventilateur n°4 
const int V5 = 11;   // ventilateur n°5
const int V6 = 12;   // ventilateur n°6
// Pins Analogiques
const int V7 = A0;   // ventilateur n°7
const int V8 = A1;   // ventilateur n°8
const int V9 = A2;   // ventilateur n°9
const int V10 = A3;  // ventilateur n°10
const int V11 = A4;  // ventilateur n°11
const int V12 = A5;  // ventilateur n°12

const int LED = 13;
const int T = 8000; // 8 secondes
const int NUM_REPEATS = 10;
char incomingByte;
int counter = 2;
int groupCounter = 2;
bool groupOn = true;

void setup()
{
  // communication série
  Serial.begin(115200);
  
  // Pins Digitales et Analogiques en sortie (output)
  pinMode(V1,OUTPUT);
  pinMode(V2,OUTPUT);
  pinMode(V3,OUTPUT);
  pinMode(V4,OUTPUT);
  pinMode(V5,OUTPUT);
  pinMode(V6,OUTPUT);
  pinMode(V7,OUTPUT);
  pinMode(V8,OUTPUT);
  pinMode(V9,OUTPUT);
  pinMode(V10,OUTPUT);
  pinMode(V11,OUTPUT);
  pinMode(V12,OUTPUT);   
  
  // Ventilateurs à l'arrêt
  digitalWrite(V1,LOW);
  digitalWrite(V2,LOW);
  digitalWrite(V3,LOW);
  digitalWrite(V4,LOW);
  digitalWrite(V5,LOW);
  digitalWrite(V6,LOW);
  analogWrite(V7,0);
  analogWrite(V8,0);
  analogWrite(V9,0);
  analogWrite(V10,0);
  analogWrite(V11,0);
  analogWrite(V12,0);
  
  // LED Arduino (pin n°13)
  pinMode(LED,OUTPUT);    // Pin n°13 en sortie
  digitalWrite(LED,LOW);  // LED éteinte
}

void loop()
{  
  if (Serial.available () > 0)      // vérification de la communication série USB
  {
    incomingByte = Serial.read();   // attente d'une commande vers Arduino
    //Serial.write(incomingByte);
    if (incomingByte == '1')
      { 
       digitalWrite(V1,HIGH);
       analogWrite(V7,255);
       Serial.println("Ventilateurs Niveau 1 : ON.");
       //delay(T);
       //digitalWrite(V1,LOW);
       //analogWrite(V7,0);
      }
    if (incomingByte == '2')
      { 
       digitalWrite(V2,HIGH);
       analogWrite(V8,255);
       Serial.println("Ventilateurs Niveau 2 : ON.");
       //delay(T);
       //digitalWrite(V2,LOW);
       //analogWrite(V8,0);
      }  
    if (incomingByte == '3')
      { 
       digitalWrite(V3,HIGH);
       analogWrite(V9,255);
       Serial.println("Ventilateurs Niveau 3 : ON.");
       //delay(T);
       //digitalWrite(V3,LOW);
       //analogWrite(V9,0);       
      }
    if (incomingByte == '4')
      { 
       digitalWrite(V4,HIGH);
       analogWrite(V10,255);
       Serial.println("Ventilateurs Niveau 4 : ON.");
       //delay(T);
       //digitalWrite(V4,LOW);
       //analogWrite(V10,0);           
      }
    if (incomingByte == '5')
      { 
       digitalWrite(V5,HIGH);
       analogWrite(V11,255);
       Serial.println("Ventilateurs Niveau 5 : ON.");
       //delay(T);
       //digitalWrite(V5,LOW);
       //analogWrite(V11,0);  
      }
    if (incomingByte == '6')
      { 
       digitalWrite(V6,HIGH);
       analogWrite(V12,255);
       Serial.println("Ventilateurs Niveau 6 : ON.");
       //delay(T);
       //digitalWrite(V6,LOW);
       //analogWrite(V12,0);  
      }
    if (incomingByte == '0')
      { 
       digitalWrite(V1,LOW);
       digitalWrite(V2,LOW);
       digitalWrite(V3,LOW);
       digitalWrite(V4,LOW);
       digitalWrite(V5,LOW);
       digitalWrite(V6,LOW);
       analogWrite(V7,0);
       analogWrite(V8,0);
       analogWrite(V9,0);
       analogWrite(V10,0);
       analogWrite(V11,0);
       analogWrite(V12,0);
       Serial.println("12 Ventilateurs : OFF.");
      }  
  } 
  Serial.flush();
}

Le deuxième code (avec le cycle, qui ne s'arrête pas) :

// Commande de 12 ventilateurs
// Commandes : 1 à 6 pour actionner les ventilateurs et 0 pour tout arrêter.
// 1 actionne les ventilateurs V1 et V7,
// 2 actionne V2 et V8,
// 3 actionne V3 et V9,
// 4 actionne V4 et V10,
// 5 actionne V5 et V11,
// et 6 actionne les ventilateurs V6 et V12.
//
// Schéma de la disposition des ventilateurs par colonne : (colonne V1 à V6 et colonne V7 à V12)
//  ____        ____
// | V1 |------| V7 |
// | V2 |------| V8 |
// | V3 |------| V9 |
// | V4 |------| V10|
// | V5 |------| V11|
// | V6 |------| V12|
// |____|------|____|

// Pin des 12 ventilateurs :
// Pins Digitales
const int V1 = 7;   // ventilateur n°1
const int V2 = 8;   // ventilateur n°2
const int V3 = 9;   // ventilateur n°3
const int V4 = 10;  // ventilateur n°4
const int V5 = 11;  // ventilateur n°5
const int V6 = 12;  // ventilateur n°6
// Pins Analogiques
const int V7 = A0;   // ventilateur n°7
const int V8 = A1;   // ventilateur n°8
const int V9 = A2;   // ventilateur n°9
const int V10 = A3;  // ventilateur n°10
const int V11 = A4;  // ventilateur n°11
const int V12 = A5;  // ventilateur n°12

const int LED = 13;
const int T = 5000;          // 5 seconds en miliseconds
const int pauseTime = 3000;  // 3 seconds pause
const int repeatCount = 2;   // T number of times
char incomingByte;
int repeatCounter = 0;

void setup() {
  // communication série
  Serial.begin(115200);

  // Pins Digitales et Analogiques en sortie (output)
  pinMode(V1, OUTPUT);
  pinMode(V2, OUTPUT);
  pinMode(V3, OUTPUT);
  pinMode(V4, OUTPUT);
  pinMode(V5, OUTPUT);
  pinMode(V6, OUTPUT);
  pinMode(V7, OUTPUT);
  pinMode(V8, OUTPUT);
  pinMode(V9, OUTPUT);
  pinMode(V10, OUTPUT);
  pinMode(V11, OUTPUT);
  pinMode(V12, OUTPUT);

  // Ventilateurs à l'arrêt
  digitalWrite(V1, LOW);
  digitalWrite(V2, LOW);
  digitalWrite(V3, LOW);
  digitalWrite(V4, LOW);
  digitalWrite(V5, LOW);
  digitalWrite(V6, LOW);
  analogWrite(V7, 0);
  analogWrite(V8, 0);
  analogWrite(V9, 0);
  analogWrite(V10, 0);
  analogWrite(V11, 0);
  analogWrite(V12, 0);

  // LED Arduino (pin n°13)
  pinMode(LED, OUTPUT);    // Pin n°13 en sortie
  digitalWrite(LED, LOW);  // LED éteinte
}


void loop() {
  if (Serial.available() > 0) {
    incomingByte = Serial.read();

    if (incomingByte == '1') {
      Serial.println("Ventilateurs Niveau 1 : ON.");
      timer(T, 1, V1, V7);
    } else if (incomingByte == '0') {
      digitalWrite(V1, LOW);
      digitalWrite(V2, LOW);
      digitalWrite(V3, LOW);
      digitalWrite(V4, LOW);
      digitalWrite(V5, LOW);
      digitalWrite(V6, LOW);
      analogWrite(V7, 0);
      analogWrite(V8, 0);
      analogWrite(V9, 0);
      analogWrite(V10, 0);
      analogWrite(V11, 0);
      analogWrite(V12, 0);
      Serial.println("12 Ventilateurs : OFF.");
    } else if (incomingByte == '2') {
      Serial.println("Ventilateurs Niveau 2 : ON.");
      timer(T, 1, V2, V8);
    } else if (incomingByte == '3') {
      Serial.println("Ventilateurs Niveau 3 : ON.");
      timer(T, 1, V3, V9);
    } else if (incomingByte == '4') {
      Serial.println("Ventilateurs Niveau 4 : ON.");
      timer(T, 1, V4, V10);
    } else if (incomingByte == '5') {
      Serial.println("Ventilateurs Niveau 5 : ON.");
      timer(T, 1, V5, V11);
    } else if (incomingByte == '6') {
      Serial.println("Ventilateurs Niveau 6 : ON.");
      timer(T, 1, V6, V12);
    } else if (incomingByte == 'x') {
      Serial.println("Arrêt des ventilateurs.");
      digitalWrite(V1, LOW);
      digitalWrite(V2, LOW);
      digitalWrite(V3, LOW);
      digitalWrite(V4, LOW);
      digitalWrite(V5, LOW);
      digitalWrite(V6, LOW);
      analogWrite(V7, 0);
      analogWrite(V8, 0);
      analogWrite(V9, 0);
      analogWrite(V10, 0);
      analogWrite(V11, 0);
      analogWrite(V12, 0);
      repeatCounter = 0; // Reset repeat counter
    } else if (incomingByte == 'q') {
      Serial.println("Arrêt du programme.");
      digitalWrite(V1, LOW);
      digitalWrite(V2, LOW);
      digitalWrite(V3, LOW);
      digitalWrite(V4, LOW);
      digitalWrite(V5, LOW);
      digitalWrite(V6, LOW);
      analogWrite(V7, 0);
      analogWrite(V8, 0);
      analogWrite(V9, 0);
      analogWrite(V10, 0);
      analogWrite(V11, 0);
      analogWrite(V12, 0);
      while (true) {} // Wait indefinitely
    }
  }
void timer(int duration, int numCycles, int pin1, int pin2) {
  for (int i = 0; i < numCycles; i++) {
    digitalWrite(LED, HIGH);  // turn on LED
    digitalWrite(pin1, HIGH);
    analogWrite(pin2, 255);
    delay(duration);         // wait for duration
    digitalWrite(LED, LOW);  // turn off LED
    digitalWrite(pin1, LOW);
    analogWrite(pin2, 0);
    delay(pauseTime);  // wait for pauseTime
  }
  repeatCounter++;
  if (repeatCount < 0 || repeatCounter < repeatCount) {
    timer(duration, numCycles, pin1, pin2);
  } else {
    repeatCounter = 0;
  }
}

  Serial.flush();
}

Dans ton code N°1, tu utilises analogWrite uniquement avec les deux paramètres 0 et 255. Au lieu d'utiliser analogWrite, on peut alors alors utiliser digitalWrite.

Les broches A0..A5 sont des broches digitales et acceptent en plus de LIRE une valeur analogique. Si tu utilises une Uno par exemple, ces broches ne gèrent pas le PWM et de mémoire (mais je ne le vois pas dans la référence) utiliser anaologWrite ne peut générer qu'un état haut ou bas. Ce qui fait que ton programme fonctionne, mais tu n'as pas forcément la variation de vitesse possible.

On peut donc remplacer:
analogWrite(0) par digitalWrite(LOW)
et
analogWrite(255) par digitalWrite(HIGH)

Pour la suite, il faut aussi préciser sur quelle carte tu fonctionnes.

Bon d'habitude on ne fait pas le code comme ça mais le projet à l'air rigolo... On veut des photos du système en production

j'ai un peu amélioré les fonctions. Vous avez bien vos commandes de 1 à 6 et 0 mais vous pouvez aussi associer d'autres commandes aux paires de ventilateurs. par exemple '*' va tout allumer ou 'a' va allumer le groupe de ceux commandés par 1,3,5 alors que b va allumer ceux commandés par 2,4,6.

la configuration se fait simplement en déclarant les paires avec leurs paramètres

paireVentilateur paires[] {
  {"V1V7",  "1*a",  7, A0, ETEINT, 1000, 7000, 0},
  {"V2V8",  "2*b",  8, A1, ETEINT, 1000, 7000, 0},
  {"V3V9",  "3*a",  9, A2, ETEINT, 1000, 7000, 0},
  {"V4V10", "4*b", 10, A3, ETEINT, 1000, 7000, 0},
  {"V5V11", "5*a", 11, A4, ETEINT, 1000, 7000, 0},
  {"V6V12", "6*b", 12, A5, ETEINT, 1000, 7000, 0},
};
  • on commence par un petit nom de la paire, par exemple la première s'appelle "V1V7" mais on aurait pu mettre "entrée de l'exposition"
  • ensuite la liste des commandes (1 caractère) qui activent cette paire, par exemple la première peut être activée indifféremment par '1' ou '*' ou 'a' donc on met "1*a"
  • ensuite suivent les 2 pins de la paire
  • ensuite suit l'état initial (ETEINT, EN_FONCTION_ON, EN_FONCTION_OFF)
  • ensuite la durée d'activation du ventilateur en ms lorsque la paire est activée
  • ensuite la durée d'attente en ms lorsque la paire est activée
  • et on finit juste par 0 parce qu'il y en a besoin

voici le code que vous pouvez utiliser

absolument non testé en vrai, juste dans le simulateur

/* ============================================
  code is placed under the MIT license
  Copyright (c) 2023 J-M-L
  For the Arduino Forum : https://forum.arduino.cc/u/j-m-l

  Permission is hereby granted, free of charge, to any person obtaining a copy
  of this software and associated documentation files (the "Software"), to deal
  in the Software without restriction, including without limitation the rights
  to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
  copies of the Software, and to permit persons to whom the Software is
  furnished to do so, subject to the following conditions:

  The above copyright notice and this permission notice shall be included in
  all copies or substantial portions of the Software.

  THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
  IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
  FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
  AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
  LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
  OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
  THE SOFTWARE.
  ===============================================
*/



// Schéma de la disposition des ventilateurs par colonne : (colonne V1 à V6 et colonne V7 à V12)
//  ____        ____
// | V1 |------| V7 |
// | V2 |------| V8 |
// | V3 |------| V9 |
// | V4 |------| V10|
// | V5 |------| V11|
// | V6 |------| V12|
// |____|------|____|

// Commande de 12 ventilateurs
// 0 pour tout arrêter.
// Commandes : 1 à 6 pour actionner les ventilateurs 
// 1 actionne V1 et V7,
// 2 actionne V2 et V8,
// 3 actionne V3 et V9,
// 4 actionne V4 et V10,
// 5 actionne V5 et V11,
// 6 actionne V6 et V12.
// on peut partager des commande. 
// * pour tout allumer, 
// a pour allumer le groupe (1,3,5) 
// b pour allumer le groupe (2,4,6)

enum t_etat : uint8_t {ETEINT, EN_FONCTION_ON, EN_FONCTION_OFF};

struct paireVentilateur {
  const char* nom;
  const char* lettresCommande;
  const uint8_t pinVentilateur1;
  const uint8_t pinVentilateur2;
  t_etat etat;
  const unsigned long dureeOn;
  const unsigned long dureeOff;
  unsigned long chrono;

  void appliquerEtat(const t_etat m) {
    etat = m;
    chrono = millis();
    switch (etat) {
      case ETEINT:          digitalWrite(pinVentilateur1, LOW);   digitalWrite(pinVentilateur2, LOW);   Serial.print(nom); Serial.println(" est éteint"); break;
      case EN_FONCTION_ON:  digitalWrite(pinVentilateur1, HIGH);  digitalWrite(pinVentilateur2, HIGH);  Serial.print(nom); Serial.println(" est en fontion et allumé"); break;
      case EN_FONCTION_OFF: digitalWrite(pinVentilateur1, LOW);   digitalWrite(pinVentilateur2, LOW);   Serial.print(nom); Serial.println(" est en fontion et éteint"); break;
    }
  }

  void begin() {
    pinMode(pinVentilateur1, OUTPUT);
    pinMode(pinVentilateur2, OUTPUT);
    appliquerEtat(etat);
  }

  void executer(const char commandeID) {
    if (commandeID == '0') {                                            // '0' pour éteindre
      if (etat != ETEINT) appliquerEtat(ETEINT);
    } else if (strchr(lettresCommande, commandeID) != nullptr) {        // est-ce une commande connue d'allumage ?
      appliquerEtat(EN_FONCTION_ON);
    }
  }

  void tick() {
    switch (etat) {
      case ETEINT: break;
      case EN_FONCTION_ON:  if (millis() - chrono >= dureeOn)  appliquerEtat(EN_FONCTION_OFF); break;
      case EN_FONCTION_OFF: if (millis() - chrono >= dureeOff) appliquerEtat(EN_FONCTION_ON);  break;
    }
  }
};

paireVentilateur paires[] {
  {"V1V7",  "1*a",  7, A0, ETEINT, 1000, 7000, 0},
  {"V2V8",  "2*b",  8, A1, ETEINT, 1000, 7000, 0},
  {"V3V9",  "3*a",  9, A2, ETEINT, 1000, 7000, 0},
  {"V4V10", "4*b", 10, A3, ETEINT, 1000, 7000, 0},
  {"V5V11", "5*a", 11, A4, ETEINT, 1000, 7000, 0},
  {"V6V12", "6*b", 12, A5, ETEINT, 1000, 7000, 0},
};
const uint8_t nombreDePaires = sizeof paires / sizeof * paires;


void setup() {
  Serial.begin(115200);
  Serial.println(F("\nConfiguration"));
  for (auto& p : paires) p.begin();
  Serial.println(F("\nEntrez vos commandes"));
}

void loop() {

  int commande = Serial.read();
  if (commande != -1)                                         // -1 si rien à lire
    for (auto& p : paires) p.executer((char) commande);

  for (auto& p : paires) p.tick(); // on gère l'état

}

j'espère que les ventilateurs ne sont pas alimentés par les pins et que vous avez des mosfet ou relais avec une alimentation externe pour les ventilateurs

salut!

tu t'es donc décidé à rejoindre le fil français, bienvenue!
par contre je suis pas sur que multiplier les comptes sur le forum soit une très bonne idée, mais je ne m'occupe pas de ça.
tu n'as pas regardé l'histoire des programmation en "machine à état" comme plusieurs te l'ont suggéré?

j'espère en tout cas que tu trouveras l'aide dont tu as besoin.

faudrait préciser parce que ce n'est pas autorisé... Vaut mieux être clean dès le début plutôt que de se faire prendre la main dans le sac et se faire virer du forum plus tard...

La qualité du forum appartient à tous ses membres...

Bonjour, merci beaucoup pour votre aide, le code a fonctionné ! Je vous en suis très sincèrement reconnaissant, et vous remercie chaleureusement. Enfin, pour ce qu'il s'agit du deuxième compte, je suis vraiment désolé, je suis nouveau sur ce genre de forum, et je ne savais pas que c'était interdit. J'ai simplement voulu créer un deuxième compte pour séparer ma question "internationale" et ma question "française". Encore merci pour le code, et désolé pour cette maladresse.

OK

je vous suggère de détruire un des deux comptes pour qu'il n'y ait pas d'ambiguïté


tant mieux :slight_smile:

Oui :slightly_smiling_face:

Salut @ewannn , n'oublie pas de choisir le message #3 comme solution, avec le petit bouton en bas a droite :wink:

Cordialement
Pandaroux007 :fox_face:

C'est chose faite, j'ai supprimé l'autre compte. Merci encore pour votre aide !

N'oubliez pas

oh oui :grin: !
Par contre, je n'ai jamais entendu parler de haut-parleurs odorants
C'est des diffuseurs ? Je croie que c'est le truc de "haut-parleurs" qui m'étonne le plus :wink: as tu un lien vers une doc ? J'ai cherché mais je n'ai pas trouvé d'exemples ni de descriptions...

Cordialement
Pandaroux007 :fox_face:

C'est chose faite, j'ai supprimé l'autre compte. Merci encore pour votre aide !

Oui ce sont comme des diffuseurs on peut dire cela, on parle de haut-parleurs car il ressemble visuellement fortement à des haut-parleurs sonores

Ahah je ferais cela dès que je les utilise prochainement !

Ok, merci pour les précisions, @ewannn :slightly_smiling_face:
j'attends avec impatience les photos :wink:

Pandaroux007 :fox_face:

au fait est-ce que la fonction supplémentaires de pouvoir commander plusieurs paires d'un coup est utile ?

Oui éventuellement, car elle permettrait d'activer plusieurs paires en simultané, et donc si on a plusieurs capsules d'odeurs, on pourrait déclencher plusieurs ventilateurs et augmenter l'intensité

j'ai bien fait de rajouter ça alors :slight_smile:

Je me pose cette question depuis un moment. Si deux "ventilateurs" sont toujours commandés en même temps, pourquoi utiliser deux sorties différentes et pas la même?

bonne question. Je me la suis posée aussi et me suis dit que c'est pour une évolutivité future :slight_smile: