Search
Write a publication
Pull to refresh

Оптический терменвокс на Arduino


Когда я впервые столкнулся с Arduino, терменвокс казался мне сложным устройством, состоящим из сенсора и исполнительного устройства. Но он оказался весьма доступным и интересным в создании. У него простое строение: лишь один фотодатчик и переделанные наушники. После нескольких экспериментов я понял, что необходима функция самокалибровки, если я хочу неизменные характеристики на различных уровнях освещённости. Также, я решил сделать автонастройку с помощью математики, а не таблицы поиска. Для меня, пентатонная настройка оказалась самой подходящей, хотя её можно легко заменить на хроматическую или другую настройку по желанию.

Вот список того, что я использовал:

*Arduino Uno (запущено на Mac OS X 10.7.4 Intel)
*Кабель USB
*Макетная плата
*Копеечные наушники-вкладыши
*Стандартный фотодатчик
*Резистор на 10 кОм
*Немного проволоки
*Паяльник и припой

Шаг первый. Переделываем наушники.



Для того, чтобы посылать сигналы в наушники, я обрезал провода и припаял их к паре проволочных перемычек. Но здесь есть несколько нюансов.
Для начала, когда вы перережете провода и снимете часть изоляции, вы увидите четыре провода, по два с каждой стороны. Каждая пара образует цепь с одним наушником, поэтому мы можем считать, что каждая пара состоит из плюсового провода (обычно окрашены в красный или голубой цвет) и заземляющего провода (обычно меднокрасный). Мы можем использовать или только один наушник (следовательно, только одну пару проводов), или объединить провода для использования обоих наушников, тем самым обеспечивая в два раза больше веселья. Для этого мы припаяем плюсовые провода из каждой пары к одной проволочной перемычке, а заземляющие провода – к другой. При необходимости смотрите фото выше.
Во-вторых, под заметной резиновой изоляцией часто можно встретить слой прозрачной резины, обволакивающий четыре провода по отдельности. Простейший способ избавиться от него – нагревать провод зажигалкой до тех пор, пока резина не сгорит. Обратите внимание: после того, как это будет сделано, будет очень трудно различить цвета. Поэтому рекомендую оставить небольшой кусок провода необожжённым для того, чтобы можно было определить тип провода. Также, я использовал мокрую ткань для того, чтобы стереть остатки сожжённой смолы для улучшения проводимости.
У меня было очень простое оборудование для пайки, поэтому я просто скрутил провода наушников вместе и вокруг проволочной перемычки, а затем капнул чуть-чуть припоя.

Шаг второй. Собираем цепь.



Здесь у нас две простые цепи:
1. Цепь наушников: Используем любой цифровой выходной контакт Arduino и заземлитель для создания цепи с проволочными перемычками наушников.

2. Цепь датчика: Это стандартный делитель напряжения, который позволяет меняющемуся сопротивлению фотодатчика регулировать напряжение, считываемое аналоговым входным контактом Arduino. Для начала, я сделал последовательную цепь, которая идет по порядку: Arduino 5V контакт питания -> фотодатчик -> резистор на 10кОм ->заземление. Я опробовал напряжение в узле между резистором и фотодатчиком, используя аналоговый вход A0.

Иногда у меня были проблемы с качеством соединений. Я думаю, что лучше использовать более качественные проволочные перемычки в следующий раз. Когда что-то шло не так, я просто шевелил некоторые провода и определял качество соединения. Более хорошее закрепление провода в макетной плате или повторный обжиг провода всегда срабатывали.

Шаг третий. Пишем код.


