Pull to refresh

Как пьезоизлучатель голос искал

Reading time5 min
Views5.2K

Как известно, каждый пьезоизлучатель уникален и производится со скрытым талантом. Наша задача его увидеть. Так получилось, что у моего пьезоизлучателя врожденный талант к музыке. Голосом он, конечно, не вышел, пассивный, маломощный, на АЧХ вообще лучше не смотреть, зато желания воспроизводить музыку хоть отбавляй. Воспроизведение мелодии понадобилось для одного из проектов. Задача простая: действия пользователя должны сопровождаться звуками. Если нажатие кнопки это стандартный «БИП», то разряд батареи уже «ТУРУРУМ», включение «ТУМТУМ-ТУТУ» и т.д. Оказалось, что звуки в моей голове и звуки, получаемые на пьезоизлучателе совершенно не похожи друг на друга. Пришлось немного углубиться в тему.

Сперва небольшой обзор того, что было изучено. За основу взята идея, изложенная китайским коллегой, есть английский перевод. Также стоит упомянуть материалы статьи. Вот что удалось узнать.

  1. Для воспроизведения мелодий необходимо использовать информацию: ноты, длительность нот, темп;

  2. Для воспроизведения нот и установки их длительности необходимо использовать таймеры;

  3. Алгоритм должен быть таким, чтобы не останавливать выполнения основной программы.

И этого достаточно, чтобы сделать небольшую библиотеку для воспроизведения мелодии по нотам. Вот результат:

Для работы с библиотекой необходимо иметь минимальные знания нотной грамоты. Музыкальная нотация присваивает нотам буквенные обозначения c, d, e, f и т.д. Вместо букв можно использовать цифры, за ноль принимаем ноту ДО малой октавы.  

Частота, Гц

Нота

Малая октава

Вторая октава

ДО

0

c, his

130,8

24

c2, his2

523,2

ДО ♯, РЕ ♭

1

cis, des

138,6

25

cis2, des2

554,4

РЕ

2

d

146,8

26

d2

587,3

РЕ ♯, МИ ♭

3

dis, es

155,6

27

dis2, es2

622,3

МИ

4

e, fes

164,8

28

e2, fes2

659,3

ФА

5

f, eis

174,6

29

f2, eis2

698,5

ФА ♯, СОЛЬ ♭

6

fis, ges

185

30

fis2, ges2

740

СОЛЬ

7

g

196

31

g2

784

СОЛЬ ♯, ЛЯ ♭

8

gis, as

207,7

32

gis2, as2

830,6

ЛЯ

9

a

220

33

a2

880

ЛЯ ♯, СИ ♭

10

ais, b

233,1

34

ais2, b2

932,3

СИ

11

h, ces1

247

35

h2, ces3

987,8

Нота

Первая октава

Третья октава

ДО

12

c1, his1

261,6

36

c3, his3

1046,5

ДО ♯, РЕ ♭

13

cis1, des1

277,2

37

cis3, des3

1108,7

РЕ

14

d1

293,7

38

d3

1174,7

РЕ ♯, МИ ♭

15

dis1, es1

311,1

39

dis3, es3

1244,5

МИ

16

e1, fes1

329,6

40

e3, fes3

1318,5

ФА

17

f1, eis1

349,2

41

f3, eis3

1396,9

ФА ♯, СОЛЬ ♭

18

fis1, ges1

370

42

fis3, ges3

1480

СОЛЬ

19

g1

392

43

g3

1568

СОЛЬ ♯, ЛЯ ♭

20

gis1, as1

415,3

44

gis3, as3

1661,2

ЛЯ

21

a1

440

45

a3

1760

ЛЯ ♯, СИ ♭

22

ais1, b1

466,2

46

ais3, b3

1864,7

СИ

23

h1, ces2

493,9

47

h3, ces4

1975,6

Допустимую длительность нот ограничим в диапазоне от 1 до 1/16.

Условный номер

Длительность ноты/паузы

1

шестнадцатая

2

восьмая

4

четвертая

8

половинная

16

целая

