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

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

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

Схема

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

#include "Adafruit_NeoPixel.h"
#include "CyberLib.h"

#define DEBUG     false //false true включить режим отладки
#define DIR_1     D8_High
#define STEP_1    D9_High
#define HAMMER_1  D10_High 
#define DIR_0     D8_Low 
#define STEP_0    D9_Low              
#define HAMMER_0  D10_Low             
#define WS2812_PIN   11              // выход для подключения ws2812

#define step_num 400                // количество шагов на 1 оборот ШД. включен полушаговый режим для снижения шума
#define note_num 7                  // Количество нот-бокалов
#define step_note step_num/note_num // количество шагов двигателя между нотами. вычисляет автоматически
#define step_duration 950          // длительность шага влияет на скорость ШД: чем ниже значение, тем быстрее, но есть вероятность пропуска шагов
#define ratio 1.3                   // коэффициент делитель длительности отрицательного импульса шага
#define kick_duration 8             // длительность удара молоточка в мс.
#define tact 6                    // количество тактов за 1 сек., но нужно учитывать скорость перемещения ШД от ноты к ноте
#define tact_us 1000000/tact        // длительность такта в мкс. вычисляет автоматически

#define NUM_PIX 1                   // количество светодиодов в ленте
Adafruit_NeoPixel strip = Adafruit_NeoPixel(NUM_PIX, WS2812_PIN, NEO_GRB + NEO_KHZ800);

volatile uint8_t tact_num=0, int_state=0; 
uint8_t sound=0;
int next_sound=0;

 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,
                                  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 };
                                  
 /* 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,
                                   255,1,2,255,255,255,255,255, 255,255,3,255,3,255,3,255,   255,2,3,255,2,255,2,255,
                                   1,2,255,1,255,1,255,2,       255,1,255,255,255,4,255,255,  255,2,255,2,255,2,255,255,
                                   255,2,255,2,255,2,255,255,   255,2,255,4,255,0,255,255,    1,2,255,255,255,255,255,255,
                                   255,3,255,3,255,3,255,255,   2,3,255,2,255,2,255,255,      2,4,255,4,255,3,255,1,
                                   255,0,255,255,255,255,255,255   };
                                     
 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, 
                                            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, 
                                            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, 
                                            5,3,0,3,5,3,0,3,     6,3,0,3,6,3,0,3,      255,255,255,255 }; */
                 
 // const uint8_t music[] PROGMEM = { 255,0,1,2,3,4,5,6,5,4,3,2,1,0,255 }; // для расстановки бокалов   

void setup()      
{
 D10_Out; 
  HAMMER_1; D8_Out; D9_Out; DIR_0; STEP_0;   //Настраиваем пин D8, D9 и D10 на выход
  D12_In; D12_High; 
 
 pinMode(12, INPUT_PULLUP);
 
  randomSeed(analogRead(0));      // получаем начальное значение случайного числа
  strip.begin(); 
  strip.setBrightness(255);       // яркость светодиода на максимум
  strip.setPixelColor(0,0,0,0);
  strip.show();
   
  while(D12_Read){} // ждем нажатия кнопки
  
  #if DEBUG                       // для отладки кода
    Serial.begin(115200);
  #endif

  StartTimer1(tempo, tact_us);  // запуск таймера, первый параметр это обработчик прерывания
}

void loop()
{ 
  if( int_state )                 // если было прерывание по таймеру
   { 
      cli();                     // запрет прерываний, чтобы избежать нарушений последовательности тактов   
       uint8_t tmpS = pgm_read_byte_near(&music[tact_num]);   // текущая нота
       uint8_t tmpN;
       if(tact_num != sizeof(music)-1)
       {
        tmpN = pgm_read_byte_near(&music[tact_num+1]); // следующая нота
       } else tmpN = pgm_read_byte_near(&music[0]);     // иначе в начало массива
      sei(); 

      if(tmpN != 255) next_sound = tmpN;  // проверяем следующий сэмпл на пустой такт
      if(tmpS != 255)                    // если не пустой такт, то ударяем молоточком и перемещаемся на следующую ноту
      {    
         HAMMER_0;
          sound = tmpS;
          uint8_t r=random(2); if(r) r=255;
          uint8_t g=random(2); if(g) g=255;
          uint8_t b=random(2); if(b) b=255;
          if(r==0 && g==0) b=255;
          strip.setPixelColor(0,r,g,b);
          strip.show(); 
          delay_ms(kick_duration);       // длительность импульса удара. Можно регулировать силу удара
        HAMMER_1;
      } 
        #if DEBUG                             //для отладки кода
          Serial.println(tact_num);
          Serial.println();
        #endif
      
     steps((next_sound-sound) * step_note); // перемещаем на следующий бокал
     int_state=0;                           // сбросить флаг прерывания
   }     
}

//******************выполнение шагов************************
void steps(int shag)
{       
  if(shag>0) { DIR_1; } else { DIR_0; shag=abs(shag); }       // проверка направления вращения, убираем знак(-)
   for(uint16_t i = 0; i < shag; i++)  // Выполняем заданное количество шагов
   {
    STEP_1;
    delay_us(step_duration);          // длительность шага, влияет на скорость вращения
    STEP_0;
  //  delay_us(step_duration/ratio);
  } 
}

//****************обработчик прерывания таймера1***********
void tempo()
{
 int_state=1;             // флаг прерывания установлен
 tact_num++;              // добавим 1 такт
 if( tact_num > sizeof(music)-1) tact_num=0; //если достигли конца массива, то сбрасываем в начало
}

 

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

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

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

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 на тилипоне - все основные гармоники видны прекрасно. Спектроид просто БПФ с нормальным интерфейсом.

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