Перейти к содержимому →

Arduino для музыканта часть 1. Делаем DIY MIDI контроллер/конвертер

Решил выйти наконец из затишья и написать несколько статей о том, чем сейчас занимаюсь в музыкальном плане, думаю, мой опыт будет интересен.

Где-то с 2007-го года я активный читатель Habr’a, последние его трансформации я уже особо не отслеживаю, но до 2011-го года все статьи получал по RSS и просматривал хотя бы заголовки.  Поэтому я хорошо помню момент, когда Arduino и Raspberry пошли в массы как недорогие микроконтроллеры. С тех пор у меня засела в голове мысль попробовать с ними свои силы, но так как и на музыку особо времени не остается, приходилось постоянно откладывать начало экспериментов.

Пару лет назад я окончательно пересел на Fractal Axe FX о чем я чуть позже напишу поподробнее.

GAS на этом не унимался, поэтому в довесок покупались различные педали, в какой-то момент ситуация вышла из под контроля, и педалборд выглядел вот так:

IMG_8512

Понятно, что в таком формате он ни разу не покинул дом, и даже дома его надо было где-то хранить, постоянно коммутировать и тд.

Принял решение перейти на рэк и управление только с миди контроллера.

К тому моменту BJ Devices выпустили новую модель с педалью экспрессии и начался процесс проектирования и оформления для себя ТЗ на покупку или разработку река.

В AXE FX отлично эмулируются усилители, дилеи и тд, но там нет пары моих любимых перегрузов(Fulltone OCD и Xotic Soul Driven), я решил убрать их в рэк и контролировать их включение в цепь по миди. Для этого можно было купить миди свитчи от GLAB или Voodoo LAB, но я решил, что тут поможет Arduino.

Итак, задача начала оформляться, нужно было устройство, которое при получении MIDI сообщений будет управлять включением выключением по реле педалей в цепь.

Начались первые эксперименты.

IMG_1755

Я купил контроллер Arduino Uno и реле для него. За один вечер удалось сделать свитч, который управляется сигналами из Arduino.

Вместе с контроллером BJ Devices у меня был куплен их свитч LoopX2, цель уже сейчас не припомню, но кто вообще будет объяснять GAS покупки. При проектировании расположения устройств в рековой полке, решил, что Arduino реле будет управлять свитчем от BJ, так как расположение будет гораздо удобнее.

Вторым этапом разработки были добавлены MIDI IN/OUT в схему и немного расширен объем работ.

В сети есть много мануалов по тому как собрать MIDI контроллер на Arduino, как минимум начните изучать эту тему с Notes And Volts.

Повозившись с россыпью комплектухи, нашелся наш магазин, который продавал уже собранные модули MIDI IN/OUT.

Купил, включил, скачал библиотеку MIDI.h и быстренько набросал программу управления свитчем LoopX2 по MIDI.  Промежуточные программы я не буду приводить по тексту, в итоговом примере вы найдете все эти же программы как блоки с комментариями, поэтому двинемся дальше.

Все эти работы шли вечерами, когда находилось время. В общей сложности на разработку ушло 4 месяца, но это с учетом того, что на старте знаний по Arduino и схемотехнике у меня было практически ноль, сейчас с горем пополам могу собрать схему Big Muff или что-то похожее.

Проект начинал обрастать новыми функциями на этот раз я решил убрать в рэк Whammy, сама педаль на мой слух звучит намного музыкальней, чем ее эмуляция в Axe FX. Почитал мануал на педаль, управление по MIDI там достаточно простое, однако, для переключения режимов используются команды Program Change, а это значит, что посылая это сообщение с контроллера в одну MIDI цепь устройств, вместе с Whammy переключать пресеты начнет и Axe FX.

Пришлось добавить еще один MIDI OUT, в итоге в Arduino заходил MIDI сигнал от контроллера и дальше шло разветвление — MIDI OUT для Axe FX , в который не попадают сообщения для Whammy и MIDI THRU, в который идет весь поток миди данных.

IMG_1947

Есть один нюанс, Arduino UNO имеет по одному serial порту, для того чтобы иметь один миди вход и два выхода, пришлось купить Arduino Mega, после 10 дней ожидания посылки с Ali удалось собрать макет.

