Музыкальная шкатулка на Arduino

Наш следующий проект на контроллере Arduino – музыкальная шкатулка. Программный скетч для Ардуино прилагается, так что вы легко сможете добавить свои мелодии, даже не имея больших познаний в программировании Ардуино. Принцип работы устройства очень прост — при открытии шкатулка будет играть приятную мелодию, при закрытии шкатулки воспроизведение мелодии прекращается. Для данного проект потребуется сама плата Arduino и минимум деталей: динамик, потенциометр (переменный резистор), сопротивление на 10кОм, батарейки АА, кнопка и транзистор КТ503А или любой другой маломощный n-p-n транзистор, например КТ315.

Звук – колебательное движение частиц упругой среды, распространяющееся в виде волн в газообразной, жидкой или твёрдой средах. Если сказать просто — это колебания волн. В динамике колеблется мембрана. В зависимости от частоты колебания мы слышим звук разной тональности. От глубины хода мембраны зависит громкость. Управляют мембраной за счёт подаваемого напряжения.
В платах Arduino для вывода звука на динамик используются цифровые или аналоговые выходы. Для воспроизведения мелодии необходимо подавать последовательно звуки определенной частоты и длительности. Для генерации звуков определенной частоты и длительности  в Arduino используется функция tone():
tone(pin,frequency,duration);

Функция tone() генерирует на выводе pin прямоугольный сигнал  частоты frequency с коэффициентом заполнения 50%. Третий (необязательный) параметр функции duration позволяет задавать длительность сигнала. Если длительность сигнала не указана, звук будет генерироваться до вызова функция noTone().
Обычно в примерах по генерации звуков на Arduino для воспроизведения звука используется пьезоэлектрический излучатель, но к сожалению громкость звука при этом недостаточна. Поэтому Мы для воспроизведения звука мы будем использовать маленький динамик.

В качестве контроллера Arduino я использовал Arduino Pro Mini, которая отличается малым размером и очень удобна при использовании на плате. Можно использовать любую плату Ардуино, например, подойдет наиболее популярная Arduino Uno. Соберем схему, показанную на рисунке 1 (схема соединений на рисунке 2).

Принципиальная схема музыкальной шкатулки
Рис. 1. Принципиальная схема музыкальной шкатулки
Схема подключения компонентов к Ардуино
Рис. 2. Схема подключения компонентов к Arduino

Для написания скетча нам понадобятся значения частот для нот 1 и 2 октавы и обозначения для каждой ноты (см. таблицу 1).

Таблица нот
Таблица 1. Таблица нот

Теперь подберем мелодию, которую будет воспроизводить музыкальная шкатулка. Желательно найти мелодию, записанную на нотном стане. Я выбрал простую мелодию – «В траве сидел кузнечик» (ноты на рисунке 3).

Ноты мелодии
Рисунок 3. Мелодия «В траве сидел кузнечик» на нотном стане.

Теперь приступим к написанию скетча. Потенциометр в схеме (рисунок 1) присутствует для подбора нужного темпа мелодии. Темп может принимать значения от MIN_TEMPO до MAX_TEMPO. Для вычисления подобранного темпа используем функцию map(), которая преобразует значение на аналоговом входе A0 в значение подобранного темпа.
tempo=map(analogRead(PIN_POT),0,1024,MIN_TEMPO,MAX_TEMPO);

Занесем в массив melody[] последовательность воспроизводимых нот, список длительностей нот занесем в массив duration[], при этом длительность целой ноты равна 32, половинной 16, и т.д. до 1/32 – длительность1. Данные с обозначением нот занесем в массив notes[], а данные с частотами для соответствующих нот занесем в массив frequency[]. Паузу обозначим символом ‘*’.

// МЕЛОДИЯ – массив нот и массив длительностей
char melody[]={'A', 'E','A','E','A', 'U','G','G','G',
                    'E','U','E','G', 'A','A','A','A',
                    'E','A','E','A', 'U','G','G','G',
                    'E','U','E','G', 'A','A',
                    'H','H','H','H','H', 'c','c','c','c','c',
                    'c','H','A','U', 'A','A','A','A',
                    'H','H','H','H','H', 'c','c','c','c','c',
                    'c','H','A','U', 'A', '*'
};
int bb[]={4, 4,4,4,4, 4,4,4,4,
        4,4,4,4, 4,4,4,4,
        4,4,4,4, 4,4,4,4,
        4,4,4,4, 8,8,
        4,2,2,4,4, 4,2,2,4,4,
        4,4,4,4, 4,4,4,4,
        4,2,2,4,4, 4,2,2,4,4,
        4,4,4,4, 4,64
};
// массив для наименований нот в пределах двух октав
char names[]={'c','r','d','s','e','f','t','g','u','a','b',
'h','C','R','D','S','E','F','T','G','U','A','B', 'H','F'};
// массив частот нот
int tones[]={261,277,293,311,329,349,370,392,415,440,466,
494, 523,554,587,622,659,698,740,784,830,880,932,988};

