В этой статье из цикла «Музыка в Arduino» мы приводим электрическую схему и программу для музыкальной шкатулки исполняющей несколько мелодий.
Звучание мелодии начинается после нажатия кнопки. После исполнения мелодии музыкальный автомат переходит в ждущий режим, повторное нажатие кнопки запускает на воспроизведение следующую мелодию.
Музыкальный автомат, исполняющий мелодию, собран на Arduino Nano v.3 ядром которой является микроконтроллер ATMEL ATmega328P AU. Музыкальный автомат так же содержит усилитель на транзисторе 2N2222 включённом по схеме с общим эмиттером. В коллектор транзистора включён громкоговоритель с сопротивлением постоянному току 30 Ом. Громкоговоритель (динамик) помещён в ракушку рапана и приклеен к ней термоклеем так, чтобы не было щелей. Ракушка рапана используется нами не только как декоративный элемент. Динамик в ракушке представляет из себя акустическую колонку. Звук в такой акустической системе получается мягче и существенно громче.
Рис. 1. Принципиальная электрическая схема музыкального автомата.
Рис. 2. Акустическая система (колонка) собранная из громкоговорителя и ракушки рапана.
Кнопку подключите к выводу Arduino D7 и GND.
Если кнопку заменить на геркон, музыкальный автомат может срабатывать при открывании дверей. Можно использовать и другие датчики.
Программа для музыкальной шкатулки разработана на языке C в среде Arduino.
#define si3 OCR1A=4050;
#define lad3 OCR1A=4290;
#define la3 OCR1A=4545;
#define sod3 OCR1A=4816;
#define so3 OCR1A=5102;
#define fad3 OCR1A=5405;
#define fa3 OCR1A=5727;
#define mi3 OCR1A=6067;
#define red3 OCR1A=6428;
#define re3 OCR1A=6810;
#define dod3 OCR1A=7215;
#define do3 OCR1A=7645;
#define si2 OCR1A=8099;
#define lad2 OCR1A=8581;
#define la2 OCR1A=9091;
#define sod2 OCR1A=9631;
#define so2 OCR1A=10204;
#define fad2 OCR1A=10811;
#define fa2 OCR1A=11454;
#define mi2 OCR1A=12135;
#define red2 OCR1A=12856;
#define re2 OCR1A=13621;
#define dod2 OCR1A=14431;
#define do2 OCR1A=15289;
#define si1 OCR1A=16198;
#define lad1 OCR1A=17161;
#define la1 OCR1A=18182;
#define sod1 OCR1A=19263;
#define so1 OCR1A=20408;
#define fad1 OCR1A=21622;
#define fa1 OCR1A=22908;
#define mi1 OCR1A=24270;
#define red1 OCR1A=25713;
#define re1 OCR1A=27242;
#define dod1 OCR1A=28862;
#define do1 OCR1A=30578;
#define si0 OCR1A=32396;
#define lad0 OCR1A=34323;
#define la0 OCR1A=36364;
#define sod0 OCR1A=38526;
#define so0 OCR1A=40817;
#define fad0 OCR1A=43244;
#define fa0 OCR1A=45815;
#define mi0 OCR1A=48540;
#define red0 OCR1A=51426;
#define re0 OCR1A=54484;
#define dod0 OCR1A=57724;
#define do0 OCR1A=61156;
#define d2 delay(1000);
#define d4 delay(500);
#define d8 delay(250);
#define d16 delay(125);
#define p4 TCCR1B = 0b00001000;delay(500);TCCR1B = 0b00001001;
#define p8 TCCR1B = 0b00001000;delay(250);TCCR1B = 0b00001001;
#define p16 TCCR1B = 0b00001000;delay(125);TCCR1B = 0b00001001;
#define p64 TCCR1B = 0b00001000;delay(7);TCCR1B = 0b00001001;
int buttonPin = 7;
int n = 0;
void setup() {
pinMode(buttonPin, INPUT_PULLUP);
// Serial.begin(9600);
// while (!Serial) {
// }
}
void loop() {
boolean k = digitalRead(buttonPin);
if (!k) {
pinMode (9, OUTPUT);
pinMode (10, OUTPUT);
TCCR1A = 0b01010000;
//TCCR1B = 0b00001010; // Делитель на 8, на выходе 1.000 MGz
TCCR1B = 0b00001001; // Делитель на 0, на выходе 8.000 MGz
DDRD = 0b11111111;
n < 3 ? n++ : n = 0;
// Serial.println (n);
switch (n) {
case 0:
HavaNagila();
break;
case 1:
Loituma();
break;
case 2 :
grig();
break;
case 3:
gimnRF();
break;
}
PORTD = 0b00000000;
TCCR1B = 0b00001000; // Осанов
digitalWrite (9, LOW);
digitalWrite (10, LOW);
pinMode (9, INPUT);
pinMode (10, INPUT);
pinMode(buttonPin, INPUT_PULLUP);
}
delay(100);
}
void grig() {
mi0 d8 fad0 d8 so0 d8 la0 d8 si0 d8 so0 d8 si0 d4
lad0 d8 fad0 d8 lad0 d4 la0 d8 fa0 d8 la0 d4
mi0 d8 fad0 d8 so0 d8 la0 d8 si0 d8 so0 d8 si0 d8 mi1 d8
re1 d8 si0 d8 so0 d8 si0 d8 re1 d2
mi1 d8 fad1 d8 so1 d8 la1 d8 si1 d8 so1 d8 si1 d4
lad1 d8 fad1 d8 lad1 d4 la1 d8 fa1 d8 la1 d4
mi1 d8 fad1 d8 so1 d8 la1 d8 si1 d8 so1 d8 si1 d8 mi2 d8
re2 d8 si1 d8 so1 d8 si1 d8 re2 d2
}
void Loituma() {
mi1 d8 la1 d16 p64 la1 d16 p64 la1 d8 p64 la1 d16 si1 d16
do2 d16 p64 do2 d16 la1 d16 p64 la1 d16 p64 la1 d8 do2 d8
si1 d8 so1 d16 p64 so1 d16 p64 so1 d8 si1 d8
do2 d8 la1 d16 p64 la1 d16 p64 la1 d4
mi1 d8 la1 d16 p64 la1 d16 p64 la1 d8 p64 la1 d16 si1 d16
do2 d8 la1 d16 p64 la1 d16 p64 la1 d8 do2 d8
mi2 d16 p64 mi2 d16 p64 mi2 d16 re2 d16 do2 d8 si1 d8
do2 d8 la1 d16 p64 la1 d16 p64 la1 d8 p64 la1 d16 do2 d16
mi2 d8 p64 mi2 d8 p64 re2 d8 do2 d8
si1 d8 so1 d16 p64 d16 so1 d16 p64 so1 d8 si1 d8
re2 d16 p64 re2 d16 p64 re2 d16 p64 re2 d16 do2 d8 si1 d8
do2 d8 la1 d16 p64 la1 d16 p64 la1 d8 do2 d8
mi2 d8 p64 mi2 d8 re2 d8 do2 d8
si1 d8 so1 d16 p64 so1 d16 p64 so1 d8 p64 si1 d8
re2 d16 p64 re2 d16 p64 re2 d16 p64 re2 d16 do2 d8 si1 d8
do2 d16 p64 do2 d16 la1 d8 p64 la1 d4
mi2 d8 p64 mi2 d8 re2 d8 do2 d8
si1 d8 so1 d16 p64 so1 d16 p64 so1 d8 si1 d8
re2 d8 p64 re2 d16 p64 re2 d16 do2 d8 si1 d8
do2 d8 la1 d8 p64 la1 d8 do2 d8
mi2 d16 p64 mi2 d16 p64 mi2 d16 p64 mi2 d16 re2 d8 do2 d8
si1 d8 so1 d16 p64 so1 d16 p64 so1 d8 si1 d8
re2 d16 p64 re2 d16 p64 re2 d16 p64 re2 d16 do2 d8 si1 d8
do2 d16 p64 do2 d16 la1 d8 p64 la1 d4
}
void HavaNagila() {
takt1();
takt4();
takt1();
takt8();
takt9();
takt4();
takt9();
takt8();
la1 d2 p64 la1 d2 p64 la1 d4 p64 la1 d4 p64 la1 d4 p64 la1 d4
takt19();
takt19();
takt21();
takt21();
si1 d8 p64 si1 d8 mi2 d2 p4
si1 d4 p64 si1 d4 mi2 d2 p8 mi1 d8 p64
mi1 d4 p64 mi1 d4 mi2 d8 re2 d8 do2 d8 si1 d8
la1 d2
}
void takt1() {
mi1 d4 p64 mi1 d4 p8 sod1 d8 fa1 d8 mi1 d8
sod1 d4 p64 sod1 d4 p8 si1 d8 la1 d8 sod1 d8
la1 d4 p64 la1 d4 p8 do2 d8 si1 d8 la1 d8
}
void takt4() {
sod1 d8 p16 fa1 d16 mi1 d8 fa1 d8 sod1 d2
}
void takt8() {
sod1 d8 p16 fa1 d16 mi1 d8 fa1 d8 mi1 d2
}
void takt9() {
sod1 d8 p64 sod1 d8 p64 sod1 d8 fa1 d8 mi1 d8 p64 mi1 d8 p64 mi1 d4
fa1 d8 p64 fa1 d8 p64 fa1 d8 mi1 d8 re1 d8 p64 re1 d8 re1 d4 p64
re1 d4 fa1 d8 p16 mi1 d16 re1 d4 la1 d4
}
void takt19() {
la1 d8 p64 la1 d8 do2 d8 p16 si1 d16 la1 d8 do2 d8 si1 d8 la1 d8 p64
}
void takt21() {
si1 d8 p64 si1 d8 re2 d8 p16 do2 d16 si1 d8 re2 d8 do2 d8 si1 d8 p64
}
void gimnRF(){
so1 d8
kuplet();
do2 d4 si1 d8 p64 si1 d16 la1 d16 so1 d4 p8 so1 d8
kuplet();
so1 d2 la1 d4 si1 d4
do2 d2 p64 do2 d4
}
void kuplet(){
do2 d4 so1 d8 p64 so1 d16 la1 d16 si1 d4 mi1 d8 p64 mi1 d8
la1 d4 so1 d8 p64 so1 d16 fa1 d16 so1 d4 do1 d8 p64 do1 d8
re1 d4 p64 re1 d8 mi1 d8 fa1 d4 p64 fa1 d8 so1 d8
la1 d4 si1 d8 do2 d8 re2 d4 p64 re2 d8 so1 d8
mi2 d4 re2 d8 p64 re2 d16 do2 d16 re2 d4 si1 d8 so1 d8
do2 d4 si1 d8 p64 si1 d16 la1 d16 si1 d4 mi1 d8 p64 mi1 d8
la1 d4 so1 d8 fa1 d8 so1 d4 do1 d8 p64 do1 d8
do2 d4 si1 d8 p64 si1 d16 la1 d16 so1 d2
mi2 d2 re2 d8 do2 d8 si1 d8 do2 d8
re2 d4 p64 re2 d8 so1 d8 p64 so1 d2
do2 d2 si1 d8 la1 d8 so1 d8 la1 d8
si1 d4 p64 si1 d8 mi1 d8 p64 mi1 d4 p4
do2 d4 la1 d8 p64 la1 d16 si1 d16 do2 d4 la1 d8 p64 la1 d16 si1 d16
do2 d4 la1 d8 do2 d8 fa2 d2 p64
fa2 d2 mi2 d8 re2 d8 do2 d8 re2 d8
mi2 d4 p64 mi2 d8 do2 d8 p64 do2 d2
re2 d2 do2 d8 si1 d8 la1 d8 si1 d8
do2 d4 p64 do2 d8 la1 d8 p64 la1 d2
do2 d4 si1 d8 la1 d8 so1 d4 do1 d8 do2 d8 p64
}
Рис. 4. Листинг программы для музыкального автомата на Arduino.
Скетч использует 11198 байт (36%) памяти устройства. Всего доступно 30720 байт. Глобальные переменные используют 11 байт (0%) динамической памяти, оставляя 2037 байт для локальных переменных. Максимум: 2048 байт.
Ниже, одна из многих музыкальных шкатулок сделанная руками моих маленьких (7-10 лет) учеников.