Таким образом, чтобы составить массив входных данных, необходимо указать перечень нот, их длительность и скорость воспроизведения мелодии. Массив мелодии можно записать как uint8_t MUSIC[] = {23, 23, 24, 26 … }, массив длительностей как uint8_t DURATION[] = {4, 4, 4, 4 … }, темп uint8_t TEMPO = 140. Либо с использованием обозначений нот uint8_t MUSIC[] = {h1, h1, c2, d2…}, uint8_t DURATION[] = {T_1_4, T_1_4, T_1_4, T_1_4 … }.

На рисунке номерами сверху обозначены ноты и их длительности согласно таблицам.

Возможности пьезоизлучателя для генерации звука весьма ограничены, получить низкочастотные колебания не удастся. Как правило, максимум громкости излучателя попадает в диапазон частот от двух до четырех кГц.  Для используемого мною HPM14A громкость звука на частотах менее 500 Гц будет примерно 40 – 50 дБ.

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

Каждая нота представляет собой «треугольник» определенной высоты. Программа синтезирует затухающий звук, как это происходит при колебаниях струны. Сгенерировать сигнал такой формы на микроконтроллере достаточно сложно. Существенно упростим себе задачу. Каждую ноту будем задавать при помощи интервала сигнала и интервала тишины. Сумма двух интервалов составляет длительность звучания ноты. Интервал сигнала – ШИМ заданной частоты, тишины – нулевой уровень напряжения. Вставка нулевого интервала позволяет различать многократное воспроизведение одной и той же ноты.

Для решения задачи достаточно двух таймеров. Рассмотрим генерацию частоты нот. Возьмем ноту ДО малой октавы в качестве примера. При тактировании таймера частотой 4 МГц, значения для регистра перезагрузки считаются следующим образом.

В регистр сравнения необходимо записать половину рассчитанной величины, чтобы сигнал ШИМ представлял меандр.

Интервалы воспроизведения и тишины задаются вторым таймером, значения которого рассчитываются исходя из длительности нот и темпа мелодии. Темп определяет  число ударов метронома в минуту. Используется понятие BPM (beats per minute, удары в минуту). BPM — это количество четвертных нот в минуту, например, 120 BPM означает, что в минуту играется 120 четвертных. Соответственно расчет длительности необходимо выполнять относительно длительности нот в ¼.

Например, темп равен 140. Длительность воспроизведения четвертной ноты составляет:

В итоге интервал воспроизведения выбран как play_time * 9/10, интервал тишины, как play_time * 1/10.

В завершение упомяну о работе с библиотекой. В моем проекте пьезоизлучатель выделен в класс с простым интерфейсом управления и внутренней машиной состояний. Переход между состояниями происходит по прерыванию от таймера интервалов (duration timer). Такая структура необходима для того, чтобы не тормозить остальные задачи программы, минимизировать время пребывания в функции воспроизведения ноты.

Для воспроизведения мелодии достаточно вызвать функцию PlayMusic(...), например так: Buzzer.PlayMusic(MUSIC_WIND_OF_CHANGE, DURATION_WIND_OF_CHANGE, TEMPO_WIND_OF_CHANGE, SIZE_WIND_OF_CHANGE). А затем в прерывании от таймера длительности вызывать функцию PlayNote(). Если устройству требуется переход в сон, то текущее состояние пьезоизлучателя возвращает функция GetState(), а функцией StopMusic() можно принудительно остановить воспроизведение.

Свой проект я запустил на микроконтроллере STM32, однако библиотека построена так, чтобы не зависеть от производителя железа. Если на вашем микроконтроллере имеется два 16-и битных таймера, причем один из них поддерживает генерацию ШИМ сигнала, то код вам подходит на 80%. Необходимо проверить, что воспроизведение тех или иных нот, а также длительностей нот не приводит к переполнению счета. При частоте тактирования таймера нот 4 МГц и таймера длительности 10 кГц всё должно получиться. Ножку для пьезоизлучателя требуется настроить в режим альтернативной функции. Увеличить громкость можно путем коммутации более высоких напряжений при помощи внешней схемотехники. Мной испробованы несколько мелодий, с которыми библиотека успешно справилась. Вместе с тем допускаю наличие ошибок, дайте знать, если найдете. Файлы библиотеки можно найти по ссылке.

История закончилась тем, что приехал пьезик на телевизионное шоу, выступил, получил одобрение. И все шло хорошо, пока не появился старик Монтана. Вот незадача, снова изобрел велосипед…

Tags:
Hubs:
Total votes 12: ↑10 and ↓2+14
Comments14

Articles