Переключать ноты будем так же, как в предьщущем примере с цветным светодиодом, - по нажатию кнопки. Задаем базовые частоты для каждой ноты и переключаем их каждый раз при нажатии кнопки.
12.5.1. Схема музыкального инструмента
Аппаратная часть проекта очень простая. К схеме предыдущего примера с RGB-светодиодом добавляем динамик, подключенный к контакту 12 Arduino через резистор 150 Ом. Я взял пьезоизлучатель, вы можете выбрать другой динамик. Монтажная схема показана на рис. 12.9.
12.5.2. Программа для музыкального инструмента
Программа для музыкального инструмента использует аппаратные прерывания и прерывания по таймеру, а также функцию tone() для управления динамиком и осуществляет передачу данных в последовательный порт. Загрузите код из листинга 12.3 на плату Arduino и нажимайте кнопку для перебора базовых частот. Посмотреть частоту, воспроизводимую в текущий момент, можно в мониторе последовательного порта.
Листинг 12.3. Код для музыкального инструмента - fun_with_sound.ino
// Использование аппаратных прерываний и прерываний по таймеру
// Подключение библиотеки TimerOne
#include
//
const int BUTTON INT =0; // Прерывание 0 (вывод 2 для Uno)
const int SPEAKER=12;
// Вывод 12 для подключения динамика
- 267 -
Рис. 12.9. Графическая схема музыкального аппарата
// Базовые частоты для нот
#define NOTE_C 65
#define NOTE_D 73
#define NOTE_E 82
#define NOTE_F 87
#define NOTE_G 98
#define NOTE_A 110
#define NOTE_B 123
// Переменные volatile для изменения при обработке прерываний
volatile int key = NOTE_C;
volatile int octave_multiplier = 1;
void setup()
{
// Запуск последовательного порта
Serial.begin(9600);
pinMode (SPEAKER, OUTPUT);
// Запуск для кнопки аппаратного прерывания по RISING
attachInterrupt(BUTTON_INT, changeKey, RISING);
//Set up timer interrupt
Timer1.initialize(500000);
// Период 0,5 секунды
- 268 -
Timer1.attachInterrupt(changePitch); // Выполнять changePitch()
// при прерываниях по таймеру
void changeKey()
{
octave_multiplier=1;
if (key == NOTE_C)
key = NOTE_D;
else if (key == NOTE_D)
key = NOTE_E;
else if (key == NOTE_E)
key = NOTE_F;
else if (key == NOTE_F)
key = NOTE G;
else if (key == NOTE_G)
key = NOTE_A;
else if (key == NOTE_A)
key = NOTE_B;
else if (key == NOTE_B)
key = NOTE_C;
}
// Обработка прерывания по таймеру
void changePitch()
{
octave_multiplier = octave_multiplier * 2;
if (octave_multiplier > 16) octave_multiplier
tone(SPEAKER,key*octave_multiplier);
}
void loop()
{
Serial.print ("Кеу: ");
Serial.print(key);
Serial.print(" Multiplier: ");
Serial.print(octave_multiplier);
Serial.print(" Frequency: ");
Serial.println(key*octave_multiplier);
delay(100);
}
Значения частот для нот можно найти в Интернете. Базовые частоты определены для нот второй октавы. Обратите внимание, что переменные key и octave_multiplier должны быть объявлены как volatile, потому что их значения меняются во время обработки прерываний. Функция changeKey() вызывается каждый раз при срабатывании прерывания по нажатию кнопки и изменяет базовое значение пере
- 269 -
менной key. Функция changePitch() вызывает tone() для установки частоты сигнала для динамика. Она запускается каждые полсекунды по прерыванию таймера.
При каждом вызове она удваивает базовую частоту, пока не будет достигнуто ее 16-кратное увеличение. Затем процесс повторяется с начальной базовой частоты.
В цикле loop() в последовательный монитор каждые 0, 1 с выводятся значения переменных key, octave_multiplier и частоты.
ПРИМЕЧАНИЕ
Посмотреть видеоклип, демонстрирующий работу музыкального инструмента, можно на странице www.exploringarduino.com/content/ch12. Этот видеофайл доступен и на странице издательства Wiley.
Резюме
В этой главе вы узнали следующее:
• Как выбрать альтернативу: опрос входов в цикле или использование прерываний.
• Что реализация прерываний на различных платах Arduino неодинакова. На плате Due прерывания можно задать для любого контакта, на других платах для прерываний доступны только определенные контакты.
• Как создать противодребезговую защиту кнопок на аппаратном уровне с помощью RC-цепочки и триггера Шмитта.
• Что с помощью функций обработки прерываний можно асинхронно опрашивать входы Arduino.
• Как с помощью сторонней библиотеки TimerOne организовать прерывания по таймеру.
• Как комбинировать прерывания таймера, аппаратные прерывания и опрос в одной программе, чтобы параллельно выполнять несколько задач.
Глава 13. Обмен данными с картами памяти SD
Список деталей
Для повторения примеров главы вам понадобятся следующие детали:
• плата Arduino (рекомендуется Uno );
• USB-кабель для программирования платы Arduino;
Читать дальше