Опубликовано

Генерирование несколько тонов одновременно с помощью Arduino

По материалам главы 9 («Работа со звуком») книги “Arduino. Большая книга рецептов, 3-е изд.” (авторы Джепсон Брайан, Марголис Майкл, Уэлдин Николас Роберт).

Arduino. Большая книга рецептов, 3-издание

ЗАДАЧА

Требуется генерировать одновременно два звука. Библиотека Tone среды Arduino IDE поддерживает воспроизведение только одного тона на стандартных платах, но мы хотим создавать одновременно два тона. При этом следует отметить, что плата Mega оснащена большим количеством таймеров и способна воспроизводить до шести тонов одновременно.

РЕШЕНИЕ

Возможности библиотеки Tone среды Arduino IDE ограничены одновременным воспроизведением лишь одного тона. Это объясняется тем, что для каждого тона требуется использовать отдельный таймер, и хотя стандартная плата Arduino оснащена тремя таймерами, один из них занят функцией millis(), а еще один требуется для работы с сервомашинками. Чтобы решить эту проблему, здесь применена библиотека Tone с расширенными возможностями разработки Бретта Хагмана (Brett Hagman), который также является и разработчиком функции tone(). Его библиотека позволяет генерировать одновременно несколько тонов. Библиотеку можно загрузить с ее веб-страницы Github (https://github.com/bhagman/Tone) или же просто установить с помощью Менеджера библиотек.

В листинге 9.4 приводится код скетча, который проигрывает часть мелодии «Twinkle, Twinkle Little Star» с теми же самыми нотами, но в двух октавах.

Листинг 9.4. Скетч для воспроизведения нескольких тонов одновременно на стандартной плате Arduino

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
/*
* Скетч Dual Tones
* Проигрывает фрагмент мелодии "Twinkle, Twinkle Little Star" в двух октавах
*/
 
#include <Tone.h>
int notes1[] = {NOTE_C3, NOTE_C3, NOTE_G3, NOTE_G3, NOTE_A4, NOTE_A4,
NOTE_G3, NOTE_F3, NOTE_F3, NOTE_E3, NOTE_E3, NOTE_D3,
NOTE_D3, NOTE_C3 };
int notes2[] = {NOTE_C3, NOTE_C3, NOTE_G3, NOTE_G3, NOTE_A4, NOTE_A4,
NOTE_G3, NOTE_F3, NOTE_F3, NOTE_E3, NOTE_E3, NOTE_D3,
NOTE_D3, NOTE_C3 };
const byte scoreLen = sizeof(notes1)/sizeof(notes1[0]); // Количество нот
// Тоны можно объявить в виде массива
Tone notePlayer[2];
 
void setup(void)
{
notePlayer[0].begin(11);
notePlayer[1].begin(12);
}
 
void loop(void)
{
for (int i = 0; i < scoreLen; i++)
{
notePlayer[0].play(notes1[i]);
delay(100); // Небольшая пауза перед проигрыванием следующей ноты
notePlayer[1].play(notes2[i]);
delay(400);
notePlayer[0].stop();
notePlayer[1].stop();
delay(30);
}
delay(1000);
}

Обсуждение работы решения и возможных проблем

Чтобы смешать два выходных сигнала разной частоты на одном динамике, сигналы с выходных контактов платы Arduino подаются на один из контактов динамика через резисторы номиналом 500 Ом. Второй контакт динамика подключается на «землю» (контакт GND платы Arduino), как показано на схемах для предыдущих решений (например, на рис. 9.3).

Подключение динамика для воспроизведения тонов разной частоты и длительности

Рис. 9.3. Подключение динамика для воспроизведения тонов разной частоты и длительности

На стандартных платах Arduino для генерирования первого тона задействуется таймер 2 (в результате чего подача ШИМ-сигнала на контакты 9 и 10 платы будет невозможна), а для генерирования второго сигнала — таймер 1 (что делает невозможным использование библиотеки Servo, а также подачу ШИМ-сигнала на контакты 11 и 12). На платах Mega для каждого тона используется отдельный таймер
в следующем порядке: 2, 3, 4, 5, 1, 0. На момент подготовки книги эта библиотека поддерживает возможности, реализуемые архитектурой AVR, и не поддерживается платами с микроконтроллерами ARM и платами MegaAVR — такими как платы Arduino Uno WiFi R2 и Nano Every.

При проигрывании двух нот одной частоты или одной и той же ноты, но двух разных октав, может наблюдаться эффект биения (или пульсации), похожий на эффект тремоло (амплитудного вибрато). Причиной биения является не совсем идеальная синхронизация двух каналов. Этот эффект используют при ручной настройке струн гитары — биение прекращается, когда струна настроена на эталонную ноту.

Хотя на плате Arduino возможно одновременно воспроизводить три тона, а на плате Mega — более чем шесть, это создает проблемы для нормальной работы функций delay() и millis(). Поэтому для надежности рекомендуется одновременно воспроизводить только два тона на плате Arduino или пять на плате Mega.
Добавить комментарий