Код состоит в основном из двух команд:
* команда AnalogRead, которая получает значение напряжения из вывода A0. Это эффективно измеряет уровень освещенности на фотодатчике.
* Команда tone, которая посылает сигнал к выводу 9 и заставляет наушники выдавать тон определённой частоты.
Конечно, есть ещё много вещей, которые нужно сделать:
* Установить контакт 9 как вывод.
* Цикл калибровки: пользователь показывает фотодатчику диапазон уровней освещения, обучая программу градуировать частоты.
* Измерить градацию и параметр сдвига на основе данных, полученных при калибровке.
* Автонастройка: округление частоты до ближайшего нужного тона с помощью логарифмов.
Вот сам код:

// Optical Theramin

//pin definitions
#define PHONES 9   // headphones connected to digital pin 9
#define PHOTOCELL 0 //photocell analog in pin 0

//variable definitions
long val = 0;        //stores raw value from photocell
long maxread = 0;    //maximum value from calibration phase
long minread = 1000;  // minimum value from calibration phase
double f = 0;         // frequency of sound
double normf = 0;    // normalized frequency 
double logf = 0;      // logarithm of normalized frequency
int ilogf = 0;        // rounded logarithm
int i = 0;            // loop dummy variable
double factor = 0;    // scaling factor for calibration
double shift = 0;     // shift for calibration
long maxfreq = 1048;  // maximum desired frequency after calibration
long minfreq = 131;   // minimum desired frequency after calibration


//magic numbers that make the intervals sound pleasing
double gap = 1.148698355;  //ratio of consecutive notes (pentatonic)
                             // it's the 5th root of 2
//double gap = 1.059463094;  //ratio of consecutive notes (chromatic)
                              // its the 12th root of 2

                              
void setup()
{
  pinMode(PHONES, OUTPUT);    // sets the digital pin as output

// calibration loop to determine a rasonable range of light levels (minread to maxread)
// and map that to frequencies between minfreq and maxfreq
  for (i = 0; i< 500; i++) {  // calibration loop runs for 5 seconds
    val = analogRead(PHOTOCELL);   // read photocell 
    tone(PHONES, val);          // play raw tone to guide calibration
    if (val > maxread) {        // as the values climb, store the largest
      maxread = val;
    }
    if (val < minread) {        // as the values drop, store the smallest
      minread = val;
    }  
    delay(10);                  // reasonable delay
  } 
  
  //Now we use the calibration to calculate scale and shift parameters
  factor = (double)(maxfreq - minfreq) / (double)(maxread - minread); // scale parameter
  //it's like a slope
  
  shift = factor * minread - minfreq;  //shift parameter: it's like an offset
}

void loop()
{
  val = analogRead(PHOTOCELL);   // read photocell 
  f = factor * val - shift;     // this linearly maps the frequency to
                                // a value between minfreq and maxfreq
                                // according to the calibration result
  
  normf = f / (double) minfreq;  // Dividing an exponential function by the min value
  logf = log(normf) / log(gap); // allows us to take the log (base gap) and the result 
  ilogf = round(logf);           // is the number of notes above the lowest, once we round it.
  f = minfreq * pow(gap,ilogf);  // we better "unlog" it.
  
  
  tone(PHONES, f);              // this produces the tone signal
  
}

Шаг четвёртый. Запускаем.


Теперь просто открываете редактор Arduino, верифицируете код, подсоединяете USB и загружаете. Вот видеогайд:

Конечно, есть много возможностей для изменения и улучшения. Некоторые возможности включают в себя:
* Добавление регулятора громкости (реостат или другой фотодатчик)
* Использование лучшего динамика
* Сделать код более эффективным (меньше переменных типа double)
* Воспользовавшись функцией map вместо маппинга калибровки вручную
Не стесняйтесь предлагать свои идеи, и веселиться, раздражая людей своим терменвоксом :)

Это перевод статьи с сайта instructables.com.

P.S. Это мой первый перевод, поэтому прошу судить строго и сообщать об ошибках.
Tags:
Hubs:
You can’t comment this publication because its author is not yet a full member of the community. You will be able to contact the author only after he or she has been invited by someone in the community. Until then, author’s username will be hidden by an alias.