Но вернемся к теме перегрузов и их включения в цепь, в Axe FX отлично эмулируется различные варианты квакушек, но раз уж перегрузы будут стоять ПЕРЕД процессором, то значит квакушка в такой цепи будет стоять ПОСЛЕ перегруза. В таком варианте подключения квакушка звучит слишком стерильно, весь смачный рок-н-ролльный саунд Wah получается только если педаль стоит перед перегрузом.

После пары дней размышлений, удалось достать плату Cry Baby GCB-95.

Час гугления и нашлась вот такая статья (https://www.instructables.com/id/Wahduino-WahWah-by-shakingraise-the-guitar/) про Arduino квакушку, которая управляется акселерометром.

Пришлось покупать цифровой потенциометр, который заменил стандартный пот 100k в квакушке.

Ну и еще пара ссылок вам на интересные проекты DIY рековых квакушек

В этих статьях был только один минус — управление было не по MIDI.

Это была третья часть проекта — добавить квакушку, которая будет управляться по MIDI при помощи Arduino. После пары недель доехала россыпь различных цифровых потенциометров, пара часов экспериментов и я услышал первые «кваки» в наушниках, которые управлялись с мидиконтроллера.

Итак, в процессе экспериментов появился вот такой «монстр»:

IMG_2256

В одну коробку я воткнул Arduino Mega (https://ru.aliexpress.com/item/1Pcs-Keyestudio-MEGA-2560-R3-1Pcs-USB-cable-compatible-with-Arduino-MEGA-2560-R3-AVR/32247818078.html?spm=a2g0s.9042311.0.0.4Cgo2z), shield для mega (https://ru.aliexpress.com/item/Free-shipping-2015-New-Keyestudio-MEGA-Sensor-Shield-V1-for-Arduino-MEGA/2042269441.html?spm=a2g0s.9042311.0.0.4Cgo2z) для удобства подключения внешних девайсов, электромеханическое реле для управления свитчем, midi in (http://amperka.ru/product/troyka-midi-in),  два midi out, цифровой потенциометр и плата Cry Baby.

Когда я собрал все в одну коробку, от цифровой части схем в квакушку шел очень сильный фон. Пришлось изолировать потенциометр через LDR (http://www.instructables.com/id/How-to-Use-a-Light-Dependent-Resistor-LDR/).

Чтобы вам проще было повторить вот несколько схем. На плате Cry Baby есть 8pin слот для подключения батарейки, кнопки и потенциометра. На схеме ниже каждый выход подписан.

gcb_shield

Подробнее про замену потенциометра квакушки на LDR(Light Depended Resistor) можно почитать вот в этой статье http://www.geofex.com/article_folders/wahpedl/wahped.htm

Немного поковырявшись со схемой у меня получился вот такой вариант:

LDR

Для удобства я все покрасил на картинке в соответствующие цвета и подписал. Сам по себе LDR это светодиод и фоторезистор. Яркостью светодиода в моей схеме управляет цифровой потенциометр, а фоторезистор одной ногой подключен к выходу «3-ground PA0», ко второму выходу через 100k резистор подключен выход «6 — fx return PB0» и выходу «5 — wiper PW0».

Если у вас в квакушке Dunlop начал хрустеть потенциометр, можно так же не меняя пот, добавить LDR и получить квак, в котором никогда больше не надо будет менять потенциометр.

После перехода на LDR фона стало меньше, но наводок было все равно очень много, я долго игрался с разными вариантами земли, изоляции и тд. Единственный способ как удалось избавиться от фона это убрать плату квакушки в отдельный корпус. При таком раскладе пазл в площадь река у меня уже не складывался, немного поразмыслив я решил купить себе рековую Cry Baby и опять же управлять ею из Arduino. Сам рек ко мне пока только едет, поэтому проект еще не завершен.

Пока схема подключения выглядит вот так:

Схема подключения

Аудио сигнал подается на вход Whammy, откуда идет на MidiWah и далее в свитч, который управляется Arduino. Миди сигнал идет из контроллера в Arduino оттуда разделяется на управление Whammy и Axe FX.

Ниже листинг кода для Arduino. Напомню, что при помощи этого кода вы сможете получать и отправлять MIDI команды, управлять реле, управлять Digitech Whammy 5 как переключением режимов так и педалью экспрессии, управлять цифровым потенциометром, который подключен к Cry Baby.

// Версия 2.3
// Получение данных на вход MIDI IN, передача во вход MIDI THRU Arduino Mega и
//преобразование команд CC_TG в соответствующие команды PC для управления Digitech
//Whammy по 4-му MIDI каналу
//управление включением реле для переключения петель BJ LoopX2
//Управление значением DigiPot MCP42100 по MIDI(педалью экспрессии)
//Управление включением/выключением Wah эффекта при помощи реле
//LED BAR показывает уровень нажатия на педаль MIDI экспрессии
//SETUP: pin RX1/TX1, RX2/TX2. MIDI IN и MIDI THRU подключены в Serial(RX0/TX0), MIDI OUT в Serial1(RX1/TX1)
//SETUP: pin 5, 6 для управления входами реле №1
//SETUP: pin 7, 8 подключены к LED BAR, 8 - clock pin, 7 - data pin
//SETUP:  pin 10, 11, 13 - пины для управления DigiPot MCP42100
//SETUP:  pin 42, 43, 44, 45 - пины для управления входами реле№2 
 
#include <MIDI.h>  // подключение библиотеки MIDI
 
//Подключение библиотеки по управлению LED Bar
#include <Adeept_Bar.h>
 
//Подключение библиотеки для управления цифровым потенциометром MCP42100
#include <SPI.h>
// 10-ый выход установлен как slave select, управляем po1(commandbyte =18)
const int slaveSelectPin = 53;
const int CommandByte = 18;
const int CommandByte2 = 17;
 
 
int wah_value = 0;
int led_value = 0;
 
int k = 0; // счетчик старта
 
//определение номеров выхода Arduino для управление переключением реле №1
const int relPin1 = 5; // номер выхода реле #1
const int relPin2 = 6; // номер выхода реле #2
 
//определение номеров выхода Arduino для управление переключением реле №2
const int relPin21 = 42; // номер выхода реле №2#1
const int relPin22 = 43; // номер выхода реле №2#2
const int relPin23 = 44; // номер выхода реле №2#3
const int relPin24 = 45; // номер выхода реле №2#4
 
//Определение номеров выходя Arduino для управления LED BAR
Adeept_Bar bar(8, 7);  // Clock pin, Data pin
 
//Create an instance of the library with name, serial port and settings
MIDI_CREATE_INSTANCE(HardwareSerial, Serial1, midi_IO);
MIDI_CREATE_INSTANCE(HardwareSerial, Serial2, midi_THRU);
 
void setup() {
    Serial.begin(9600);
    Serial1.begin(9600);
    Serial2.begin(9600);
    
    midi_IO.begin(MIDI_CHANNEL_OMNI); // Initialize the Midi Library.
    midi_THRU.begin(MIDI_CHANNEL_OMNI); // Initialize the Midi Library.
    
    //midi_IO.setHandleProgramChange(MyHandleProgramChange);
    midi_IO.setHandleControlChange(MyHandleControlChange);
    
    pinMode(relPin1, OUTPUT);
    pinMode(relPin2, OUTPUT);
 
    pinMode(relPin21, OUTPUT);
    pinMode(relPin22, OUTPUT);
    pinMode(relPin23, OUTPUT);
    pinMode(relPin24, OUTPUT);
 
    digitalWrite(relPin21, LOW); 
    digitalWrite(relPin22, LOW);
    digitalWrite(relPin23, HIGH);
    digitalWrite(relPin24, HIGH);
 
    bar.begin();  //инициализация LED BAR
 
  // установка  slaveSelectPin как выходного:
  pinMode (slaveSelectPin, OUTPUT);
  // стартуем SPI:
  SPI.begin(); 
 
}
 
void loop() { // Main loop     
 
  
  //Пересыл всех сообщений со входа MIDI IN в выход MIDI THRU на Serial2
  midi_IO.read(); 
  midi_IO.turnThruOn();
}
 
void MyHandleControlChange(byte channel, byte number, byte value) {
 
//Работа с MIDI++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
 
//СС сообщение 60 - включение режима Октава вверх
//СС сообщение 61 - включение режима Октава вниз
//СС сообщение 62 - включение режима Октава вверх/Октава вниз
//СС сообщение 63 - включение реле #1
//СС сообщение 64 - включение реле #2
 
//Serial.print("CC = ");
//Serial.print(number);
//Serial.print("   value = ");
//Serial.print(value);
//Serial.println(" ");
 
 
 
 
switch (number) {
    //Включение режима Октава вверх на Whammy при получении CC_TG_60
    case 60:
       if (value == 127){
        midi_THRU.sendProgramChange(43,4);     //Whammy ON
        }; 
       if (value == 0){ 
         midi_THRU.sendProgramChange(64,4);     //Whammy OFF
        };
      break;
    //Включение режима Октава вверх/Октава вниз на Whammy при получении CC_TG_61
    case 61:
       if (value == 127){
        midi_THRU.sendProgramChange(62,4);        //Whammy ON
        };
       if (value == 0) {
         midi_THRU.sendProgramChange(83,4);     //Whammy OFF
        };
      break;
    //Включение режима Октава вверх/Октава вниз на Whammy при получении CC_TG_62
    case 62 :
      if (value == 127){
        midi_THRU.sendProgramChange(49,4);         //Whammy ON
        }; 
      if (value == 0){
        midi_THRU.sendProgramChange(70,4);     //Whammy OFF
      }
      break;
   
    //Включение реле №1#1 при получении CC_TG_63
    case 63 :
      if (value == 0){
          digitalWrite(relPin22, LOW); 
        };
      if (value == 127){
          digitalWrite(relPin22, HIGH); 
        } ;
      
      break;
 
    //Включение реле №1#2 при получении CC_TG_64
    case 64 :
      if (value == 0){
          digitalWrite(relPin21, LOW); 
        } ;
      if (value == 127){
          digitalWrite(relPin21, HIGH); 
        } ; 
      
      break;
 
    //Управление педалью экспрессии
    case 16 :
      //передача данных по управлению педалью экспрессии на Whammy
      midi_THRU.sendControlChange(11, value, 4);//передача данных по управлению педалью экспрессии на Whammy
      
      //конвертация MIDI данных экспрессии в данные для DigiPot
      wah_value = map(value, 0, 127, 0, 255);//конвертация MIDI данных экспрессии в данные для DigiPot
      
      break;
 
      // все остальное - пустота
      default:
      break;
    
}
 
//передача параметров MIDI в качестве управления в DigiPot
digitalPotWrite(CommandByte, wah_value);
 
//передача параметров MIDI в качестве управления в DigiPot
digitalPotWrite(CommandByte2, wah_value);
 
 
led_value = ceil(float(wah_value)/25);
led_control(led_value);
 
//Работа с MIDI-------------------------------------------------------------------------------------------------
 
}
 
//передача данных SPI на DigiPot
int digitalPotWrite(int CommandByte, int value) {
  // take the SS pin low to select the chip:
  digitalWrite(slaveSelectPin,LOW);
  //  send in the address and value via SPI:
  SPI.transfer(CommandByte); 
  SPI.transfer(value);
  // take the SS pin high to de-select the chip:
  digitalWrite(slaveSelectPin,HIGH); 
}
 
// управление LED BAR
void led_control(byte led_bar) {
switch (led_bar) {
  case 0:
   // Turn off all LEDs
 bar.setBits(0x0);
  break;
  
  case 1:
  // Turn on LED 1
bar.setBits(0b000000000000001);
  break;
  
  case 2:
   // Turn on LED 12
bar.setBits(0b000000000000011);
  break;
  
  case 3:
   // Turn on LED 123  
 bar.setBits(0b000000000000111);
  break;
  
  case 4:
   // Turn on LED 1234
 bar.setBits(0b000000000001111);
  break;
  
  case 5:
   // Turn on LED 12345
 bar.setBits(0b000000000011111);
  break;
  
  case 6:
  // Turn on LED 123456
bar.setBits(0b000000000111111);
  break;
  
  case 7:
  // Turn on LED 1234567 
bar.setBits(0b000000001111111);
  break;
  
  case 8:
  // Turn on LED 12345678
bar.setBits(0b000000011111111);
  break;
  
  case 9:
  // Turn on LED 123456789
bar.setBits(0b000000111111111);
  break;
  
  case 10:
   // Turn on all LEDs
 bar.setBits(0x3ff);
  break;
}
}

В следующей статье рассмотрим подробно только часть проекта — MIDI сплиттер на Arduino

Пишите в комментарии или группу вконтакте свои музыкальные проекты на Arduino и задавайте вопросы.

Опубликовано в Оборудование