mardi 8 mai 2012

Décodage d'un clavier d'orgue par un Arduino

Résumé du projet:  un vieux clavier d'orgue électronique est branché à un Arduino par l'entremise de deux registres à décalage HC595.  Lorsqu'on appuie sur une ou plusieurs touches du clavier, le nom des notes activées s'affiche à l'écran de l'ordinateur.

Le but ultime (qui sera atteint, je l'espère, dans un prochain article) sera de construire moi-même un instrument à clavier complet:  un clavier MIDI, un synthétiseur, une Keytar, peut-être?

J'ai déjà décrit le clavier et sa matrice dans un article précédent:  il a été récupéré d'un vieil orgue électronique Yamaha Electone qui avait été fabriqué au début des années '80.  Le clavier comporte 37 touches (3 octaves) et j'ai utilisé sans modification sa matrice de diodes.

Le schéma ci-dessous montre la matrice du clavier (dont je n'ai représenté que 4 des 37 touches).  Il y a 4 entrées d'octaves.  La première est reliée aux 8 premières touches du clavier (de FA à DO), la deuxième est reliée aux 12 touches suivantes (de DO# à DO), etc.  Il y a 12 entrées de notes:  une même entrée pour tous les "sol" , une autre entrée pour tous les "la", etc.

Pour identifier les touches qui sont enfoncées, j'ai opté pour le principe suivant (voir le circuit ci-dessous):  si je veux vérifier l'état de la touche "sol 1" je place l'entrée "octave 1" à 5 volts, les autres entrées d'octave à 0 volts, l'entrée "sol" à 0 V et les autres entrées de notes (la, si, do, etc.) à 5 V.

De cette façon, la sortie "octave 1" sera à 5 V si la touche "sol 1" est enfoncée puisqu'aucun courant ne circule dans la résistance.  Le voltage de la sortie "octave 1" deviendra (idéalement) 0 V lorsque la touche "sol 1" est enfoncée.  L'état des autres touches du même octave ne change rien, puisque ces touches ne sont soumises à aucune différence de potentiel (5 volts de part et d'autre).

Il s'agit ensuite de tester l'état de chacune des 37 touches du clavier, l'une après l'autre, ce que l'Arduino pourra faire très rapidement.


Mais pas question d'utiliser 20 entrées/sorties de l'Arduino (4 entrées d'octave, 12 entrées de notes et 4 sorties d'octave), surtout que mon Duemilanove en comporte beaucoup moins...  J'ai donc utilisé deux registres à décalage 74HC595 en cascade.  Puisque chaque registre à décalage comporte 8 sorties, ils contrôleront les 4 entrées d'octave et les 12 entrées de notes.


Si vous n'êtes pas familiers avec les registres à décalage, je mentionne rapidement qu'il s'agit d'un circuit intégré qui transforme un signal numérique 8 bits reçu de façon séquentielle à son entrée en un signal équivalent étalé en parallèle sur 8 sorties.  Par exemple, l'Arduino peut envoyer le message "11111111" à l'entrée du registre à décalage; sur réception de cette instruction, le régistre mettra ses 8 sorties  à 5 volts.  Si l'Arduino envoie le message "01010101", 4 sorties seront à 0 volt, les autres seront à 5 volts, etc.

Le schéma ci-dessous montre les branchements des deux registres à décalage.

Il restait ensuite à coder un sketch pour que l'Arduino vérifie les 37 touches du clavier l'une après l'autre.  J'ai d'abord tenté de produire  un programme élégant avec des boucles et des opérateurs "bitwise"...et je me suis lamentablement cassé la gueule:  rien ne fonctionnait!    Voici donc une version peu élégante, très répétitive,  mais qui a l'avantage de fonctionner (et qui est facile à comprendre, je crois), dans laquelle je vérifie l'état de chaque touche une par une.


Notez qu'à deux endroits dans le code, j'ai dû ajouter un délai d'une milliseconde (pour do#2 et do#3): sans ces délais, ces deux notes étaient mesurées à 0 V (position "touche enfoncée") sans que la touche du clavier ne soit enfoncée.  Je suppose qu'il faut laisser un peu de temps au circuit pour se stabiliser avant de prendre la mesure.

Dans cette version, le clavier ne produit aucun son:  le nom de la note s'affiche tout simplement dans le "serial monitor", à l'écran de l'ordinateur.  Et ça semble très bien fonctionner, même lorsqu'on fait un accord en enfonçant plusieurs touches simultanément.

Prochaine étape:  la version MIDI!

Mise à jour (12 mai 2012):  Cet article a maintenant une suite:  Clavier MIDI à base d'Arduino



int latchPin = 8; //Pin de l'Arduino branchée à la Pin 12 du 74HC595 (Latch)
int clockPin = 12; //Pin de l'Arduino branchée à la Pin 11 du 74HC595 (Clock)
int dataPin = 11; //Pin de l'Arduino branchée à la Pin 14 du 74HC595 (Data)
int octave1In= 2; // pin de l'Arduino qui reçoit le voltage pour le 1er octave
int octave2In = 3; // pin de l'Arduino qui reçoit le voltage pour le 2e octave
int octave3In = 4; // pin de l'Arduino qui reçoit le voltage pour le 3e octave
int octave4In = 5; // pin de l'Arduino qui reçoit le voltage pour le 4e octave


void setup() {

  pinMode(latchPin, OUTPUT);  
  pinMode(clockPin, OUTPUT);
  pinMode(dataPin, OUTPUT);
  
  pinMode(octave1In, INPUT);
  pinMode(octave2In, INPUT);
  pinMode(octave3In, INPUT);
  pinMode(octave4In, INPUT);
  
  Serial.begin(9600); // pour le serial monitor
}

void loop() {

//Testons la touche FA1

shiftOut(B11110001,B11111110);

if (!digitalRead(octave1In))
      {       
        Serial.println("FA1"); 
      }
    
//Testons la touche FA#1

shiftOut(B11110001,B11111101);

if (!digitalRead(octave1In))
      {       
        Serial.println("FA#1"); 
      }

//Testons la touche SOL1

shiftOut(B11110001,B11111011);

if (!digitalRead(octave1In))
      {       
        Serial.println("SOL1"); 
      }

//Testons la touche SOL#1

shiftOut(B11110001,B11110111);

if (!digitalRead(octave1In))
      {       
        Serial.println("SOL#1"); 
      }


//Testons la touche LA1

shiftOut(B11110001,B11101111);

if (!digitalRead(octave1In))
      {       
        Serial.println("LA1"); 
      }

//Testons la touche SIb1

shiftOut(B11110001,B11011111);

if (!digitalRead(octave1In))
      {       
        Serial.println("SIb1"); 
      }


//Testons la touche SI1

shiftOut(B11110001,B10111111);

if (!digitalRead(octave1In))
      {       
        Serial.println("SI1"); 
      }


//Testons la touche DO1

shiftOut(B11110001,B01111111);

if (!digitalRead(octave1In))
      {       
        Serial.println("DO1"); 
      }


//Testons la touche DO#1

shiftOut(B11100010,B11111111);

if (!digitalRead(octave2In))
      {
        Serial.println("DO#1"); 
      }

//Testons la touche RE1

shiftOut(B11010010,B11111111);

if (!digitalRead(octave2In))
      {
        Serial.println("RE1"); 
      }


//Testons la touche RE#1

shiftOut(B10110010,B11111111);

if (!digitalRead(octave2In))
      {
        Serial.println("RE#1"); 
      }


//Testons la touche MI1

shiftOut(B01110010,B11111111);

if (!digitalRead(octave2In))
      {
        Serial.println("MI1"); 
      }

//Testons la touche FA2

shiftOut(B11110010,B11111110);

if (!digitalRead(octave2In))
      {       
        Serial.println("FA2"); 
      }
    
//Testons la touche FA#2

shiftOut(B11110010,B11111101);

if (!digitalRead(octave2In))
      {       
        Serial.println("FA#2"); 
      }

//Testons la touche SOL2

shiftOut(B11110010,B11111011);

if (!digitalRead(octave2In))
      {       
        Serial.println("SOL2"); 
      }

//Testons la touche SOL#2

shiftOut(B11110010,B11110111);

if (!digitalRead(octave2In))
      {       
        Serial.println("SOL#2"); 
      }


//Testons la touche LA2

shiftOut(B11110010,B11101111);

if (!digitalRead(octave2In))
      {       
        Serial.println("LA2"); 
      }

//Testons la touche SIb2

shiftOut(B11110010,B11011111);

if (!digitalRead(octave2In))
      {       
        Serial.println("SIb2"); 
      }


//Testons la touche SI2

shiftOut(B11110010,B10111111);

if (!digitalRead(octave2In))
      {       
        Serial.println("SI2"); 
      }


//Testons la touche DO2

shiftOut(B11110010,B01111111);

if (!digitalRead(octave2In))
      {       
        Serial.println("DO2"); 
      }

//Testons la touche DO#2

shiftOut(B11100100,B11111111);
delay(1);

if (!digitalRead(octave3In))
      {
        Serial.println("DO#2"); 
      }



//Testons la touche RE2

shiftOut(B11010100,B11111111);

if (!digitalRead(octave3In))
      {
        Serial.println("RE2"); 
      }


//Testons la touche RE#2

shiftOut(B10110100,B11111111);

if (!digitalRead(octave3In))
      {
        Serial.println("RE#2"); 
      }


//Testons la touche MI2

shiftOut(B01110100,B11111111);

if (!digitalRead(octave3In))
      {
        Serial.println("MI2"); 
      }

//Testons la touche FA3

shiftOut(B11110100,B11111110);

if (!digitalRead(octave3In))
      {       
        Serial.println("FA3"); 
      }
    
//Testons la touche FA#3

shiftOut(B11110100,B11111101);

if (!digitalRead(octave3In))
      {       
        Serial.println("FA#3"); 
      }

//Testons la touche SOL3

shiftOut(B11110100,B11111011);

if (!digitalRead(octave3In))
      {       
        Serial.println("SOL3"); 
      }

//Testons la touche SOL#3

shiftOut(B11110100,B11110111);

if (!digitalRead(octave3In))
      {       
        Serial.println("SOL#3"); 
      }


//Testons la touche LA3

shiftOut(B11110100,B11101111);

if (!digitalRead(octave3In))
      {       
        Serial.println("LA3"); 
      }

//Testons la touche SIb3

shiftOut(B11110100,B11011111);

if (!digitalRead(octave3In))
      {       
        Serial.println("SIb3"); 
      }


//Testons la touche SI3

shiftOut(B11110100,B10111111);

if (!digitalRead(octave3In))
      {       
        Serial.println("SI3"); 
      }


//Testons la touche DO3

shiftOut(B11110100,B01111111);

if (!digitalRead(octave3In))
      {       
        Serial.println("DO3"); 
      }

//Testons la touche DO#3

shiftOut(B11101000,B11111111);

delay(1);

if (!digitalRead(octave4In))
      {
        Serial.println("DO#3"); 
      }

//Testons la touche RE3

shiftOut(B11011000,B11111111);

if (!digitalRead(octave4In))
      {
        Serial.println("RE3"); 
      }


//Testons la touche RE#3

shiftOut(B10111000,B11111111);

if (!digitalRead(octave4In))
      {
        Serial.println("RE#3"); 
      }


//Testons la touche MI3

shiftOut(B01111000,B11111111);

if (!digitalRead(octave4In))
      {
        Serial.println("MI3"); 
      }

//Testons la touche FA4

shiftOut(B11111000,B11111110);

if (!digitalRead(octave4In))
      {       
        Serial.println("FA4"); 
      }
} 

// la routine suivante n'est pas de moi...piqué quelque part...
void shiftOut(byte dataOut1,byte dataOut2) {
  boolean pinState; 

  digitalWrite(latchPin, LOW); 

  digitalWrite(dataPin, LOW); 
  digitalWrite(clockPin, LOW);
  for (int i=0; i<=7; i++) { 
    digitalWrite(clockPin, LOW); 
    
    if ( dataOut1 & (1 << i) ) {  
      pinState = HIGH;
    }
    else {
      pinState = LOW;
    }
   
    digitalWrite(dataPin, pinState);
    digitalWrite(clockPin, HIGH);
    digitalWrite(dataPin, LOW);
  }
  digitalWrite(clockPin, LOW); 

  digitalWrite(dataPin, LOW);
  digitalWrite(clockPin, LOW);
  for (int i=0; i<=7; i++) { 
    digitalWrite(clockPin, LOW); 
    
    if ( dataOut2 & (1 << i) ) {   
      pinState = HIGH;
    }
    else {
      pinState = LOW;
    }
   
    digitalWrite(dataPin, pinState);
    digitalWrite(clockPin, HIGH); 
    digitalWrite(dataPin, LOW);
  }
  digitalWrite(clockPin, LOW); 

  digitalWrite(latchPin, HIGH);
}



10 commentaires:

  1. Ou en est votre projet?
    J'ai réalisé un clavier Midi 61 touches avec un seul 74HC595 et un uno.
    si ça vous intéresse dites le moi
    Delcano

    RépondreSupprimer
    Réponses
    1. Je suis intéressé. Si'l vous plait, email à drancope@gmail.com

      Supprimer
    2. las_lb@hotmail.com thanks!!!

      Supprimer
    3. Bonjour,

      je suis allé au Synthfest 2016 à Nantes ce week end et en discutant avec des geeks, on voulait faire un proto de Keytar de 37 touches pour l'exposer sur scene l'année prochaine. Donc 32 touches c'est bon je sais faire mais au delà avec un seul 74HC595 à premiere vue je sèche. Pourriez vous m'aider? laurentnowacki@hotmail.fr. Merci!

      Supprimer
  2. Mon clavier MIDI est maintenant parfaitement fonctionnel. Ça me rappelle que j'avais l'intention de lui ajouter quelques fioritures mais il traîne dans un coin depuis près d'un an: il faudrait que je m'y remette.

    RépondreSupprimer
    Réponses
    1. Dear Mr.Pelletier
      I start a project Arduino/Midi using the first part of your project.
      I believe that at this time you have finalize your midi project.
      If possible I will appreciate if you can supply more information so I cam complete also my initial project.

      Tank you for your attention to my request,
      Madison
      mleapfrog@gmail.com

      Supprimer
    2. The complete project is here:
      http://electroniqueamateur.blogspot.ca/2015/06/clavier-midi-arduino-version-20.html

      Supprimer
  3. Bjr Delcano,
    Moi aussi je suis interessé par ton projet CLAVIER MIDI.
    adamastor59@hotmail.com
    Un grand merci...

    RépondreSupprimer
  4. bonsoir Delcano
    Je suis interresser par ton projet de clavier midi.
    Voici mon adresse perceval.barreau.laetitia@gmail.com
    merci pour ta réponse

    RépondreSupprimer
  5. Bonjour!
    J'ai besoin de votre aide j'ai un clavier m-audio keystation 61es qui ne fonctionne plus je voulais utilisée juste les touches avec arduino.... Merci! Azur0821@gmail.com

    RépondreSupprimer