Kontroler MIDI do efektu gitarowego Line 6 M5

Dziś coś dla gitarzystów, mianowicie przedstawię budowę kontrolera MIDI do efektu Line 6 M5. Kostka ta posiada bardzo wiele możliwości kreowania dźwięku, jednakże sposób poruszania się pomiędzy wybranymi presetami nie należy do najbardziej ergonomicznych. Poniżej opisana konstrukcja pozwoli w zdecydowanie szybszy i jaśniejszy sposób wybierać interesujące nas programy w modelerze M5.

arduino kontroler MIDI Line 6 M5

Kontroler oparłem na popularnej platformie Arduino, także nawet laik powinien odtworzyć etapy tworzenia tego urządzenia. 
Sterowanie odbywa się przy pomocy pięciu przycisków presetów oraz jednego do zmiany banków, tak więc mamy 5 banków po 5 presetów, razem 25, a właściwie to 24, bo na tyle posiada Line 6 (bank nr 5 posiada 4 presety). Aktualny program jest wskazywany przez diodę LED, natomiast za informowanie o banku odpowiada dioda RGB (kolory podstawowe + ich kombinacje).
Całość zamknięta jest w aluminiowej obudowie i może być zasilana napięciem z zakresu 7V - 12V, gitarzyści zastosują pewnie zasilacze 9V.

Poniżej linkuję film demonstracyjny, który nagrałem dobre kilka lat temu. Przedstawia on pełną funkcjonalność kontrolera.

 

Będziemy potrzebowali:

- Arduino Nano,
- 6 sztuk footswitchy monostabilnych (momentary),
- 5 sztuk diod LED,
- dioda RGB ze wspólną katodą,
- 8 sztuk rezystorów 4,7k omów,
- 2 sztuki rezystorów 220 omów,
- gniazdo żeńskie DIN5 (MIDI),
- gniazdko zasilania (dla gitarzystów 2,1/5,5mm z minusem w środku)
- obudowa aluminiowa (przykładowo obudowa Enclosure BBDD),
- 6 sztuk oprawek na diody LED.

Montaż elektroniki

Na początku radzę sobie rozplanować elementy w obudowie, nawiercić otwory pod footswitche, oprawki LED oraz gniazda zasilania i MIDI. Następnie instalujemy elementy mechaniczne i świecące. Masę proponuję rozprowadzić w miarę sztywnym drutem miedzianym, ułatwi to potem dołączenie kolejnych elementów do układu.
Rezystory 4,7k omów przeznaczone są dla anod diod LED, natomiast te o wartości 220 omów posłużą do podłączenia gniazda MIDI.
Podczas montażu zadbajcie o ułożenie Arduino, powinno być możliwe późniejsze podłączenie kabla USB do programowania mikrokontrolera.

Schemat elektroniczny kontrolera
Mały komentarz: pin 5 gniazda MIDI łączymy przez rezystor do wyjścia TX Arduino, pin 2 do masy, natomiast pin 4 poprzez rezystor do 5V.
Niżej znajdziecie rozmieszczenie pinów w gnieździe.
Pinout gniazda MIDI

Sądzę, że oprócz tego reszta powinna być czytelna i zrozumiała, a więc teraz możemy przejść do wgrania programu na naszą płytkę Arduino.

Programowanie Arduino

Przed wgraniem kodu programu musimy się zaopatrzyć w bibliotekę Bounce2, do znalezienia tutaj: https://github.com/thomasfredericks/Bounce2. Sposób w jaki dodajemy biblioteki do Arduino IDE opisałem w poprzednim moim poradniku, tutaj.

