LL412, Interface Midi CV/Gate et plus...

Durant la construction de mon modulaire, j'ai vite ressenti le besoin de développer un module de commande. Je me suis tourné vers la solution Arduino car le produit est vraiment sympa, ouvert, économique, facile à mettre en oeuvre sans PCB. Avec un simple port USB, on reprogramme le plus simplement du monde. L'environnement de développement est libre, convivial , fiable et performant même si il n'y a pas à proprement parler d'outil de deboggage et d'optimisation.

Spécifications du module

  • 2 CV (0-5V) (réglage précis de la conversion dans le logiciel) + 2 Gates 
  • Midi vers CV suivant la norme 1V/Octave sur cinq octaves (accord fin, transposition)
  • Mode Dual et Split
  • Gestion de l'expression, vélocité, modulation et bend
  • LFO combinable avec modulations, plusieurs formes d'onde
  • Gestion du MIDI Clock, Start, Stop etc...
  • Arpégiateur (différents motifs, range)
  • Mini séquenceur 32 pas.
  • Midi Thru, Midi Out
  • Interface ergonomique
Plutôt que de longues explications, une petite vidéo ;)






Le schéma

Le DAC et l'optocoupleur sont montés sur une plaque proto pour Arduino comme celle-ci
Mon DAC est un cms, la plaque proto intègre un emplacement pour ce type de composant.

Pour le compilateur, j'utilise et recommande la dernière version dispo à cette adresse : http://arduino.cc/en/Main/Software

Le code source
Le dossier MIDI doit être placé dans libraries. Exemple : C:\arduino-1.0.1\libraries\MIDI
Le fichier LL412.ino peut être placé dans un dossier LL412 de vos documents. C'est lui qu'il faudra ouvrir avec l'environnement de développement Arduino.

La façade est en plexi (PMMA) avec un feuille de SCOTCHMARK pour la sérigraphie...C'est facile à percer et la transparence parfaite évite les découpes pour l'afficheur, car question travail soigneux... ;)

J'ai trouvé l'afficheur pour pas cher sur la baie, celui-ci n'est pas rétro-éclairé . Aussi, tout afficheur type HD44780 2 lignes de 32 ou 40 caractères fera l'affaire. Cela s'adapte en 2 secondes dans le code source.
Une version en 5U avec un 4x20 devrait pouvoir être envisagé en organisant la façade autrement, le code source s'adaptera facilement.

Pour l'alimentation, un bloc secteur pour pédale de guitare (+9 v) fait l'affaire mais il faut inverser la polarité, sur l'Arduino c'est un connecteur 2.1mm avec + au centre.

Quelques photos du b..désordre intérieur et de la façade





et la version 5U de MikZed53



Quelques remarques

L'accord se règle par logiciel. La variable REF_1V donne la correspondance.  Chez moi , c'est 896 pour 1v/octave. Pour régler l'accord, vous pressez A1 et tournez A1 jusqu'à "1 VOLT" et là avec les poussoirs A2 et A3 vous changez la référence pour que la même note soit juste sur au moins 4 octaves. L'utilisation d'un simple accordeur électronique est très pratique pour cela.

Pour l'affichage 2x32, j'ai défini six zones décrites dans le prog, ligne 400:

byte ZL[]= {9, 9, 9, 9, 9, 9};
byte ZPOS[]= {1, 10, 19, 1, 10, 19};
byte ZLIN[]= {0, 0, 0, 1, 1, 1};


ZL est la largeur des zones
ZPOS la colonne de départ
ZLIN la ligne

La zone 1 a une longueur de 9, commence colonne 1 sur la ligne 0
...
La zone 6 a une longueur de 9, commence colonne 19 sur la ligne 1
 
Pour 16 caractères x 2 lignes on peut faire trois zones
xxxxxx xxxx xxxx
xxxxxx xxxx xxxx

ce qui donne 
byte ZL[]= {6, 4, 4, 6, 4, 4};
byte ZPOS[]= {0, 7, 12, 0, 7, 12};
byte ZLIN[]= {0, 0, 0, 1, 1, 1};


Ne pas oublier dans setup()
ligne 1251 :     lcd.begin(32, 2);
devient lcd.begin(16, 2);

Il faudra aussi modifier quelques libellés dans le code qui sont trop longs ;)

Ci-dessous des programmes simplifiées pour tester chaque organe.

Pour le montage, il est plus simple de tester chaque élément avant d'envoyer tout le code. C'est le rôle de ces petits bouts de codes.

L'afficheur

L'afficheur doit afficher Bonjour de LL412

