Arduino робот играет музыку на бокалах

duino
Offline
Зарегистрирован: 13.03.2018

Всех приветствую! Сегодня я расскажу про то, как я собрал своими руками, ардуино робота "Glass Harp", играющего музыку на винных бокалах.

Схема

Код для Ардуино

001#include "Adafruit_NeoPixel.h"
002#include "CyberLib.h"
003 
004#define DEBUG     false //false true включить режим отладки
005#define DIR_1     D8_High
006#define STEP_1    D9_High
007#define HAMMER_1  D10_High
008#define DIR_0     D8_Low
009#define STEP_0    D9_Low             
010#define HAMMER_0  D10_Low            
011#define WS2812_PIN   11              // выход для подключения ws2812
012 
013#define step_num 400                // количество шагов на 1 оборот ШД. включен полушаговый режим для снижения шума
014#define note_num 7                  // Количество нот-бокалов
015#define step_note step_num/note_num // количество шагов двигателя между нотами. вычисляет автоматически
016#define step_duration 950          // длительность шага влияет на скорость ШД: чем ниже значение, тем быстрее, но есть вероятность пропуска шагов
017#define ratio 1.3                   // коэффициент делитель длительности отрицательного импульса шага
018#define kick_duration 8             // длительность удара молоточка в мс.
019#define tact 6                    // количество тактов за 1 сек., но нужно учитывать скорость перемещения ШД от ноты к ноте
020#define tact_us 1000000/tact        // длительность такта в мкс. вычисляет автоматически
021 
022#define NUM_PIX 1                   // количество светодиодов в ленте
023Adafruit_NeoPixel strip = Adafruit_NeoPixel(NUM_PIX, WS2812_PIN, NEO_GRB + NEO_KHZ800);
024 
025volatile uint8_t tact_num=0, int_state=0;
026uint8_t sound=0;
027int next_sound=0;
028 
029 const uint8_t music[] PROGMEM = {255,255,0,1,2,255,2,255, 2,3,4,255,4,255,4,5, 3,255,3,255,2,1,1,2,
030                                  255,255,0,1,2,255,2,255, 2,3,4,255,4,255,4,5, 3,255,3,255,2,1,2,255,255,255 };
031                                   
032 /* const uint8_t music[] PROGMEM = { 255,255,2,255,2,255,2,255,   255,255,2,255,2,255,2,255,   255,255,2,255,4,255,0,255,
033                                   255,1,2,255,255,255,255,255, 255,255,3,255,3,255,3,255,   255,2,3,255,2,255,2,255,
034                                   1,2,255,1,255,1,255,2,       255,1,255,255,255,4,255,255,  255,2,255,2,255,2,255,255,
035                                   255,2,255,2,255,2,255,255,   255,2,255,4,255,0,255,255,    1,2,255,255,255,255,255,255,
036                                   255,3,255,3,255,3,255,255,   2,3,255,2,255,2,255,255,      2,4,255,4,255,3,255,1,
037                                   255,0,255,255,255,255,255,255   };
038                                      
039 const uint8_t music[] PROGMEM = { 255,255, 5,3,0,3,5,3,0,3,     5,2,0,2,5,2,0,2,       4,2,0,2,4,2,0,2,   4,2,0,2,4,2,0,2,
040                                            5,3,0,3,5,3,0,3,     5,3,0,3,5,3,0,3,       5,2,0,2,5,2,0,2,  5,2,0,2,5,2,0,2,
041                                            5,3,1,3,5,3,1,3,     5,3,1,3,4,3,1,3,       6,4,2,4,6,4,2,4,   6,2,0,2,5,2,0,2,
042                                            5,3,0,3,5,3,0,3,     6,3,0,3,6,3,0,3,      255,255,255,255 }; */
043                  
044 // const uint8_t music[] PROGMEM = { 255,0,1,2,3,4,5,6,5,4,3,2,1,0,255 }; // для расстановки бокалов  
045 
046void setup()     
047{
048 D10_Out;
049  HAMMER_1; D8_Out; D9_Out; DIR_0; STEP_0;   //Настраиваем пин D8, D9 и D10 на выход
050  D12_In; D12_High;
051  
052 pinMode(12, INPUT_PULLUP);
053  
054  randomSeed(analogRead(0));      // получаем начальное значение случайного числа
055  strip.begin();
056  strip.setBrightness(255);       // яркость светодиода на максимум
057  strip.setPixelColor(0,0,0,0);
058  strip.show();
059    
060  while(D12_Read){} // ждем нажатия кнопки
061   
062  #if DEBUG                       // для отладки кода
063    Serial.begin(115200);
064  #endif
065 
066  StartTimer1(tempo, tact_us);  // запуск таймера, первый параметр это обработчик прерывания
067}
068 
069void loop()
070{
071  if( int_state )                 // если было прерывание по таймеру
072   {
073      cli();                     // запрет прерываний, чтобы избежать нарушений последовательности тактов  
074       uint8_t tmpS = pgm_read_byte_near(&music[tact_num]);   // текущая нота
075       uint8_t tmpN;
076       if(tact_num != sizeof(music)-1)
077       {
078        tmpN = pgm_read_byte_near(&music[tact_num+1]); // следующая нота
079       } else tmpN = pgm_read_byte_near(&music[0]);     // иначе в начало массива
080      sei();
081 
082      if(tmpN != 255) next_sound = tmpN;  // проверяем следующий сэмпл на пустой такт
083      if(tmpS != 255)                    // если не пустой такт, то ударяем молоточком и перемещаемся на следующую ноту
084      {   
085         HAMMER_0;
086          sound = tmpS;
087          uint8_t r=random(2); if(r) r=255;
088          uint8_t g=random(2); if(g) g=255;
089          uint8_t b=random(2); if(b) b=255;
090          if(r==0 && g==0) b=255;
091          strip.setPixelColor(0,r,g,b);
092          strip.show();
093          delay_ms(kick_duration);       // длительность импульса удара. Можно регулировать силу удара
094        HAMMER_1;
095      }
096        #if DEBUG                             //для отладки кода
097          Serial.println(tact_num);
098          Serial.println();
099        #endif
100       
101     steps((next_sound-sound) * step_note); // перемещаем на следующий бокал
102     int_state=0;                           // сбросить флаг прерывания
103   }    
104}
105 
106//******************выполнение шагов************************
107void steps(int shag)
108{      
109  if(shag>0) { DIR_1; } else { DIR_0; shag=abs(shag); }       // проверка направления вращения, убираем знак(-)
110   for(uint16_t i = 0; i < shag; i++)  // Выполняем заданное количество шагов
111   {
112    STEP_1;
113    delay_us(step_duration);          // длительность шага, влияет на скорость вращения
114    STEP_0;
115  //  delay_us(step_duration/ratio);
116  }
117}
118 
119//****************обработчик прерывания таймера1***********
120void tempo()
121{
122 int_state=1;             // флаг прерывания установлен
123 tact_num++;              // добавим 1 такт
124 if( tact_num > sizeof(music)-1) tact_num=0; //если достигли конца массива, то сбрасываем в начало
125}

 

