Arduino робот играет музыку на бокалах
- Войдите на сайт для отправки комментариев
Ср, 24/11/2021 - 17:51
Всех приветствую! Сегодня я расскажу про то, как я собрал своими руками, ардуино робота "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 // количество светодиодов в ленте |
023 | Adafruit_NeoPixel strip = Adafruit_NeoPixel(NUM_PIX, WS2812_PIN, NEO_GRB + NEO_KHZ800); |
024 |
025 | volatile uint8_t tact_num=0, int_state=0; |
026 | uint8_t sound=0; |
027 | int 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 |
046 | void 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 |
069 | void 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 | //******************выполнение шагов************************ |
107 | void 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*********** |
120 | void tempo() |
121 | { |
122 | int_state=1; // флаг прерывания установлен |
123 | tact_num++; // добавим 1 такт |
124 | if ( tact_num > sizeof (music)-1) tact_num=0; //если достигли конца массива, то сбрасываем в начало |
125 | } |
По-моему очень мило! Код не смотрел, а идея вполне новогодняя и техническая часть - истинный DIY! Реле - молоточек мне реально понравилось!
Я - плюсую такое!
С наливатором не думали совместить?
Для подстройки нот или для злоупотреблений?
Можно совместить, но с подбором нот думаю проблема будет
Для создания праздничной атмосферы и получения большего количества звуковых эффектов.
Идея "Бомба", высота звука определяется количеством налитого. Наливатор наливает определенное количество напитков в фужеры, а участники угадывают мелодию. Затем мелодия воспроизводится и угадавший получает в награду это произведение :)). А можно с завязанными глазами выпить и воспроизвести.
Можно попробовать лазерным дальномером измерять количество жидкости и по таблице определять ноту.
Хотя при этом сами бокалы должны все одинаково звучать, а такого не бывает. Если бы не куча гармоник, то можно бы было при помощи Arduino определять частоту звучания.
Предварительный прозвон/калибровка в микрофончик не поможет? Потом коррекция определённым объёмом жидкости.
Идея хорошая, но у бокалов слишком широкий гармонический спектр колебаний. Даже приложением тюнер невозможно поймать основную частоту. Я думаю на ардуине будет еще сложней. Хотя смотря какие бокалы, можно попробовать с фужерами из обычного стекла, они не так сильно звенят гармониками
Идея хорошая, но у бокалов слишком широкий гармонический спектр колебаний. Даже приложением тюнер невозможно поймать основную частоту. Я думаю на ардуине будет еще сложней. Хотя смотря какие бокалы, можно попробовать с фужерами из обычного стекла, они не так сильно звенят гармониками
А музыканта под руками нет?, на слух наливать ноту?
Идея хорошая, но у бокалов слишком широкий гармонический спектр колебаний. Даже приложением тюнер невозможно поймать основную частоту. Я думаю на ардуине будет еще сложней. Хотя смотря какие бокалы, можно попробовать с фужерами из обычного стекла, они не так сильно звенят гармониками
А музыканта под руками нет?, на слух наливать ноту?
На слух наливать - это хорошо, но бокал не долго останется заполненным! ;))
------------------
А так я только что специально проверил приложением Spectroid на тилипоне - все основные гармоники видны прекрасно. Спектроид просто БПФ с нормальным интерфейсом.
----------------
Развитие вижу ессно в сочетании с наливатором, который заполнит имеющиеся бокалы до гаммы, пересчитает мелодию в получившуюся тональность с учетом разрешения отсутствующих нот гармонически правильно (пока все даже нанка сделает, хотя уже ближе к меге идем). И потом проиграет мелодию.
Далее застольная игра: кто точнее споет (или просвитстит) ноту, тот бокал с её звучанием и выпивает! Смешно? Вроде весело!
Или гости по очереди повторяют за молоточком ноты - на какой сфальшивил - ту и выпил. Тоже забавно, особенно если ноты высокие и участвуют молодые дамы. Будет реально и смешно и пьяно!
Кстати гости с басом и бородой могут брать на октаву или две ниже молоточка, будет еще смешнее! Дама пытается взять как есть, её кавалер на октаву ниже. Хохот обеспечен ...и хорошее настроение!
На слух наливать - это хорошо, но бокал не долго останется заполненным! ;))
Наливали всегда по количеству булек. (в народе по булькам) :))))
На слух наливать - это хорошо, но бокал не долго останется заполненным! ;))
Наливали всегда по количеству булек. (в народе по булькам) :))))
Так это чтобы поровну, а тут совсем наоборот - ноты ведь :-)
Надо версию музыкального наливатора попробовать, с голосовым управлением. Например,так: "Нам в лесу родилась ёлочка", а после исполнения - "а теперь долей до краёв".
Игра "попади в ноту" - аппарат доливает, участник отпивает. Так продолжается до совпадения звука с контрольной нотой.
Так можно алкоголиком стать. Пить напёрстками, всё равно что ложками хлебать из миски.:)))
А так я только что специально проверил приложением Spectroid на тилипоне - все основные гармоники видны прекрасно. Спектроид просто БПФ с нормальным интерфейсом.
Прикольное приложение, спасибо за подсказку