Projet commande Ampli-casque

Bonjour,

J'ai réalisé en partie la programmation d'une commande pour un Ampli-casque, je dis en partie car j'ai eu recours à ChatGPT pour trouver une commande approprié "activated", le code que j'utilisais pour la bascule de sortie:

if (nouvelEtatEntree1 != etatEntree1) {
    etatEntree1 = nouvelEtatEntree1;
    if (etatEntree1) {
      etatSortie1 = !etatSortie1;
      digitalWrite(SORTIE_1, etatSortie1);

      // Activation de la temporisation
      tempsActivationSorties = millis();
    }
  }

Ne me permettais pas de réaliser une tempo à l'allumage, tout du moins je n'ai pas trouvé la solution.

le système est composé de 3 boutons poussoir:

  • POWER
  • Sélecteur sortie (2 sorties)
  • Sélecteur Entrée (2 entrées)

l'ARDUINO pilote 5 relais 5v par le biais de Mosfet.

Le programme doit:

  • Le bouton POWER doit allumer/éteindre la sortie 12
  • Lorsque POWER est "OFF" toute les sorties et entrées doivent être coupées "12, 11, 10, 7 & 2".
  • Lorsque POWER est "ON" la sortie 12 est activée et 4 secondes plus tard la sortie 11 & 7 est activées.
  • Le sélecteur de sortie bascule entre la sortie 11 et 10.
  • Le sélecteur d'entrée bascule entre la sortie 7 et 2.

Tout fonctionne presque parfaitement avec le code suivant, sauf lorsque j'allume l'ampli, la tempo de 4 sec s'écoule, les 2 sorties s'activent, mais si je souhaite basculer de la sortie 11 à la sortie 10, il arrive qu'il me coupe les 2 sorties 11 & 10 et exécute une bascule en couplant les 2 simultanément, idem pour les sortie 7 & 2.

Quelqu'un aurait il une solution à me proposer ? ou pour me corriger d'une erreur ?


