===== Эксперимент 23. Темп, длительность и паузы =====
Если в прошлом эксперименте ты попробовал выполнить дополнительное задание и записать мелодию, то, вероятно, понял, что это не просто, учитывая, что нужно описывать и ноты и их длительности и паузы между ними. А если после написания такой мелодии потребуется изменить ее темп, то придется пересчитывать все паузы. Должен быть другой, более удобный способ записывать мелодии.
Для этого запишем мелодию, последовательность ее нот, в массив, а длительности этих нот в другой. С помощью оператора цикла будем получать эти данные и исполнять. Для записи темпа заведем отдельную переменную, которая будет учитываться в расчете длительностей.
==== Схема эксперимента ====
Схему эксперимента оставим прежней, займемся программой.
{{ :products:esp-iot:exp7_sch.png?nolink |}}
//Рисунок 1. Электрическая принципиальная схема эксперимента//
{{ :wiki:exp7_mont.png?direct&600 |}}
//Рисунок 2. Монтажная схема эксперимента//
==== Программный код эксперимента ====
#define SPEAKER_PIN 15
int tones[8] = {262, 294, 330, 349, 392, 440, 494, 523};
enum Note {c, d, e, f, g, a, b, C};
struct Sound {
int note;
int length;
};
const int tempo = 2000;
Sound melody[8] = {{a, 8}, {b, 2}, {c, 1}, {d, 8}, {e, 3}, {f, 4},
{g, 6}, {C, 8}};
void setup() {
pinMode(SPEAKER_PIN, OUTPUT);
analogWriteRange(1024);;
}
void loop() {
for (int i = 0; i < 8; i++){
analogWrite(SPEAKER_PIN, 512);
analogWriteFreq(tones[melody[i].note]);
delay(tempo / melody[i].length);
analogWrite(SPEAKER_PIN, 0);
delay(tempo / melody[i].length / 4);
}
}
Для того, чтобы записать ноту и ее длительность в одну переменную воспользуемся типом ""struct"", который представляет набор переменных разного типа, объединённых одним именем, в нашем случае — ""Sound"" Количество переменных внутри ""struct"" в принципе не ограничено нам будет достаточно двух "note" и "length":
struct Sound {
int note;
int length;
};
Мелодию мы запишем в массив ''melody[8]'' содержащий элементы типа ''Sound'', каждый из которых в свою очередь состоит из двух переменных типа ''int''.
Sound melody[8] = {{a, 8}, {b, 2}, {c, 1}, {d, 8}, {e, 3}, {f, 4},
{g, 6}, {C, 8}};
С помощью цикла ''for'' проходим по всем элементам мелодии. Обращение к внутренней переменной типа ''struct'' производится с помощью ''.'' и ее имени.
Получив ноту и ее длительность настраиваем частоту и скважность. Нота начинает звучать:
analogWrite(SPEAKER_PIN, 512);
analogWriteFreq(tones[melody[i].note]);
Нота звучит, пока мы ждем время, равное ее длительности. В расчете учитывается темп:
delay(tempo / melody[i].length);
Чтобы ноты не сливались, мы делаем между ними маленькие паузы. Паузы между нотами также зависят от темпа и длительности ноты, но в 4 раза короче.
analogWrite(SPEAKER_PIN, 0);
delay(tempo / melody[i].length / 4);
==== Дополнительное задание ====
* Измени темп мелодии и длительности отдельных нот.