В цикле loop() мы проверяем отжатие кнопки (открытие шкатулки). По отжатию кнопки начинается проигрывание мелодии понотно, вызывая процедуру playNote(), в которую передает обозначение текущей ноты и продолжительность. Процедура playNote() находит по обозначению ноты значение соответствующей частоты и вызывает для проигрывания ноты функцию tone(). Продолжительность звучания ноты – это базовая нотная длительность (32 – для целой, 16 – для полуноты, 8 – для четвертной и т.д.) умноженная на значение темпа произведения – temp. Значение temp устанавливается по значению потенциометра, и подбирается при отладке, в работе не меняется. Для лучшего звучания музыкального отрезка после воспроизведения каждой ноты делаем небольшую паузу delay(beats*tempo+tempo). По нажатии кнопки при воспроизведении мелодии, воспроизведение прекращается. При нажатии клавиш обязательно использовать процедуру проверки на дребезг debounce(boolean last).

Запустим Arduino IDE. Создадим новый скетч и внесем в него содержимое листинга 1.

// МЕЛОДИЯ – массив нот и массив длительностей
char melody[]={'A', 'E','A','E','A', 'U','G','G','G',
                    'E','U','E','G', 'A','A','A','A',
                    'E','A','E','A', 'U','G','G','G',
                    'E','U','E','G', 'A','A',
                    'H','H','H','H','H', 'c','c','c','c','c',
                    'c','H','A','U', 'A','A','A','A',
                    'H','H','H','H','H', 'c','c','c','c','c',
                    'c','H','A','U', 'A', '*'
};
int bb[]={4, 4,4,4,4, 4,4,4,4,
        4,4,4,4, 4,4,4,4,
        4,4,4,4, 4,4,4,4,
        4,4,4,4, 8,8,
        4,2,2,4,4, 4,2,2,4,4,
        4,4,4,4, 4,4,4,4,
        4,2,2,4,4, 4,2,2,4,4,
        4,4,4,4, 4,64
};
// подключить динамик к pin 8
#define PIN_SPEAKER 8
// переменные - темп воспроизведения, ноты, длительности
int tempo,notes,beats;
#define MIN_TEMPO 20
#define MAX_TEMPO 100
// пин подключения потенциометра
#define PIN_POT A0
// пин подключения кнопки
// при отжатии - включить проигрывание мелодии
// при нажатии прекратить
// пин подключения потенциометра
#define PIN_BUTTON 5
// Переменная для сохранения текущего состояния кнопки
int tekButton = LOW;
// Переменная для сохранения предыдущего состояния
int prevButton = LOW; 
// Переменная для сохранения количества проигрываний
int countPlay = 0; 
void setup()  {
   // Сконфигурировать контакт динамика как выход
   pinMode(PIN_SPEAKER, OUTPUT);
   // Сконфигурировать контакт кнопки как вход
   pinMode (PIN_BUTTON, INPUT);
}
void loop()  {
   tekButton = debounce(prevButton);
   if (prevButton == HIGH && tekButton == LOW) // если отжатие...
      {
      // получить темп воспроизведения
      tempo=map(analogRead(PIN_POT),0,1024,MIN_TEMPO,MAX_TEMPO);
      for(int i=0;i<sizeof(melody);i++)  {
         notes=melody[i];
         beats=bb[i];
         if (notes == '*')
            tone(PIN_SPEAKER,0, beats*tempo); // пауза
         else
            playNote(notes, beats*tempo); // воспроизвести ноту
         // пауза между нотами
         delay(beats*tempo+tempo);
         // проверить на нажатие
         tekButton = debounce(prevButton);
         if (prevButton == LOW  && tekButton == HIGH) }
            i=sizeof(melody); // если нажатие - прекратить
            tekButton == LOW;
         }               
         prevButton = tekButton;
         // получить темп воспроизведения  
         tempo=map(analogRead(PIN_POT),0,1024,MIN_TEMPO,MAX_TEMPO);
     }
   }
   prevButton = tekButton;   
}
//
// процедура проигрыша ноты
void playNote(char note, int duration) {
   // массив для наименований нот в пределах двух октав
   char names[]={'c','r','d','s','e','f','t','g','u','a','b',
   'h','C','R','D','S','E','F','T','G','U','A','B', 'H','F'};
   // массив частот нот
   int tones[]={261,277,293,311,329,349,370,392,415,440,466,
   494, 523,554,587,622,659,698,740,784,830,880,932,988};
   for (int i = 0; i < sizeof(tones); i++) {
      if (names[i] == note)  {
         tone(PIN_SPEAKER,tones[i],duration);
      }
   }
}
// Функция сглаживания дребезга. Принимает в качестве
// аргумента предыдущее состояние кнопки и выдает фактическое.
boolean debounce(boolean last) {
   // Считать состояние кнопки,
   boolean current = digitalRead(PIN_BUTTON); 
   if (last != current) // если изменилось...
      {
      delay(5); // ждем 5 мс
      // считываем состояние кнопки
      current = digitalRead(PIN_BUTTON); 
      // возвращаем состояние кнопки
      return current; 
   }
}    

После загрузки скетча и настройки потенциометром скорости воспроизведения мелодии все упаковываем в шкатулку (рисунки 4, 5, 6) и дарим маме или любимой девушке.

Собранная схема музыкальной шкатулки
Рис. 4. Собранная схема музыкальной шкатулки

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

Корпус музыкальной шкатулки
Рис. 5. Сундучок — корпус музыкальной шкатулки

Готовое устройство - музыкальная шкатулка
Рис. 6. Устанавливаем схему музыкальной шкатулкив корпус

 Скачать файлы проекта

 Вы можете собрать данный проект, используя товары из магазина Радиодеда:

{product id=1212}

Похожие записи