```cpp
// Amplificateur casque

// Constantes pour les broches d'entrée et de sortie
const int buttonPin = 5;                                                        // Bouton-poussoir en broche 5, Sélecteur de Entrée
const int buttonPin1 = 6;                                                       // Bouton-poussoir en broche 1, bouton ON/OFF
const int buttonPin2 = 4;                                                       // Bouton-poussoir en broche 1, Sélecteur Sortie

const int RPin1 = 11;                                                           // Relais en broche 11, bascule SCR 1
const int RPin2 = 10;                                                           // Relais en broche 10, bascule SRC 2
const int RPin3 = 7;                                                            // Relais en broche 7, CASQUE
const int RPin4 = 2;                                                            // Relais en broche 2, PREAMPLI
const int RPin6 = 12;                                                           // Relais POWER

// État initial des sorties
const bool initialOutputState = LOW;

// Variables pour suivre l'état des sorties
bool stateRPin1 = initialOutputState;
bool stateRPin2 = initialOutputState;
bool stateRPin3 = initialOutputState;
bool stateRPin4 = initialOutputState;
bool stateRPin6 = initialOutputState;

// Temporisation pour RPin1 en ms
const unsigned long RPin1_delay = 4000;

// Variable pour suivre l'état de RPin1 après l'appui sur buttonPin1
bool RPin1_activated = false;
bool RPin3_activated = false;                                                   // Variable pour suivre l'état de RPin3

unsigned long prevMillis = 0;                                                   // Variable pour stocker le temps précédent
const int R_delay = 500;                                                        // Temps de rebond en ms

void setup() {
  pinMode(buttonPin, INPUT_PULLUP);                                             // Sélecteur de sortie
  pinMode(buttonPin1, INPUT_PULLUP);                                            // Bouton ON/OFF
  pinMode(buttonPin2, INPUT_PULLUP);                                            // Bouton Sélecteur Sortie

  pinMode(RPin1, OUTPUT);                                                       // Relais en broche 11, bascule SCR 1
  pinMode(RPin2, OUTPUT);                                                       // Relais en broche 10, bascule SRC 2
  pinMode(RPin3, OUTPUT);                                                       // Relais en broche 7, bascule CASQUE
  pinMode(RPin4, OUTPUT);                                                       // Relais en broche 2, bascule PREAMPLI
  pinMode(RPin6, OUTPUT);                                                       // Sortie Alimentation Générale

  digitalWrite(RPin1, initialOutputState);
  digitalWrite(RPin2, initialOutputState);
  digitalWrite(RPin3, initialOutputState);
  digitalWrite(RPin4, initialOutputState);
  digitalWrite(RPin6, initialOutputState);
}

void loop() {

  // Gestion de l'alimentation générale (buttonPin1)
  if (digitalRead(buttonPin1) == LOW && millis() - prevMillis > R_delay) {
    prevMillis = millis();                                                      // Stocke le temps actuel
    RPin1_activated = !RPin1_activated;
    RPin3_activated = !RPin3_activated;
    digitalWrite(RPin6, RPin1_activated);                                       // Inverse l'état de RPin6 en fonction de RPin1_activated
    if (!RPin1_activated) {
      digitalWrite(RPin1, initialOutputState);
      digitalWrite(RPin2, initialOutputState);
      digitalWrite(RPin3, initialOutputState);
      digitalWrite(RPin4, initialOutputState);
      stateRPin1 = stateRPin2 = stateRPin6 = initialOutputState;
      stateRPin3 = stateRPin4 = stateRPin6 = initialOutputState;
    }
  }

  // Gestion sélecteur d'entrée (buttonPin)
  if (digitalRead(RPin6) == HIGH) {
  if (digitalRead(buttonPin) == LOW && millis() - prevMillis > R_delay) {
    prevMillis = millis();                                                      // Stocke le temps actuel
    stateRPin1 = !stateRPin1;
    stateRPin2 = !stateRPin2;
    digitalWrite(RPin1, stateRPin1);
    digitalWrite(RPin2, stateRPin2);
  }
}
  // Gestion sélecteur sortie (buttonPin2)
  if (digitalRead(RPin6) == HIGH) {
  if (digitalRead(buttonPin2) == LOW && millis() - prevMillis > R_delay) {
    prevMillis = millis();                                                      // Stocke le temps actuel
    stateRPin3 = !stateRPin3;
    stateRPin4 = !stateRPin4;
    digitalWrite(RPin3, stateRPin3);
    digitalWrite(RPin4, stateRPin4);
  }
  }
  // Gestion du temporisateur pour RPin1 (entrée)
  if (RPin1_activated && millis() - prevMillis >= RPin1_delay) {
    if (!stateRPin2) {                                                           // Si RPin2 est LOW
      stateRPin1 = !stateRPin1;
      digitalWrite(RPin1, stateRPin1);
    }
  }

  // Gestion du temporisateur pour RPin3 (sortie)
  if (RPin3_activated && millis() - prevMillis >= RPin1_delay) {
    if (!stateRPin4) {                                                            // Si RPin4 est LOW
      stateRPin3 = !stateRPin3;
      digitalWrite(RPin3, stateRPin3);
    }
  }
}

Ton code ne semble pas faire de distinction entre les deux sorties, puisque tu positionne les deux états en même temps à leur contraire.
Si tu veux faire une bascule, il faudrait que si les deux états stateRPin3 et stateRPin4 sont à HIGH, il choisisse l'un des deux et si ils sont opposés les intervertissent.

C'est un programme qui se prête bien à l'utilisation d'une machine à état. Il y a un bon tuto ici:

j'ai demandé à chatGPT pour voir et après quelques itérations, engueulades et conseils d'amis il m'a généré

#include <OneButton.h>

const byte PIN_BOUTON_ALIMENTATION = 3;
const byte PIN_SELECTEUR_SORTIE = 4;
const byte PIN_SELECTEUR_ENTREE = 5;
const byte PIN_RELAY_12 = 12;
const byte PIN_RELAY_11 = 11;
const byte PIN_RELAY_10 = 10;
const byte PIN_RELAY_7 = 7;
const byte PIN_RELAY_2 = 2;

OneButton boutonAlimentation(PIN_BOUTON_ALIMENTATION, true);
OneButton boutonSelecteurSortie(PIN_SELECTEUR_SORTIE, true);
OneButton boutonSelecteurEntree(PIN_SELECTEUR_ENTREE, true);

enum  EtatAlimentation : byte {
  ETEINT,
  ALLUMAGE_EN_COURS,
  ALLUME,
  EXTINCTION_EN_COURS
};

EtatAlimentation etatAlimentation = ETEINT;
boolean etatSelecteurSortieActif = false;
boolean etatSelecteurEntreeActif = false;
unsigned long debutAllumage = 0;

void boutonAlimentationAppuye() {
  if (etatAlimentation == ETEINT) {
    digitalWrite(PIN_RELAY_12, HIGH);
    etatAlimentation = ALLUMAGE_EN_COURS;
    debutAllumage = millis();
  } else if (etatAlimentation == ALLUME) {
    etatAlimentation = EXTINCTION_EN_COURS;
  }
}

void boutonSelecteurSortieAppuye() {
  etatSelecteurSortieActif = !etatSelecteurSortieActif;
  digitalWrite(PIN_RELAY_11, etatSelecteurSortieActif ? HIGH : LOW);
  digitalWrite(PIN_RELAY_10, etatSelecteurSortieActif ? LOW : HIGH);
}

void boutonSelecteurEntreeAppuye() {
  etatSelecteurEntreeActif = !etatSelecteurEntreeActif;
  digitalWrite(PIN_RELAY_7, etatSelecteurEntreeActif ? HIGH : LOW);
  digitalWrite(PIN_RELAY_2, etatSelecteurEntreeActif ? LOW : HIGH);
}

void setup() {
  pinMode(PIN_RELAY_12, OUTPUT);
  pinMode(PIN_RELAY_11, OUTPUT);
  pinMode(PIN_RELAY_10, OUTPUT);
  pinMode(PIN_RELAY_7, OUTPUT);
  pinMode(PIN_RELAY_2, OUTPUT);

  boutonAlimentation.attachClick(boutonAlimentationAppuye);
  boutonSelecteurSortie.attachClick(boutonSelecteurSortieAppuye);
  boutonSelecteurEntree.attachClick(boutonSelecteurEntreeAppuye);

}

void loop() {
  boutonAlimentation.tick();
  boutonSelecteurSortie.tick();
  boutonSelecteurEntree.tick();

  switch (etatAlimentation) {
    case ALLUMAGE_EN_COURS:
      if (millis() - debutAllumage >= 4000) {
        digitalWrite(PIN_RELAY_11, etatSelecteurSortieActif ? HIGH : LOW);
        digitalWrite(PIN_RELAY_10, etatSelecteurSortieActif ? LOW : HIGH);
        digitalWrite(PIN_RELAY_7, etatSelecteurEntreeActif ? HIGH : LOW);
        digitalWrite(PIN_RELAY_2, etatSelecteurEntreeActif ? LOW : HIGH);
        etatAlimentation = ALLUME;
      }
      break;

    case EXTINCTION_EN_COURS:
      digitalWrite(PIN_RELAY_12, LOW);
      digitalWrite(PIN_RELAY_11, LOW);
      digitalWrite(PIN_RELAY_10, LOW);
      digitalWrite(PIN_RELAY_7, LOW);
      digitalWrite(PIN_RELAY_2, LOW);
      etatAlimentation = ETEINT;
      break;
    default: break;
  }
}

en mettant ça dans wokwi ça a l'air pas trop mal

bon j'ai plus galéré à expliquer ce que je voulais à ChatGPT et lui faire corriger ses bugs que taper le code directement.... :slight_smile:

PS/ il y a un truc qu'il n'arrivait pas à faire donc j'ai fait la modification moi même (pour ALLUMAGE_EN_COURS)

Au final, on peut voir que le gain du passage à une machine à état est presque nul sur cet exemple précis :frowning:

Je me demande, si il ne manque pas dans le "cahier des charges" un état au bouton de switch avec un double click, pour repasser en dual ?

On revient que searchGPT est vraiment pertinent lorsque l'on cherche comment faire ou le nom d'une classe, que pour générer du code que l'on sait faire :slight_smile:

disons qu'on n'a pas un code bloquant sur les 4 secondes, ce qui fait que si on fait power et juste après on appuie et relâche IN ou OUT ce sera pris en compte

Oui, mais du coup tu perds la fonctionnalité d'entre 4s avant de connecter l'entrée et la sortie ?

oui, la spécification

ne précise pas que c'est interdit tant que le cycle POWER n'est pas terminé :slight_smile:
(bien que tel que c'est codé, ce n'est pas forcément 11 et 7 qui seront activées)

Sauf que du coup, tu ne respecte plus cela

sauf lorsque j'allume l'ampli, la tempo de 4 sec s'écoule, les 2 sorties s'activent

Si on respecte toutes les conditions exprimées, ton code devrais permettre de switcher pendant 4s, puis allumer les deux sorties :joy:

ce n'était pas dans le cahier des charges, c'était un commentaire sur ce qui ne fonctionnait pas

Chacun sa définition du cahier des charges, pour moi tout commentaire ou annotation est à intégrer dans le cahier des charges :joy: :laughing:

C’est chatGPT qui n’a pas compris :slight_smile:

Bonjour,

Merci JML pour ce code, il fonctionne bien.

Effectivement je n'ai pas ajouté cette contrainte car l'appareil est destiné à mon usage, mais c'est une sécurité supplémentaire que j'aurais aimé ajouter. je vais de ce pas regarder se que je peux faire, je ne connaissais pas cette librairie, excellente.

Je suppose que je peux aussi lui demander lors d'un appuie long "3sec" de réinitialiser la séquence de l'ARDUINO ? une autre option intéressante.

Ce n'est pas bloquant, il suffit de changer l'affectation des broches ou l'ordre des sorties dans

switch (etatAlimentation) {
    case ALLUMAGE_EN_COURS:
      if (millis() - debutAllumage >= 4000) {
        digitalWrite(PIN_RELAY_10, etatSelecteurSortieActif ? HIGH : LOW);
        digitalWrite(PIN_RELAY_11, etatSelecteurSortieActif ? LOW : HIGH);
        digitalWrite(PIN_RELAY_2, etatSelecteurEntreeActif ? HIGH : LOW);
        digitalWrite(PIN_RELAY_7, etatSelecteurEntreeActif ? LOW : HIGH);
        etatAlimentation = ALLUME;
      }
      break;

Merci fdufnews pour ce tuto, je vais m'instruire.

Après quelques recherches j'ai vu qu'il était possible d'ajouter des conditions dans le Void boutonselecteur, j'ai copier l'état plus haut dans le code :

if (etatAlimentation == ALLUME) {

Ça fonctionne parfaitement , la sélection n'est pas possible même pendant le délai de 4 sec :ok_hand:

Pour la fonction réinitialisation, j'ai trouvé avec Chatgpt la fonction : NVIC_SystemReset() mais à priori elle ne fonctionne pas sur ARDUINO nano, j'approfondirai plus tard.

Merci Terwal pour ton retour,

Effectivement c'est se que j'ai constaté, j'avais le même soucis avec les commandes "if (nouvelEtatEntree1 != etatEntree1) {" bien que l'allumage des sorties 11 & 7 donnait une position de départ.

J'ai testé d'ajouter des conditions supplémentaires avec différent de mais ça ne fonctionnait pas, maintenant que j'y pense, je pourrais utiliser

previousButtonValue1 = buttonValue1;

pour sauvegarder l'état après l'allumage de POWER, je testerai ça demain matin.

Bonjour,

Après vérification ma solution fonctionne, tout fonctionne sauf la sélection des entrées sorties pendant les 4 secondes de battement, voici le code pour info:

//Amplificateur casque

// Constantes pour les broches d'entrée et de sortie

const int buttonPin = 5;       //Bouton-poussoir en broche 5, Sélecteur de sortie
int buttonValue = 0;           //Variable pour enregistrer l'état du bouton-poussoir
int previousButtonValue = 0;   //Variable pour enregistrer l'ancien état du bouton-poussoir
const int buttonPin1 = 6;      //Bouton-poussoir en broche 1, bouton ON/OFF
int buttonValue1 = 0;          //Variable pour enregistrer l'état du bouton-poussoir
int previousButtonValue1 = 0;  //Variable pour enregistrer l'ancien état du bouton-poussoir
const int buttonPin2 = 4;      //Bouton-poussoir en broche 1, Sélecteur Sortie
int buttonValue2 = 0;          //Variable pour enregistrer l'état du bouton-poussoir
int previousButtonValue2 = 0;  //Variable pour enregistrer l'ancien état du bouton-poussoir

const int RPin1 = 11;  //relais en broche 11, bascule SCR 1
const int RPin2 = 10;  //relais en broche 10, bascule SRC 2
const int RPin3 = 07;  //relais en broche 11, CASQUE
const int RPin4 = 02;  //relais en broche 10, PREAMPLI
const int RPin6 = 12;  //relais POWER

boolean ETAT_RPin6 = HIGH;
boolean ETAT_buttonPin = HIGH;
boolean ETAT_buttonPin1 = HIGH;
boolean ETAT_buttonPin2 = HIGH;

unsigned long currentTime = 0;
unsigned long previousTime = 0;  // variable qui stocke la mesure du temps

unsigned long prevMillis = 0;  // État d'activation de la tempo
int R_delay = 200;             // Temps à l'activation de la tempo en MS
int R_delay2 = 4000;           // Temporisation POWER de 4sec
bool RState = 0;

int new_bp = 0, old_bp = 0;  // condition Rpin6 POWER

void setup() {
  pinMode(buttonPin, INPUT_PULLUP);   //Sélecteur de sortie
  pinMode(buttonPin1, INPUT_PULLUP);  //bouton ON/OFF
  pinMode(buttonPin2, INPUT_PULLUP);  //bouton ON/OFF

  pinMode(RPin1, OUTPUT);  //relais en broche 07, bascule SCR 1
  pinMode(RPin2, OUTPUT);  //relais en broche 06, bascule SRC 2
  pinMode(RPin3, OUTPUT);  //relais en broche 07, bascule CASQUE
  pinMode(RPin4, OUTPUT);  //relais en broche 06, bascule PREAMPLI
  pinMode(RPin6, OUTPUT);  //sortie Alimentation Générale

  digitalWrite(buttonPin, HIGH);  // Déclare BP1 à l'état haut
  digitalWrite(RPin1, LOW);
  digitalWrite(RPin2, LOW);
  digitalWrite(RPin3, LOW);
  digitalWrite(RPin4, LOW);
  digitalWrite(RPin6, LOW);
}

void loop() {


  // GESTION ALIMENTATION GENERALE

  buttonValue1 = digitalRead(buttonPin1);  //Interrogation du bouton-poussoir

  if (previousButtonValue1 != buttonValue1 && millis() - prevMillis > R_delay) {
    if (buttonValue1 == HIGH) {
      digitalWrite(RPin6, !digitalRead(RPin6));  // Inverse l'état du relais 5v
      prevMillis = millis();
    }
  }
  previousButtonValue1 = buttonValue1;  //Sauvegarde de la valeur actuelle du bouton-poussoir


//  ACTIVATION SORTIE CASQUE & PRE-AMPLI SOUS CONDITION DU POWER

  new_bp = digitalRead(RPin6);
  if ((new_bp != old_bp) && (new_bp == 1) && millis() - prevMillis > R_delay2) {
    digitalWrite(RPin1, HIGH);
    digitalWrite(RPin3, HIGH);
  }  else if (digitalRead(RPin6) == LOW) {
      digitalWrite(RPin1, LOW); 
      digitalWrite(RPin2, LOW); 
      digitalWrite(RPin3, LOW); 
      digitalWrite(RPin4, LOW); 
  }
  boolean previousETAT_RPin6 = ETAT_RPin6;
  previousButtonValue = buttonValue;  //Sauvegarde de la valeur actuelle du bouton-poussoir
  previousButtonValue2 = buttonValue2;  //Sauvegarde de la valeur actuelle du bouton-poussoir

  // SELECTEUR DE SOURCE
  buttonValue = digitalRead(buttonPin);  //Interrogation du bouton-poussoir

  if (previousButtonValue != buttonValue && millis() - prevMillis > R_delay) {
    if (buttonValue == HIGH && digitalRead(RPin6) == HIGH) {
      digitalWrite(RPin1, !digitalRead(RPin1));  // Inverse l'état du relais, bascule ampli
      digitalWrite(RPin2, !digitalRead(RPin2));  // Inverse l'état du relais, bascule preampli
      prevMillis = millis();
    }
  }
  previousButtonValue = buttonValue;  //Sauvegarde de la valeur actuelle du bouton-poussoir


  // SELECTEUR DE SORTIE

  buttonValue2 = digitalRead(buttonPin2);  //Interrogation du bouton-poussoir

  if (previousButtonValue2 != buttonValue2 && millis() - prevMillis > R_delay) {
    if (buttonValue2 == HIGH && digitalRead(RPin6) == HIGH) {
      digitalWrite(RPin4, !digitalRead(RPin4));  // Inverse l'état du relais, bascule preampli
      digitalWrite(RPin3, !digitalRead(RPin3));  // Inverse l'état du relais, bascule ampli
      prevMillis = millis();
    } 
  }
  previousButtonValue2 = buttonValue2;  //Sauvegarde de la valeur actuelle du bouton-poussoir
}

c'est ce que vous vouliez non ?

Comme évoqué plus haut c'était déjà compliqué de le faire fonctionner tel quel, mais le problème est régler.

J'aurais aimé cependant y arriver avec mon code de départ (post#16).

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.