wdrakula
wdrakula аватар
Offline
Зарегистрирован: 15.03.2016

По-моему очень мило! Код не смотрел, а идея вполне новогодняя и техническая часть - истинный DIY! Реле - молоточек мне реально понравилось!

Я - плюсую такое!

sadman41
Offline
Зарегистрирован: 19.10.2016

С наливатором не думали совместить?

andriano
andriano аватар
Offline
Зарегистрирован: 20.06.2015

sadman41 пишет:
С наливатором не думали совместить?

Для подстройки нот или для злоупотреблений?

duino
Offline
Зарегистрирован: 13.03.2018

Можно совместить, но с подбором нот думаю проблема будет 

sadman41
Offline
Зарегистрирован: 19.10.2016

Для создания праздничной атмосферы и получения большего количества звуковых эффектов.

svm
Offline
Зарегистрирован: 06.11.2016

sadman41 пишет:
С наливатором не думали совместить?

Идея "Бомба", высота звука определяется количеством налитого. Наливатор наливает определенное количество напитков в фужеры, а участники угадывают мелодию. Затем мелодия воспроизводится и угадавший получает в награду это произведение :)). А можно с завязанными глазами выпить и воспроизвести. 

duino
Offline
Зарегистрирован: 13.03.2018

Можно попробовать лазерным дальномером измерять количество жидкости и по таблице определять ноту.

Хотя при этом сами бокалы должны все одинаково звучать, а такого не бывает. Если бы не куча гармоник, то можно бы было при помощи Arduino определять частоту звучания.

sadman41
Offline
Зарегистрирован: 19.10.2016

Предварительный прозвон/калибровка в микрофончик не поможет? Потом коррекция определённым объёмом жидкости.

duino
Offline
Зарегистрирован: 13.03.2018

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

lilik
Offline
Зарегистрирован: 19.10.2017

duino пишет:

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

А музыканта под руками нет?, на слух наливать ноту?

wdrakula
wdrakula аватар
Offline
Зарегистрирован: 15.03.2016

lilik пишет:

duino пишет:

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

А музыканта под руками нет?, на слух наливать ноту?

На слух наливать - это хорошо, но бокал не долго останется заполненным! ;))

------------------

А так я только что специально проверил приложением Spectroid на тилипоне - все основные гармоники видны прекрасно. Спектроид просто БПФ с нормальным интерфейсом.

----------------

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

Далее застольная игра: кто точнее споет (или просвитстит) ноту, тот бокал с её звучанием и выпивает! Смешно? Вроде весело!

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

Кстати гости с басом и бородой могут брать на октаву или две ниже молоточка, будет еще смешнее! Дама пытается взять как есть, её кавалер на октаву ниже. Хохот обеспечен ...и хорошее настроение!

SAB
Offline
Зарегистрирован: 27.12.2016

wdrakula пишет:

На слух наливать - это хорошо, но бокал не долго останется заполненным! ;))

Наливали всегда по количеству булек. (в народе по булькам) :))))

lilik
Offline
Зарегистрирован: 19.10.2017

SAB пишет:

wdrakula пишет:

На слух наливать - это хорошо, но бокал не долго останется заполненным! ;))

Наливали всегда по количеству булек. (в народе по булькам) :))))

Так это чтобы поровну, а тут совсем наоборот - ноты ведь :-)

Надо версию музыкального наливатора попробовать, с голосовым управлением. Например,так: "Нам в лесу родилась ёлочка", а после исполнения - "а теперь долей до краёв".

sadman41
Offline
Зарегистрирован: 19.10.2016

Игра "попади в ноту" - аппарат доливает, участник отпивает. Так продолжается до совпадения звука с контрольной нотой.

SAB
Offline
Зарегистрирован: 27.12.2016

sadman41 пишет:
Игра "попади в ноту" - аппарат доливает, участник отпивает. Так продолжается до совпадения звука с контрольной нотой.

Так можно алкоголиком стать. Пить напёрстками, всё равно что ложками хлебать из миски.:)))

duino
Offline
Зарегистрирован: 13.03.2018

 

wdrakula пишет:

А так я только что специально проверил приложением Spectroid на тилипоне - все основные гармоники видны прекрасно. Спектроид просто БПФ с нормальным интерфейсом.

Прикольное приложение, спасибо за подсказку