Selecteur de source/sortie et gestion d'une télécommande

Bonjour,

j'ai récemment entrepris la conception et la fabrication d'un amplificateur de casque en pure classe A (je précise que la conception s'arrête autour du circuit d'amplification qui n'est pas de moi).
Le but étant d'avoir un système pleinement opérationnel avec télécommande et les fonctions utile à mes besoins:

  • Gestion du volume
  • Gestion de l'alimentation
  • Gestion des sources/sorties
    Le tout dans un coffrage design qui me plait.

Concernant le volume j'ai trouvé mon bonheur avec un atténuateur à étages pilotés par des relais et qui possède déjà sa propre télécommande, elle permet de monter et descendre le volume, mute, changer la luminosité de l'affichage et possède un bouton ON/OFF qui n'était pas pris en charge par le système.

Pour l'alimentation, J'ai donc décider de récupérer le code de ce bouton ON/OFF et de l'utiliser sur une seconde cellule IR avec l'Arduino, en parallèle d'un bouton poussoir en façade.

Les sources sont gérées par l'Arduino à l'aide d'un seul bouton poussoir, chaque appuie change la sortie (dans mon cas elles seront utilisées en sortie).

Les fonctions en détail:

  • Sélection des sorties:
    il y en a 3, deux doivent être temporisées (1.5sec) à l'allumage pour éviter le "ploc" de l'ampli, j'ai donc utilisé la variable Millis, la troisième sortie est destinée à mon amplificateur 2x25W, elle fonctionnera comme Pré-amplificateur passif, je souhaite donc couper l'alimentation de l'ampli casque lorsque celle-ci est activée. Partie fonctionnelle indépendamment

  • Gestion de l'alimentation:
    La gestion du ON/OFF de la télécommande est confié à la bibliothèque IRremote.h, la télécommande utilisée me transmet 2 codes distinct qui varie en fonction du temps d’appui, le bémol c'est qu'il n'est pas possible de le gérer tellement l'écart est faible, autre problèmes, sur un appui court, voir même très court elle m'envoie plusieurs fois le code, j'ai donc géré ce problème avec "delay", comme pour traiter un rebond sur un bouton poussoir.
    Pour les 2 codes, j'ai simplement dupliqué la commande avec le second code. Partie fonctionnelle indépendamment

  • Concernant l'initialisation de l'ARduino, j'utiliserai un relais sans opto-coupleur pour couper l'alimentation 5v de la batterie de relais de sorties, afin d'éviter le bagotement.

J'ai plusieurs problèmes, mais je souhaiterai les aborder dans l'ordre, le premier réside dans la commande ON/OFF qui fonctionne bien avec le bouton poussoir, mais la télécommande ne donne qu'une impulsion au relais, comment résoudre ce conflit ?

PS: Je programmais à l'époque en Grafcet et schématique sur OMRON, je suis donc novice en "C", merci pour votre compréhension.
PS2: j'ai supprimé une partie des commentaires dans le code car je dépassai les 9000 caractères autorisés :slight_smile:

[code]


//Amplificateur casque 

#include <IRRemoteControl.h>
#include <IRRemoteControlInt.h>

#include <IRremote.h>

const int buttonPin = 2;         //Bouton-poussoir en broche 2, Sélecteur de sortie
int buttonValue = 0;                       
int previousButtonValue = 0;                
const int buttonPin1 = 3;        //Bouton-poussoir en broche 3, bouton ON/OFF
const int RPin1= 9;           //relais en broche 09, sortie JACK 6.3
const int RPin2= 10;          //relais en broche 10, sortie XLR
const int RPin3= 11;          //relais en broche 11, sortie Amplificateur (sortie RCA)
const int RPin5= 13;          //relais en broche 13, sortie Alimentation amplificateur casque
int RPin6= 12;               //relais en broche 12, sortie Alimentation Générale

int counter= 3;      //Variable de compteur[/u]

boolean ETAT_RPin6=HIGH;
boolean ETAT_RPin5=HIGH;
boolean ETAT_buttonPin1=HIGH;
 
unsigned long currentTime=0;
unsigned long previousTime=0;   // variable  temps

int prevMillis = 0;           // État d'activation de la tempo
int R_delay = 1500;          // Temps à l'activation de la tempo
int R_delay1 = 10;
bool RState = 0;

int receptionIr = 4;         //signal du récepteur IR
int etat = 0;                               

IRrecv irrecv(receptionIr);   //Initialisation de la récepteion du réceptur IR
decode_results resultat;                    
 
void setup() {

pinMode(buttonPin, INPUT_PULLUP);                        
pinMode(buttonPin1, INPUT_PULLUP);                       
pinMode(RPin1, OUTPUT);                                  
pinMode(RPin2, OUTPUT);                                  
pinMode(RPin3, OUTPUT);                                  

pinMode(RPin5, OUTPUT);                                  

digitalWrite(buttonPin1, HIGH);                          
digitalWrite(RPin5, HIGH);                               
digitalWrite(RPin1, HIGH);   

irrecv.enableIRIn();                                     
etat=0;                                                  

//GESTION ALIMENTATION RELAIS 5V

pinMode(RPin6, OUTPUT);                                  
digitalWrite(RPin6, LOW);                               

}

void loop() {

  buttonValue = digitalRead (buttonPin);                     

 if(previousButtonValue != buttonValue){
   if(buttonValue == LOW){
     counter++;                                              
   }
 }
 previousButtonValue = buttonValue;                          


//RELAIS 1   sortie JACK 6.3



 if(counter % 3 == 0 && millis() - prevMillis > R_delay) {      //Variable du compteur + temporisation 1500ms
     digitalWrite(RPin1,RState);
     prevMillis = millis();
 }

 else if(counter % 3 != 0 && millis() - prevMillis > R_delay1){
     digitalWrite(RPin1,HIGH);
       delay(10);         //Attendre 10ms avant d'intérroger à nouveau le bouton-poussoir
        
 }

//RELAIS 2   sortie XLR

   
 
 if(counter % 3 == 1 && millis() - prevMillis > R_delay) {      //Variable du compteur + temporisation 1500ms
   digitalWrite(RPin2,LOW);
 prevMillis = millis();
 }

else if(counter % 3 != 1 && millis() - prevMillis > R_delay1){
 digitalWrite(RPin2,HIGH);
  delay(10);           //10ms intérroger bp
}


//RELAIS 3   sortie Amplificateur

                         
 if(counter % 3==2) {       //Variable du compteur sans tempo
 digitalWrite(RPin3,LOW);
  prevMillis = millis();
 }
else
 digitalWrite(RPin3,HIGH);
  delay(10);              //10ms intérroger bp
    

//GESTION ALIMENTATION SECONDAIRE

 
 if(counter % 3 ==2)             //Variable du compteur
 digitalWrite(RPin5,HIGH);

else
 digitalWrite(RPin5,LOW);
  delay(10);                 //10ms intérroger bp


// GESTION ALIMENTATION GENERALE


if(ETAT_buttonPin1==HIGH){        // Déclaration de l'état initiale du BP
  if (digitalRead(buttonPin1)==0)      // Lecture de l'état de BP  
  {
    delay(5);
    ETAT_RPin6 = !ETAT_RPin6;
    ETAT_buttonPin1 = LOW;
  }}
  else if(digitalRead(buttonPin1)==1){                       
   
    ETAT_buttonPin1=HIGH;}
    digitalWrite(RPin6,ETAT_RPin6);


//GESTION TELECOMMANDE


if (irrecv.decode(&resultat))       //Si il y a reception d'un code qui est stocké dans resulat
    {
  delay (100);
    if (resultat.value==0x2FD)   //Si le code reçus vaut le code du bouton que vous avez programmés (ici c'est 0xFF30CF qui est égale au bouton 1 de ma télécommande)
       {
        if(etat==0)             //si etat=0
          {
           digitalWrite(RPin6 ,HIGH);    //Ici le relais est a l'état haut (il est alimenté)
            etat=1;             //etat est maintenant a 1
                 }              //fin du if
     else if(etat==1)             //sinon, si etat=1
             {
           digitalWrite(RPin6 ,LOW);      //Ici le relais est a l'etat bas (il n'est pas alimenté)
            etat=0;              //etat est maintenant a 0
          }                     //fin du else if
       }
 if (resultat.value==0xAFD)           //Si le code reçus vaut le code du bouton que vous avez programmés (ici c'est 0xFF18E7 qui est égale au bouton 2 de ma télécommande)
       {
      delay (100);
        if(etat==0)           //si etat=0
          {
           digitalWrite(RPin6 ,HIGH); //Ici le relais est a l'état haut (il est alimenté)
            etat=1;           //etat est maintenant a 1
                 }            //fin du if(etat==0)
     else if(etat==1)         //sinon, si etat=1
              {
        digitalWrite(RPin6 ,LOW);   //Ici le relais est a l'etat bas (il n'est pas alimenté)
          etat=0;           //etat est maintenant a 0
          }                //fin du else ifetat==1)
       }                 //Fin du if (resultat.value==0xFF18E7)    
 irrecv.resume(); 
   }  
}

[/code]

Bonjour,

Apparemment ta télécommande envoi le code avec un 'toggle bit'
Il faut que tu testes si le code reçu est différent du code reçu précédent pour ne pas traiter les répétitions de la télécommande.
Ca donne un code comme ceci

  if (irrecv.decode(&resultat))       //Si il y a reception d'un code qui est stocké dans resulat
  {
    static unsigned prevCode = 0; // code précédemment reçu
    if (resultat.value != prevCode)
    {
      prevCode = resultat.value;
      unsigned code = resultat.value & ~0x800; // ote le toggle bit
      if (code == 0x2FD) //Si le code reçus vaut le code du bouton que vous avez programmé
      {
        digitalWrite(RPin6 , !digitalRead(RPin6));   // Inverse l'état du relais
      }
      irrecv.resume();
    }
  }

Merci Kamill pour la réponse rapide.

J'ai testé ton code, mais il restait figé après une première action de la télécommande, j'ai remonté "irrecv.resume()" au dessus de "static unsigned" et la boucle se fait correctement, il ne manque plus qu'un petit délai et tout fonctionne parfaitement.

[code]

#include <IRremote.h>

const int receiver = 4;           // pin 1 of IR receiver to Arduino digital pin 3

IRrecv irrecv(receiver);          // create instance of 'irrecv'

decode_results resultat;

int RPin6 = 12;                             //relais en broche 12, sortie Alimentation Générale



void setup() {

  pinMode(RPin6, OUTPUT);                                  //sortie Alimentation Générale
  Serial.begin(9600);
  irrecv.enableIRIn();
}


void loop() {

  if (irrecv.decode(& resultat))                                 //Si il y a reception d'un code qui est stocké dans resulat
  { irrecv.resume();
    delay(50);                                                 // delais pour éviter le rebond
    static unsigned prevCode = 0;                               // code précédemment reçu
    if (resultat.value != prevCode)
    {
      prevCode = resultat.value;
      unsigned code = (resultat.value & ~0x800);                    // ote le toggle bit
      if (code == 0x2FD)                                         //Si le code reçus vaut le code du bouton que vous avez programmé
      {
        digitalWrite(RPin6 , !digitalRead(RPin6));              // Inverse l'état du relais
      }

    }
  }

}

[/code]

j'ai explorer un autre lecteur de code IR (toggle bit), cela ma permis de déterminer le type "RC5".

En revanche, une fois inclus dans mon programme, je me retrouve dans la même situation que précédemment:

  • A chaque appuie sur la télécommande, le relais s'allume et s'éteint immédiatement.

Je pense que mon problème vient du fait que j'ai une autre ligne de commande sur la sortie "Rpin6", piloté par le bouton poussoir "buttonPin1".

Effectivement, irrecv.resume() doit être dans le if (irrecv.decode(&resultat))

Concernant la gestion des boutons, il faut que tu fasses avec boutonpin1 le même traitement qu’avec boutonpin, c'est à dire qu'il faut comparer à l'état précédent et changer l'état du relais lorsque le bouton vient d'être appuyé.

Parfait, J'ai repris le code du "boutonpin" et j'ai modifié l'état du "boutonvalue" en HIGH et cela fonctionne, merci.
J'en ai profité aussi pour intégrer ta solution d'inversion de l'état "digitalWrite(RPin6 , !digitalRead(RPin6));".

// GESTION ALIMENTATION GENERALE

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

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



  //GESTION TELECOMMANDE

  if (irrecv.decode(& resultat))                             //Si il y a reception d'un code qui est stocké dans resulat
  { irrecv.resume();
    delay(50);                                                // delais pour éviter le rebond
    static unsigned prevCode = 0;                              // code précédemment reçu
    if (resultat.value != prevCode)
    {
      prevCode = resultat.value;
      unsigned code = (resultat.value & ~0x800);               // ote le toggle bit
      if (code == 0x2FD)                                       //Si le code reçus vaut le code du bouton que vous avez programmé
      {
        digitalWrite(RPin6 , !digitalRead(RPin6));             // Inverse l'état du relais
      }

    }
  }

Second problème:

  • Ma temporisation sur les relais de sorties fonctionne parfaitement pendant un temps (environ 30 secondes) et par la suite je n'ai plus de tempo, les relais commute directement, ai-je fais une erreur dans l'utilisation de Millis ?

Tu définis prevMillis comme int. Ce doit être un unsigned long.
C'est sans doute ça ton problème: prevMillis déborde au bout d'un certain temps, en fait au bout de 32767 millis secondes soit environ 32 secondes.

Merci Kamil,
Effectivement c'était ça. Désolé pour le retour tardif, j'étais très occupé avec le reste de l'ampli.
J'ai reçu tous le matériel (relais) du coup je me remet dans le codage.
J'ai mis un relais sans optocoupleur afin de palier à l'initialisation de l'ARDUINO, mais ce n'est pas suffisant, le courant est suffisant pour donner le contact un cour instant, existe t'il une autre alternative que l'utilisation d'un relais temporisé ?

C'est curieux, à l'initialisation les pins de l'arduino sont en entrée et ne peuvent fournir un courant suffisant pour commander l'optocoupleur. Idem s'il n'y a pas d'optocoupleur le courant que peut débiter une entrée ne semble pas suffisant pour commander un transistor.
Quel module relais utilises tu?

C'est se que j'avais lu sur plusieurs forum, mon arduino nano est un Az-delivery.
Je l'utilise avec un module Az-delivery KY-019 et un module 8 channel Eelegoo avec optocoupleur.

Lorsque j'ajoute un delay à ce programme (pour éviter un rebond sur le bouton"buttonpin") le relais commute à l’initialisation, mais lorsque ce délai est absent, j'ai bien un fonctionnement normal, CAD pas de commutation, juste un très léger scintillement de la LED du relais, mais lui ne commute pas.

Peut être un élément de réponse.

//Amplificateur casque

#include <IRremote.h>

const int buttonPin = 2;                     
int buttonValue = 0;                         
int previousButtonValue = 0;                 
const int buttonPin1 = 1;                    
int buttonValue1 = 0;                        
int previousButtonValue1 = 0;                
int buttonValue3 = 0;                        
int previousButtonValue3 = 0;                

const int RPin1 = 10;                        
const int RPin2 = 11;                        
const int RPin6 = 12;                        

const int ledPin3 = 3;                       

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

unsigned long currentTime = 0;
unsigned long previousTime = 0;              

unsigned long prevMillis = 0;                
int R_delay = 2000;                          
int R_delay1 = 10;
bool RState = 0;

const int receiver = 4;                      
int etat = 0;                                

IRrecv irrecv(receiver);                     
decode_results resultat;                     



void setup() {

  pinMode(buttonPin, INPUT_PULLUP);                        //Sélecteur de sortie
  pinMode(buttonPin1, INPUT_PULLUP);                       //bouton ON/OFF
  pinMode(RPin1, OUTPUT);                                  //relais en broche 11, bascule ampli-preampli canal droit
  pinMode(RPin2, OUTPUT);                                  //relais en broche 11, bascule ampli-preampli canal gauche

  pinMode(RPin6, OUTPUT);                                  //sortie Alimentation Générale

  pinMode(ledPin3, OUTPUT);                                //sortie LED bleu bouton ON/OFF

  digitalWrite(buttonPin1, HIGH);                          // Déclare BP1 à l'état haut
  digitalWrite(buttonPin, HIGH);                          // Déclare BP1 à l'état haut
  digitalWrite(RPin1, LOW);
  digitalWrite(ledPin3, HIGH);


  irrecv.enableIRIn();                                     //Activation de la réception
  etat = 0;                                                //etat indique si le relais est éteint (etat=0) ou si il est allumé (etat=1)

  //GESTION ALIMENTATION RELAIS 5V

  pinMode(RPin6, OUTPUT);                                  //Broche LED6 comme sortie, sortie Alimentation 5v
  digitalWrite(RPin6, HIGH);                               // Déclare RelaisPin6 à l'état haut
}


void loop() {

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

  if (previousButtonValue != buttonValue) {
    if (buttonValue == HIGH) {
      digitalWrite(RPin1 , !digitalRead(RPin1));              // Inverse l'état du relais 5v
      digitalWrite(RPin2 , !digitalRead(RPin2));
    }
  }
  previousButtonValue = buttonValue;                         //Sauvegarde de la valeur actuelle du bouton-poussoir
  delay(20);

  // GESTION ALIMENTATION GENERALE


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

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


  //GESTION TELECOMMANDE

  if (irrecv.decode(& resultat))                                //Si il y a reception d'un code qui est stocké dans resulat
  { irrecv.resume();
    delay(50);                                                  // delais pour éviter le rebond
    static unsigned prevCode = 0;                               // code précédemment reçu
    if (resultat.value != prevCode)
    {
      prevCode = resultat.value;
      unsigned code = (resultat.value & ~0x800);                // ote le toggle bit
      if (code == 0x2FD)                                        //Si le code reçus vaut le code du bouton que vous avez programmé
      {
        digitalWrite(RPin6 , !digitalRead(RPin6));              // Inverse l'état du relais 5v
        digitalWrite(ledPin3, !digitalRead(ledPin3));
      }

    }
  }

}                                            //fin boucle

J'ai donc édité mon code avec l'utilisation de "prevmillis" et cela fonctionne parfaitement, mais je ne comprend pas pourquoi "delay" pose ce problème.

Dans ton setup tu as 2 fois pinMode(RPin6, OUTPUT); séparés par plusieurs instructions. Enlèves le premier.
Tu peux aussi mettre la pin à HIGH avant de la mettre en sortie. Ca ne dois pas changer grand chose car le relias ne doit pas avoir le temps de commuter en quelques microsecondes, mais ça ne coute rien de le faire.

  digitalWrite(RPin6, HIGH);                               // Déclare RelaisPin6 à l'état haut
  pinMode(RPin6, OUTPUT);                                  //Broche LED6 comme sortie, sortie Alimentation 5v

J'avais déjà édité ce doublon, mais oublié d'éditer le code posté.
:confused:

Je viens de test le "Rpin6, HIGH" en première instruction, toujours pareil.

Ce n'est pas la première fois que je vois ce problème sur le fofo, étrange.

Avec ton dernier programme du post #9 ça fait le problème?

Oui Kamil, par contre sur une version hyper light, cela fonctionne (voir ci-dessous). on peut supposer que "delay" est en conflit avec une autre commande ?

//Amplificateur casque

#include <IRremote.h>

const int buttonPin = 2;                     //Bouton-poussoir en broche 2, 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 RPin6 = 12;                        //relais en broche 12, sortie Alimentation 5v

const int ledPin3 = 3;                       //LED bleu bouton ON/OFF

boolean ETAT_RPin6 = HIGH;

boolean ETAT_buttonPin = HIGH;




void setup() {

  digitalWrite(RPin6, HIGH);
  pinMode(buttonPin, INPUT_PULLUP);

  pinMode(RPin6, OUTPUT);
  digitalWrite(ledPin3, HIGH);
  pinMode(ledPin3, OUTPUT);

  digitalWrite(buttonPin, HIGH);

}


void loop() {


  // GESTION ALIMENTATION GENERALE


  buttonValue = digitalRead (buttonPin);

  if (previousButtonValue != buttonValue) {
    if (buttonValue == HIGH) {
      digitalWrite(RPin6 , !digitalRead(RPin6));
      digitalWrite(ledPin3, !digitalRead(ledPin3));

    }
  }
  previousButtonValue = buttonValue;
  delay(20);

}                                            //fin boucle

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