Следующая версия | Предыдущая версия |
products:laboratory_iot_c:exp23 [2024/12/03 19:15] – создано labuser30 | products:laboratory_iot_c:exp23 [2024/12/03 21:32] (текущий) – [Программный код эксперимента] labuser30 |
---|
==== Программный код эксперимента ==== | ==== Программный код эксперимента ==== |
| |
<file python Exp23.py[enable_line_numbers="2", start_line_numbers_at="1"]> | <file arduino Exp23.ino[enable_line_numbers="2", start_line_numbers_at="1"]> |
from machine import Pin, PWM | #define SPEAKER_PIN 15 |
import time | |
_init() | |
| |
tempo = 2 | int tones[8] = {262, 294, 330, 349, 392, 440, 494, 523}; |
| |
tones = { | enum Note {c, d, e, f, g, a, b, C}; |
'c': 262, | |
'd': 294, | |
'e': 330, | |
'f': 349, | |
'g': 392, | |
'a': 440, | |
'b': 494, | |
'C': 523 | |
} | |
| |
speaker = PWM(Pin(15, Pin.OUT)) | struct Sound { |
| int note; |
| int length; |
| }; |
| |
melody = 'abcdefgC' | const int tempo = 2000; |
rhythm = [8, 2, 1, 8, 3, 4, 6, 8] | |
| |
for tone, length in zip(melody, rhythm): | Sound melody[8] = {{a, 8}, {b, 2}, {c, 1}, {d, 8}, {e, 3}, {f, 4}, |
speaker.duty(512) | {g, 6}, {C, 8}}; |
speaker.freq(tones[tone]) | |
time.sleep(tempo/length) | void setup() { |
speaker.duty(0) | pinMode(SPEAKER_PIN, OUTPUT); |
time.sleep(tempo/length/4) | 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); |
| } |
| } |
</file> | </file> |
| |
Мелодию мы записали строкой ''abcdefgC'', а ритм массивом ''[8, 2, 1, 8, 3, 4, 6, 8]''. | Для того, чтобы записать ноту и ее длительность в одну переменную воспользуемся типом ""struct"", который представляет набор переменных разного типа, объединённых одним именем, в нашем случае — ""Sound"" Количество переменных внутри ""struct"" в принципе не ограничено нам будет достаточно двух "note" и "length": |
С помощью цикла ''for'' и оператора ''in'' проходим по всем элементам мелодии. Для этого мы использовали оператор ''zip''. Он нужен для одновременного перебора сразу двух массивов и получения их элементов в переменные ''tone'' и ''length''. Так на первой итерации в переменной ''tone'' окажется ''a'', а в ''length'' — ''8''. На второй итерации ''b'' и ''2'' соответственно. | |
| <code arduino [enable_line_numbers="2", start_line_numbers_at="7"]> |
| struct Sound { |
| int note; |
| int length; |
| }; |
| </code> |
| |
| Мелодию мы запишем в массив ''melody[8]'' содержащий элементы типа ''Sound'', каждый из которых в свою очередь состоит из двух переменных типа ''int''. |
| |
| <code arduino [enable_line_numbers="2", start_line_numbers_at="14"]> |
| Sound melody[8] = {{a, 8}, {b, 2}, {c, 1}, {d, 8}, {e, 3}, {f, 4}, |
| {g, 6}, {C, 8}}; |
| </code> |
| |
Здесь внимательный читатель заметит, что ''melody'' не является массивом, а является строкой. Почему же мы говорим о ней как о массиве и работаем как с массивом. Оказывается в Python любую строку можно представить как массив символов и обращаться к ним по индексу, что мы и делаем. | С помощью цикла ''for'' проходим по всем элементам мелодии. Обращение к внутренней переменной типа ''struct'' производится с помощью ''.'' и ее имени. |
| |
Получив ноту и ее длительность настраиваем частоту и скважность. Нота начинает звучать: | Получив ноту и ее длительность настраиваем частоту и скважность. Нота начинает звучать: |
<code python [enable_line_numbers="2", start_line_numbers_at="24"]> | <code arduino [enable_line_numbers="2", start_line_numbers_at="24"]> |
speaker.duty(512) | analogWrite(SPEAKER_PIN, 512); |
speaker.freq(tones[tone]) | analogWriteFreq(tones[melody[i].note]); |
</code> | </code> |
| |
Нота звучит, пока мы ждем время, равное ее длительности. В расчете учитывается темп: | Нота звучит, пока мы ждем время, равное ее длительности. В расчете учитывается темп: |
<code python [enable_line_numbers="2", start_line_numbers_at="26"]> | <code arduino [enable_line_numbers="2", start_line_numbers_at="26"]> |
time.sleep(tempo/length) | delay(tempo / melody[i].length); |
</code> | </code> |
| |
Чтобы ноты не сливались, мы делаем между ними маленькие паузы. Паузы между нотами также зависят от темпа и длительности ноты, но в 4 раза короче. | Чтобы ноты не сливались, мы делаем между ними маленькие паузы. Паузы между нотами также зависят от темпа и длительности ноты, но в 4 раза короче. |
<code python [enable_line_numbers="2", start_line_numbers_at="27"]> | <code arduino [enable_line_numbers="2", start_line_numbers_at="27"]> |
speaker.duty(0) | analogWrite(SPEAKER_PIN, 0); |
time.sleep(tempo/length/4) | delay(tempo / melody[i].length / 4); |
</code> | </code> |
| |