Po dodaniu biblioteki możemy skompilować poniższy kod. W przypadku gdybyśmy nieco inaczej podpięli przyciski i diody do pinów, w liniach 3 - 19 możemy zdefiniować je wg własnego upodobania. Również w liniach 181 - 210 możemy przypisać własne kolory diody RGB dla konkretnego banku.

  1. #include <Bounce2.h>
  2. #define PROGRAM1 12
  3. #define PROGRAM2 9
  4. #define PROGRAM3 7
  5. #define PROGRAM4 15
  6. #define PROGRAM5 17
  7. #define BANK 18
  8. #define LED1 11
  9. #define LED2 10
  10. #define LED3 8
  11. #define LED4 14
  12. #define LED5 16
  13. #define LED_R 2
  14. #define LED_G 3
  15. #define LED_B 4
  16. #define BOUNCEDELAY 25
  17. // Instantiate a Bounce object
  18. Bounce debouncer1 = Bounce();
  19. Bounce debouncer2 = Bounce();
  20. Bounce debouncer3 = Bounce();
  21. Bounce debouncer4 = Bounce();
  22. Bounce debouncer5 = Bounce();
  23. Bounce debouncer_bank = Bounce();
  24. int action = 0;
  25. int last_action = 0;
  26. int bank_number = 0;
  27. int last_bank_number = 0;
  28. void setup() {
  29.   //  Set MIDI baud rate:
  30.   Serial.begin(31250);
  31.   // Setup the button
  32.   pinMode(PROGRAM1,INPUT);
  33.   pinMode(PROGRAM2,INPUT);
  34.   pinMode(PROGRAM3,INPUT);
  35.   pinMode(PROGRAM4,INPUT);
  36.   pinMode(PROGRAM5,INPUT);
  37.   pinMode(BANK,INPUT);
  38.   // Activate internal pull-up
  39.   digitalWrite(PROGRAM1,HIGH);
  40.   digitalWrite(PROGRAM2,HIGH);
  41.   digitalWrite(PROGRAM3,HIGH);
  42.   digitalWrite(PROGRAM4,HIGH);
  43.   digitalWrite(PROGRAM5,HIGH);
  44.   digitalWrite(BANK,HIGH);
  45.   // After setting up the button, setup debouncer
  46.   debouncer1.attach(PROGRAM1);
  47.   debouncer1.interval(BOUNCEDELAY);
  48.   debouncer2.attach(PROGRAM2);
  49.   debouncer2.interval(BOUNCEDELAY);
  50.   debouncer3.attach(PROGRAM3);
  51.   debouncer3.interval(BOUNCEDELAY);
  52.   debouncer4.attach(PROGRAM4);
  53.   debouncer4.interval(BOUNCEDELAY);
  54.   debouncer5.attach(PROGRAM5);
  55.   debouncer5.interval(BOUNCEDELAY);
  56.   debouncer_bank.attach(BANK);
  57.   debouncer_bank.interval(BOUNCEDELAY);
  58.   //Setup the LED
  59.   pinMode(LED1,OUTPUT);
  60.   pinMode(LED2,OUTPUT);
  61.   pinMode(LED3,OUTPUT);
  62.   pinMode(LED4,OUTPUT);
  63.   pinMode(LED5,OUTPUT);
  64.   pinMode(LED_R,OUTPUT);
  65.   pinMode(LED_G,OUTPUT);
  66.   pinMode(LED_B,OUTPUT);
  67.   flashPin(LED1,200);
  68.   flashPin(LED2,200);
  69.   flashPin(LED3,200);
  70.   flashPin(LED4,200);
  71.   flashPin(LED5,200);
  72.   flashPin(LED_R,200);
  73.   flashPin(LED_G,200);
  74.   flashPin(LED_B,200);
  75.   analogWrite(LED_R, 255);
  76.   digitalWrite(LED1, HIGH );
  77.   midiProg( 0xC00);
  78. }
  79. void loop() {
  80.  // Update the debouncer
  81.   debouncer1.update();
  82.   debouncer2.update();
  83.   debouncer3.update();
  84.   debouncer4.update();
  85.   debouncer5.update();
  86.   debouncer_bank.update();
  87.  // Get the update value
  88.  int value1 = debouncer1.read();
  89.  int value2 = debouncer2.read();
  90.  int value3 = debouncer3.read();
  91.  int value4 = debouncer4.read();
  92.  int value5 = debouncer5.read();
  93.  int value_bank = debouncer_bank.read();
  94.  action = 0;
  95.   if ( value1 == LOW) {
  96.    action = 1;
  97.  }
  98.   if ( value2 == LOW) {
  99.    action = 2;
  100.  }
  101.   if ( value3 == LOW) {
  102.    action = 3;
  103.  }
  104.   if ( value4 == LOW) {
  105.    action = 4;
  106.  }
  107.   if ( value5 == LOW) {
  108.    action = 5;
  109.  }
  110.   if ( value_bank == LOW) {
  111.    action = 6;
  112.  }
  113. //select action
  114. if (action != last_action) {
  115. switch ( action) {
  116.   case 0:
  117.   break;
  118.   case 1:
  119.     midiProg( 0xC00+(5*bank_number));
  120.     indicator(LED1);
  121.   break;
  122.   case 2:
  123.     midiProg( 0xC01+(5*bank_number));
  124.     indicator(LED2);
  125.   break;
  126.   case 3:
  127.     midiProg( 0xC02+(5*bank_number));
  128.     indicator(LED3);
  129.   break;
  130.   case 4:
  131.     midiProg( 0xC03+(5*bank_number));
  132.     indicator(LED4);
  133.   break;
  134.   case 5:
  135.     if ( 4+5*bank_number < 24){
  136.     midiProg( 0xC04+(5*bank_number));
  137.     indicator(LED5);
  138.     }
  139.   break;
  140.      
  141.   case 6:
  142.     bank_number=bank_number+1;
  143.     if (bank_number == 5)
  144.     bank_number = 0;
  145.   break;
  146. }
  147. }
  148. if (bank_number != last_bank_number) {
  149.   switch (bank_number){
  150.   case 0:
  151.   analogWrite(LED_R, 255);
  152.   analogWrite(LED_G, 0);
  153.   analogWrite(LED_B, 0);
  154.   break;
  155.   case 1:
  156.   analogWrite(LED_R, 0);
  157.   analogWrite(LED_G, 255);
  158.   analogWrite(LED_B, 0);
  159.   break;
  160.   case 2:
  161.   analogWrite(LED_R, 0);
  162.   analogWrite(LED_G, 0);
  163.   analogWrite(LED_B, 255);
  164.   break;
  165.   case 3:
  166.   analogWrite(LED_R, 0);
  167.   analogWrite(LED_G, 255);
  168.   analogWrite(LED_B, 255);
  169.   break;
  170.   case 4:
  171.   analogWrite(LED_R, 255);
  172.   analogWrite(LED_G, 100);
  173.   analogWrite(LED_B, 100);
  174.   break;
  175.   }
  176. }
  177.   last_action = action;
  178.   last_bank_number = bank_number;
  179. }
  180. void midiProg(char status, int data ) {
  181.   Serial.write(status);
  182.   Serial.write(data);
  183. }
  184. void flashPin( int ledPin, int flashDelay ) {
  185.   digitalWrite( ledPin, HIGH );
  186.   delay( flashDelay );
  187.   digitalWrite( ledPin, LOW );
  188. }
  189. void indicator( char nr) {
  190.   digitalWrite( LED1, LOW );
  191.   digitalWrite( LED2, LOW );
  192.   digitalWrite( LED3, LOW );
  193.   digitalWrite( LED4, LOW );
  194.   digitalWrite( LED5, LOW );
  195.   digitalWrite( nr, HIGH );
  196. }

Po wgraniu kodu nasze urządzenie powinno być już w pełni funkcjonalne. Na starcie po kolei "przeskoczy" po diodach LED, od teraz możemy zacząć zabawę z gitarą.

Podsumowanie

Myślę, że wielu gitarzystów - majsterkowiczów zainteresuje się powyższym artykułem, gdyż sterowanie MIDI na scenie to niemal podstawa, a zbudowane urządzenie w znaczący sposób ułatwi osiągnięcie zamierzonego efektu dźwiękowego.
Dodatkowo ambitni mogą spróbować przystosować kontroler pod własne potrzeby i posiadany sprzęt. Możemy budować programy sekwencyjne lub działające na warunki logiczne. Mamy praktycznie pełną dowolność. A po zmianie komunikatów MIDI kontroler zadziała z każdym efektem czy procesorem dźwięku (zazwyczaj producenci podają listę komend w dokumentacji).

Popularne wpisy

Reverse engineering wzmacniacza FirstWatt F7 - schemat