===== Эксперимент 23. Темп, длительность и паузы =====
Если в прошлом эксперименте ты попробовал выполнить дополнительное задание и записать мелодию, то, вероятно, понял, что это не просто, учитывая, что нужно описывать и ноты и их длительности и паузы между ними. А если после написания такой мелодии потребуется изменить ее темп, то придется пересчитывать все паузы. Должен быть другой, более удобный способ записывать мелодии.
Для этого запишем мелодию, последовательность ее нот, в массив, а длительности этих нот в другой. С помощью оператора цикла будем получать эти данные и исполнять. Для записи темпа заведем отдельную переменную, которая будет учитываться в расчете длительностей.
==== Схема эксперимента ====
Схему эксперимента оставим прежней, займемся программой.
{{ :products:esp-iot:exp7_sch.png?nolink |}}
//Рисунок 1. Электрическая принципиальная схема эксперимента//
{{ :wiki:exp7_mont.png?direct&600 |}}
//Рисунок 2. Монтажная схема эксперимента//
==== Программный код эксперимента ====
from machine import Pin, PWM
import time
_init()
tempo = 2
tones = {
'c': 262,
'd': 294,
'e': 330,
'f': 349,
'g': 392,
'a': 440,
'b': 494,
'C': 523
}
speaker = PWM(Pin(15, Pin.OUT))
melody = 'abcdefgC'
rhythm = [8, 2, 1, 8, 3, 4, 6, 8]
for tone, length in zip(melody, rhythm):
speaker.duty(512)
speaker.freq(tones[tone])
time.sleep(tempo/length)
speaker.duty(0)
time.sleep(tempo/length/4)
Мелодию мы записали строкой ''abcdefgC'', а ритм массивом ''[8, 2, 1, 8, 3, 4, 6, 8]''.
С помощью цикла ''for'' и оператора ''in'' проходим по всем элементам мелодии. Для этого мы использовали оператор ''zip''. Он нужен для одновременного перебора сразу двух массивов и получения их элементов в переменные ''tone'' и ''length''. Так на первой итерации в переменной ''tone'' окажется ''a'', а в ''length'' — ''8''. На второй итерации ''b'' и ''2'' соответственно.
Здесь внимательный читатель заметит, что ''melody'' не является массивом, а является строкой. Почему же мы говорим о ней как о массиве и работаем как с массивом. Оказывается в Python любую строку можно представить как массив символов и обращаться к ним по индексу, что мы и делаем.
Получив ноту и ее длительность настраиваем частоту и скважность. Нота начинает звучать:
speaker.duty(512)
speaker.freq(tones[tone])
Нота звучит, пока мы ждем время, равное ее длительности. В расчете учитывается темп:
time.sleep(tempo/length)
Чтобы ноты не сливались, мы делаем между ними маленькие паузы. Паузы между нотами также зависят от темпа и длительности ноты, но в 4 раза короче.
speaker.duty(0)
time.sleep(tempo/length/4)
==== Дополнительное задание ====
* Измени темп мелодии и длительности отдельных нот.