Эксперимент 23. Темп, длительность и паузы

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

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

Схема эксперимента

Схему эксперимента оставим прежней, займемся программой.

Рисунок 1. Электрическая принципиальная схема эксперимента

Рисунок 2. Монтажная схема эксперимента

Программный код эксперимента

Exp23.ino
  1. #define SPEAKER_PIN 15
  2.  
  3. int tones[8] = {262, 294, 330, 349, 392, 440, 494, 523};
  4.  
  5. enum Note {c, d, e, f, g, a, b, C};
  6.  
  7. struct Sound {
  8. int note;
  9. int length;
  10. };
  11.  
  12. const int tempo = 2000;
  13.  
  14. Sound melody[8] = {{a, 8}, {b, 2}, {c, 1}, {d, 8}, {e, 3}, {f, 4},
  15. {g, 6}, {C, 8}};
  16.  
  17. void setup() {
  18. pinMode(SPEAKER_PIN, OUTPUT);
  19. analogWriteRange(1024);;
  20. }
  21.  
  22. void loop() {
  23. for (int i = 0; i < 8; i++){
  24. analogWrite(SPEAKER_PIN, 512);
  25. analogWriteFreq(tones[melody[i].note]);
  26. delay(tempo / melody[i].length);
  27. analogWrite(SPEAKER_PIN, 0);
  28. delay(tempo / melody[i].length / 4);
  29. }
  30. }

Для того, чтобы записать ноту и ее длительность в одну переменную воспользуемся типом ««struct»», который представляет набор переменных разного типа, объединённых одним именем, в нашем случае — ««Sound»» Количество переменных внутри ««struct»» в принципе не ограничено нам будет достаточно двух «note» и «length»:

  1. struct Sound {
  2. int note;
  3. int length;
  4. };

Мелодию мы запишем в массив melody[8] содержащий элементы типа Sound, каждый из которых в свою очередь состоит из двух переменных типа int.

  1. Sound melody[8] = {{a, 8}, {b, 2}, {c, 1}, {d, 8}, {e, 3}, {f, 4},
  2. {g, 6}, {C, 8}};

С помощью цикла for проходим по всем элементам мелодии. Обращение к внутренней переменной типа struct производится с помощью . и ее имени.

Получив ноту и ее длительность настраиваем частоту и скважность. Нота начинает звучать:

  1. analogWrite(SPEAKER_PIN, 512);
  2. analogWriteFreq(tones[melody[i].note]);

Нота звучит, пока мы ждем время, равное ее длительности. В расчете учитывается темп:

  1. delay(tempo / melody[i].length);

Чтобы ноты не сливались, мы делаем между ними маленькие паузы. Паузы между нотами также зависят от темпа и длительности ноты, но в 4 раза короче.

  1. analogWrite(SPEAKER_PIN, 0);
  2. delay(tempo / melody[i].length / 4);

Дополнительное задание

  • Измени темп мелодии и длительности отдельных нот.