#include <LiquidCrystal.h> 

LiquidCrystal lcd(7, 6, 5, 4, 3, 2);

#define NB_COLONNE 32
#define NB_LIGNE 2

int cpt=0;

void setup()
{
    lcd.begin(NB_COLONNE, NB_LIGNE);
    lcd.clear();
}

void loop()
{

  lcd.setCursor(0,0);
  lcd.print("Bonjour de LL412");
  lcd.setCursor(0,1);
  lcd.print(cpt);
  cpt++;
  delay(1000);



Les gates

Les deux gates doivent battre la seconde...

#include <LiquidCrystal.h>

LiquidCrystal lcd(7, 6, 5, 4, 3, 2);

#define NB_COLONNE 16
#define NB_LIGNE 2

#define GATE_0 8
#define GATE_1 9


int cpt=0;

void setup()
{
    pinMode(GATE_0,OUTPUT);
    pinMode(GATE_1,OUTPUT);

    digitalWrite(GATE_0,LOW);   
    digitalWrite(GATE_1,LOW);   

    lcd.begin(NB_COLONNE, NB_LIGNE);
    lcd.clear();
}

void loop()
{
   lcd.clear();
   lcd.setCursor(0,0);
   lcd.print("Gates On");
   digitalWrite(GATE_0,HIGH);   
   digitalWrite(GATE_1,HIGH);   
   delay(1000);
   lcd.clear();
   lcd.setCursor(0,0);
   lcd.print("Gates Off");
   digitalWrite(GATE_0,LOW);   
   digitalWrite(GATE_1,LOW);   
   delay(1000);
}
   



Le midi In

Une note jouée au clavier doit être affichée (appui et relâchement).



#include <LiquidCrystal.h>
#include <MIDI.h>

LiquidCrystal lcd(7, 6, 5, 4, 3, 2);

#define NB_COLONNE 16
#define NB_LIGNE 2

void HandleNoteOn(byte channel, byte pitch, byte velocity)
{
   lcd.clear();
   lcd.setCursor(0,0);
   lcd.print("Note On");
   lcd.setCursor(0,1);
   lcd.print(pitch);
}


void HandleNoteOff(byte channel, byte pitch, byte velocity)
{
   lcd.clear();
   lcd.setCursor(0,0);
   lcd.print("Note Off");
   lcd.setCursor(0,1);
   lcd.print(pitch);
}


void setup()
{
    lcd.begin(NB_COLONNE, NB_LIGNE);
    lcd.clear();

    MIDI.begin(0);  
    MIDI.setHandleNoteOn(HandleNoteOn);
    MIDI.setHandleNoteOff(HandleNoteOff );
}

void loop()
{
    MIDI.read();
}


Un convertisseur Midi CVsimplifié.

Chaque note jouée au clavier sera convertie en tension et gate sur CV 0 et GATE 0

#include <LiquidCrystal.h>
#include <MIDI.h>

LiquidCrystal lcd(7, 6, 5, 4, 3, 2);

#define DATAOUT 11//MOSI
#define DATAIN  12//MISO Pa sutilisé pour le moment
#define SPICLOCK  13//sck
#define DAC_0 10//ss
#define DAC_1 9//ss un seul DAC pour le moment

#define GATE_0 8
#define GATE_1 9

#define NB_COLONNE 16
#define NB_LIGNE 2

int REF_1V = 895; // coorespondance DAC 1v/Oct


void p_CV(byte port, int pitch)
{
    dac_Out(port, (long)REF_1V * pitch / 12  );
}


void HandleNoteOn(byte channel, byte pitch, byte velocity)
{
   lcd.clear();
   lcd.setCursor(0,0);
   lcd.print("Note On");
   lcd.setCursor(0,1);
   lcd.print(pitch);

   p_CV(0, pitch);
   digitalWrite(GATE_0, HIGH);
              

}

void HandleNoteOff(byte channel, byte pitch, byte velocity)
{
   lcd.clear();
   lcd.setCursor(0,0);
   lcd.print("Note Off");
   lcd.setCursor(0,1);
   lcd.print(pitch);
   p_CV(0, pitch);
   digitalWrite(GATE_0, LOW);
}


// ------------------
// Ecriture tension sur DAC
// ------------------

void dac_Out(int port, uint16_t sample)
{

  uint8_t dacSPI0 = 0;
  uint8_t dacSPI1 = 0;
  byte selector;

  switch (port)
  {
  case 0:
      selector = DAC_0;
      sample = sample | 0b0111000000000000;
      break;
  case 1:
      selector = DAC_0;
      sample = sample | 0b1111000000000000;
      break;
  } 
  dacSPI0 = (sample >> 8) & 0x00FF;
  dacSPI1 = sample & 0x00FF;

  digitalWrite(selector,LOW);
  SPDR = dacSPI0;                    // Start the transmission
  while (!(SPSR & (1<<SPIF)))     // Wait the end of the transmission
  {
  };
 
  SPDR = dacSPI1;
  while (!(SPSR & (1<<SPIF)))     // Wait the end of the transmission
  {
  }; 
  digitalWrite(selector,HIGH);

}

// ------------------
// Setup Arduino
// ------------------


void setup()
{
    byte clr;

    lcd.begin(32, 2);
    lcd.clear();

  // Initialisation DAC(s) et SPI
 
    pinMode(GATE_0,OUTPUT);
    pinMode(GATE_1,OUTPUT);

    pinMode(DATAOUT, OUTPUT);
    pinMode(DATAIN, INPUT);
    pinMode(SPICLOCK,OUTPUT);
    pinMode(DAC_0,OUTPUT);
    digitalWrite(DAC_0,LOW);   
   
    SPCR = (1<<SPE)|(1<<MSTR);
    clr=SPSR;
    clr=SPDR;
    delay(10);

    // Initialisation Midi   
    MIDI.begin(0);   
    MIDI.setHandleNoteOn(HandleNoteOn); 
    MIDI.setHandleNoteOff(HandleNoteOff );

    pinMode(GATE_0,OUTPUT);
    pinMode(GATE_1,OUTPUT);

    digitalWrite(GATE_0,LOW);   
    digitalWrite(GATE_1,LOW);   
   

}

void loop()
{
    MIDI.read();
}


@+



26 commentaires:

  1. Ce module est une pure merveille , je le recommande à tous , un grand bravo et merci à toi Laurent de nous faire partager ta passion ;) Mik

    RépondreSupprimer
  2. Super content que tu ais pu mener à bien ce montage, ton expérience et ta patience serviront à d'autres, je l'espère. Le module de Mik est en 5U , intégré dans un Yusynth, avec un afficheur 2x16, ca marche !
    Merci ;)

    RépondreSupprimer
  3. Hi, This is beast module, I want it so bad :)

    It's hard to find DAC chip MCP4922 in my country,
    - Is MCP4822 can work on it (I have it laying around) ?
    - The feature is cool, but if I just need only Arpeggiator, Sequencer and Step record, How to change the code? I'm newbie in programmer.

    Sorry for my English

    Mercy
    -Toby

    RépondreSupprimer
  4. Hi Tobby,

    Yes, the MCP4822 Works Fine.
    For change the code, i can help you a little but if you don't use function, it's more easy :D :D

    Regards ;)

    Laurent

    RépondreSupprimer
    Réponses
    1. Thanks for your response.
      I like Roland SH101 and SC Pro One an arpeggiator feature for mono synth. I dont own them, my plan is to build mono synth with an arpeggiator.

      So, Can you help me how to change or deleted the code line?
      If you dont mind, this is my mail : saw6667061@gmail.com
      Or you can publish here. :)
      Merci,
      Toby

      Supprimer
    2. Hello Toby,
      Sorry for the tardive response ;)
      Yes, i can HELP you for cleaning the code.
      Regards

      Supprimer
  5. Bonjour,
    je dispose d'une modeste config midi autour de Cubase (clavier DX7, expandeur Yam TG55, BàR Boss DR550) et je cherchais depuis un moment un moyen simple d'y inclure mon vieux Moog Rogue que je viens de re-régler et nettoyer après plusieurs années de séjour au sous-sol (ah les joies de la mousse de polyether qui fond sur les potentiomètres au bout de quelques années)
    Votre petit module me paraît sympathique et me permettra de retrouver les "joies" de la programmation (je suis développeur retraité)et de découvrir l'arduino qui m'intéresse à d'autres titres que pour la musique.

    Je ne manquerai pas de vous faire part de l'avancement de la chose lorsque je me lancerai.

    En attendant, bravo pour vos réalisations !

    RépondreSupprimer
    Réponses
    1. Bonjour Jean Benoit
      Pardon pour la réponse tardive, je me suis éloigné du micro quelques temps ;) J'aimerai avoir des sous sols qui recèlent de si jolies vieilleries :D
      A votre disposition pour toute info. L'arduino et les pics sont des petites machines vraiment motivantes.
      Bien cordialement,

      Supprimer
    2. Bonjour,

      première étape : un kit arduino est en commande !
      Après réception, je testerai un peu les fonctions de base pour me familiariser avec les interactions vis-à-vis de l'extérieur.
      En effet, quand je bossais, ma "sortie" classique se faisait via une imprimante ou un traceur. J'ai donc tout à apprendre des E/S via un transistor, un dac ou un optocoupleur. :-)

      Supprimer
    3. Bonjour Jean Benoît,
      J'ai connu aussi les interfaces parallèles, les UARTs ( j'ai développé des protocoles de comm, on dialoguait avec le contrôleur en directe :D)
      Pour qui a connu cela, l'Arduino, c'est de la récréation, de la programmation plaisir et un super terrain de jeu ;)
      Amicalement,

      Supprimer
    4. Bonjour,

      j'ai profité de 3 semaines d'un bon rhume pour enfin m'atteler à ce projet. J'ai avancé petit à petit en testant avec ces petits bouts de code diablement utiles.
      Au passage, et si ça peut aider de futurs constructeurs, j'ai longtemps cherché pourquoi je n'avais pas de signaux "NoteOff". C'est qu'en fait, mon DX7, né avant la norme midi, utilise un signal NoteOn" avec une velocité nulle.
      Autre souci rencontré, je suis obligé de déconnecter Rx/Tx quand j'upload un programme. Ce problème ne semble pas se produire avec toutes les versions de cartes d'après mes recherches sur internet.
      J'en suis maintenant à la compilation du programme définitif. Et là, je crois que je dois repartir sur des bases plus saines : ma carte arduino, achetée à bas prix à HongKong ne semble pas supporter la gestion de la bibliothèque avr/pgmspace.h (la ligne correspondante est grisée dans la liste des bibliothèques)

      Donc, suite au prochain achat !
      Amicalement,
      Jean

      Supprimer
    5. Re,

      je me réponds à moi-même, ayant terminé ce montage sympa. Il n'y avait pas de souci de compatibilité restreinte avec mon clone d'origine incertaine (DX.com) mais vu ma lenteur à me décider, depuis la naissance de LL412, un certain nombre de mises à jour avaient eu lieu dans l'IDE et les bibliothèques, en particulier, avr/pgmspace, qui a été mise plus en conformité avec les évolutions du C (tout ceci me dépasse un peu, mais j'ai réussi à ne pas me noyer) Il a donc fallu corriger un petit nombre d'instructions, et finalement presque tout est rentré dans l'ordre. Presque, en effet, car il restait bien sûr un oubli de câblage du +5V vers le MCP4922, et une inversion CV1 / CV0 par rapport aux GATE.

      J'ai donc réalisé une mise en boîte au format rack 1U pour être en accord avec les quelques bricoles déjà installées. Et tout roule !

      Merci, Laurent
      Amicalement,
      Jean

      Supprimer
    6. Bravo ! et désolé pour le silence (oupppss) , j'ai le nez dans le guidon et zappe des réponses. Si tu veux mettre en ligne ton code source à jour, n'hésite pas, un mail et je le publie ici.

      Supprimer
    7. Bonjour,
      Je me lance aussi dans l'aventure. Mon clavier maitre ne transmet pas non plus de vrai message NoteOff,mais NoteOn avec vélocité nulle. Du coup, la fonction handlenoteoff n'est jamais appelée et la gate ne retombe jamais.
      Une idée ?

      Merci d'avance pour vos réponses!
      JB

      Supprimer
    8. Bonjour,

      Il suffit d'ajouter après le

      void HandleNoteOn(byte channel, byte pitch, byte velocity)
      {


      if (velocity==0 ) {
      HandleNoteOff(channel, pitch, velocity);
      return;
      }

      ....


      Bon courage ;)

      Supprimer
    9. Merci pour cette réponse ultra rapide! Et en plus ça fonctionne!
      Comment se fait-il que certains claviers MIDI ne transmettent pas de message NoteOff ? Aucun des 2 que j'ai testé n'en transmet, et à en croire la toile, c'est assez courant...

      JB

      Supprimer
  6. Bonjour, super projet, pour l'utilisation d'un mcp4822, quelles seraient les modifications à apporter au code? Je ne sais pas si je vois juste mais le 4922 peut aller jusqu'à sa tension d'alimentation (5V) mais le 4822 semble aller jusqu'à la moitié (selon la fiche technique) il serait toujours possible d'amplifier la tension pour obtenir une échelle de 0 à 5v avec un ampli-op (on pourrait même aller de 0 à 10 pour plus d'octaves)

    J'aimerais aussi savoir à quelle note équivaut la valeur 0V dans ton programme merci

    RépondreSupprimer
    Réponses
    1. Bonjour Julien, ouppps, je viens juste de découvrir ta question. Pour le MCP4822, je dois vérifier mais c'est simple. Le 4822 et le 4922 ont le même range. les deux permettent par programmation d'activer le x2.
      Dans LL113, j'utilise des MCP4822 amplifiés pour atteindre 0-10V ;)

      Supprimer
  7. Bonjour,
    J'admire la simplicité et l’originalité de ce montage. J'ai, cependant, une petite question qui concerne tous les Midi to CV, et celui-ci en particulier.

    Le pitch de la note, convertie en CC se fait par simple division dans la fonction
    dac_Out(port, (long)REF_1V * pitch / 12 );
    ce qui est logique pour l'accordage chromatique. En midi, on est lié aux tuning du synthé ou sampleur. J'ai passé pas mal de temps a jouer avec des tableaux de microtunuung, ce qui est très galère en midi propre. Certains AUs comme Albino acceptent des tableaux Scala ce qui facilite la tache.

    Ma question, que le me permettrai a poser aux anciens utilisateurs et concepteurs de synthés analogiques est: y a-t-il des expériences et des convertisseurs midi/cv qui supportent cela, et particulièrement au créateur de cette merveille : dans quelle mesure cela peut être utile à mettre en place.

    Cordialement,
    Vic

    RépondreSupprimer
    Réponses
    1. Bonjour Vic,
      Merci pour ces mots ;)
      Dans mon projet de polyphonique, chaque VCO et VCF est piloté par la somme de deux tensions : une théorique équivalente à la formule de ll412 et une fine qui a été calculée par la procédure d'Autotune. Tout est faisable, comme remplacer la fonction par une table personnalisée. Mais la difficulté est d'imaginer une procédure ergonomique pour mettre à jour cette table.
      Musicalement,
      Laurent

      Supprimer
  8. Bonjour,
    J'ai réalisé le projet, avec quelques mods mineures: Ajout des diodes de protection et les DEL d'affichage sur chaque sortie gate, ajout d'un tampon AOP a chaque CV, des terminaux pour la prog facile du AVR. Le morceau de code est terriblement complexe et je m'aventure a petit pas. Cela dit, ce projet est une pure merveille ! J'apprécie particulièrement le mode Arp Transpose et le Sequenceur. Les LFOs ont une forme d'onde bien curieuse, ça fait un effet sur les FM et PWM en très basse fréquence :D

    J'ai deux zones d'ombre tout de même: Comment la modulation est gérée et en quel mode précisément. Pour le Pitch et l'EXP c'est assez clair. Et en deuxième place: Ou est le Do de référence: C1 ou C5? Car une fois les 5 octaves atteintes ça recommence par le plus bas.

    Voila, c'est pas grand chose. Je vais poster la photo du pojet une fois la sérigraphie réalisée, pour le moment c'est de l'alu brut.

    Cordialement,
    Vic

    RépondreSupprimer
    Réponses
    1. Merci pour ces mots et très bonnes idées ces modifs.
      Je ne comprends pas trop la question sur la modulation ? d'un point de vue programmation ? ou du point de vue ergonomie ?

      Il n'y a pas de Do de référence, juste la possibilité de définir dans les paramètres 0v = note 24 ou 32 ou...

      Oui, je parle de mémoire, après 4 octaves et des brouettes, on dépasse la résolution du DAC et il retourne à zéro (modulo 4096 en gros...) Un peu de code permettrait de corriger ce point. Pour le moment, je n'ai plus de ll412, donc je suis très théorique :D :D

      Bien cordialement,

      Laurent

      Supprimer
  9. Bonjour,
    Pour la modulation je l'avais imaginé de la façon suivante: En mode Normal, en CV1 on reçoit la note 1/V et en CV2 la modulation de 0 a 5V, en continu. Dans le menu, bouton 3, les choix basculent être différentes types d'expressions et LFOs. Pas de Modulation. Ou c'est active dans un autre mode? En bref, de quel façon et dans quel mode la modulation est prise en compte?

    Cordialement,
    Vic

    PS: Je suis en train de moder le code pour étudier les possibilites ...

    RépondreSupprimer
  10. hello laurent ca fait longtemps . aloRS à quand une petite mise à jour stp :)

    RépondreSupprimer
  11. Hello Mike
    Il n'y aura pas de mise à jour de ce projet ... venant de moi ;)
    Bien à toi

    RépondreSupprimer