Курс arduino – звук

Ардуино: динамик

Курс arduino – звук

На самых первых уроках мы познакомились со светодиодами, которые часто используются в электронике как индикаторы состояния.

Самым простым примером может служить индикатор питания, с помощью которого прибор сообщает пользователю, что он включен. Очень часто вместе со световой индикацией, в устройствах применяется звуковая индикация.

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

Обычно в электронике используются два типа источников звука:

  • громкоговоритель (динамик);
  • звукоизлучатель (зуммер).

В этом уроке мы поговорим о динамике. Разберем подробно его устройство и попробуем проиграть мелодию на Ардуино!

1. Громкоговоритель, он же динамик

Все громкоговорители можно разделить на два подтипа: электродинамический и пьезоэлектрический. Именно от названия первого подтипа пошло хорошо известное нам название динамик.

Наверное каждый из нас хотя бы раз в жизни разбирал какой-нибудь старый динамик. Внутри него обязательно есть постоянный магнит, который прочно склеен с металлическим диском и цилиндрическим якорем по середине.

Кроме магнита в динамике еще есть небольшая электромагнитная (или звуковая) катушка, намотанная тонким лакированным проводом. Катушка приклеена к гофрированному подвесу и к диффузору. Все эти части изображены на схеме разреза динамика.

Человеку, знакомому со школьным курсом физики не составит труда догадаться как работает это устройство. Мы знаем, что если подать на звуковую катушку напряжение, то в её витках возникнет электрический ток (ну это уж совсем очевидно). Согласно закону Ампера, на проводник с током, находящийся в магнитном поле будет действовать сила Ампера.

Направление этой силы можно легко вычислить с помощью правила левой руки: если вектор манитного поля направлен в ладонь, а пальцы направлены по току (вдоль витков провода), то большой палец будет указывать направление силы. Именно сила Ампера то притягивает катушку к основанию якоря, то отталкивает от него, в зависимости от направления электрического тока.

То есть подавая на катушку переменный ток, мы заставим её колебаться. Звуковая катушка прочно соединена с диффузором, так что он тоже начнет колебаться. Движение же большого диффузора приведёт к колебанию большой массы воздуха, что мы и называем звуковой волной!

2. Генератор звука на транзисторах

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

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

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

Принципиальная схема генератора звука на транзисторах

В схеме есть:

  • NPN транзистор 2n2222;
  • PNP транзистор 2n2907;
  • резистор с номиналом от 10 до 100 К;
  • конденсатор 100 нФ.

Внешний вид макета

Собираем сначала схему и в самом конце подключаем к ней батарейку.

В текущем варианте динамик будет издавать пронзительный писк на высокой частоте. Изменить частоту звука можно с помощью конденсатора C1. Если параллельно с C1 подключить еще один или два точно таких же конденсаторов на 100 нФ, частота звука станет ниже.

3. Подключение динамика к Ардуино

Теперь мы знаем как заставить динамик издавать один тон без использования микроконтроллера. Но такой простой генератор может понадобиться разве что сигнального гудка на автомобиле. Нам же больше интересно проигрывать мелодии, речь и разные звуковые сэмплы, с помощью которых робот может общаться с человеком. В этом нам поможет Ардуино.

Подключим динамик к Ардуино по следующей схеме.

Принципиальная схема подключения динамика к Ардуино

Внешний вид макета

4. Программа электронного метронома

Метроном — это устройство, которое задает ритм для музыканта. То есть нам потребуется издавать краткий звук с заданным периодом, скажем в 1 секунду.

Для генерации звука заданной частоты воспользуемся функцией tone, которая имеет следующий формат:

tone( контакт, частота [, длительность] );

  • здесь контакт — номер вывода Ардуино к которому подключён динамик;
  • частота — частота генерируемого звука в герцах;
  • длительность — длительность звука в миллисекундах (параметр необязательный).

Как только мы вызовем функцию tone, Ардуино начнет генерировать импульсный сигнал и будет делать это, пока мы принудительно не выключим генерацию с помощью другой функции — noTone:

noTone( контакт );

Аргумент контакт — это номер вывода Ардуино к которому подключён динамик.

Примечание. Важно учитывать, что Ардуино может одновременно генерировать только один тон на одном контакте. Если вызовем функцию tone для одного контакта, и пока идет генерация попытаемся вызвать tone для другого контакта, то последний вызов будет попросту проигнорирован.

Программа метронома идентична программе для мигания светодиодом, за исключением того, что мы вместо функции digitalWrite применяем tone и noTone.

const byte dynPin = 2; void setup() { pinMode( dynPin, OUTPUT ); // настраиваем контакт №2 на выход } void loop() { tone( dynPin, 100 ); // генерируем звук с частотой 100 Гц delay( 100 ); // пауза 500 миллисекунд noTone( dynPin ); // выключаем звук delay( 900 ); // снова пауза 500 мс }

Загружаем программу на Ардуино и внимаем ритмичному звуку метронома. Следующий пример по-сложнее — будем играть мелодию!

5. Играем ноты на Ардуино

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

const int dynPin = 2; int numTones = 10; // Ноты C,C#,D,D#,E,F,F#,G,G#,A int tones[10] = {261, 277, 294, 311, 330, 349, 370, 392, 415, 440}; void setup(){ pinMode( dynPin, OUTPUT ); } void loop(){ for( int i = 0; i < numTones; i++ ){ tone( dynPin, tones[i] ); delay( 500 ); } noTone( dynPin ); }

Для удобства хранения последовательности нот мы использовали массив tones. В следующем примере мы будем проигрывать десятки нот, и без массива наша программа стала бы через чур громоздкой и непонятной.

6. Мелодия из Звёздных войн на Ардуино

Наконец, попробуем воспроизвести полноценную мелодию из известной всем космической саги.

const byte dynPin = 2; const byte COUNT_NOTES = 39; // частоты нот int tones[COUNT_NOTES] = { 392, 392, 392, 311, 466, 392, 311, 466, 392, 587, 587, 587, 622, 466, 369, 311, 466, 392, 784, 392, 392, 784, 739, 698, 659, 622, 659, 415, 554, 523, 493, 466, 440, 466, 311, 369, 311, 466, 392 }; // длительности нот int durations[COUNT_NOTES] = { 350, 350, 350, 250, 100, 350, 250, 100, 700, 350, 350, 350, 250, 100, 350, 250, 100, 700, 350, 250, 100, 350, 250, 100, 100, 100, 450, 150, 350, 250, 100, 100, 100, 450, 150, 350, 250, 100, 750 }; void setup() { pinMode( dynPin, OUTPUT ); // Настраиваем контакт на выход } void loop() { for (int i = 0; i

Как подключить пьезоизлучатель (пьезопищалку) к Arduino

Курс arduino – звук

Генерировать звуки с помощью Ардуино можно разными способами. Самый простой из них – подключить к плате пьезоизлучатель (или, как его ещё называют, «пьезопищалку»). Но как всегда, есть тут свои нюансы. В общем, давайте подключим к Arduino пьезопищалку и будем разбираться.

  • Компьютер;
  • Arduino;
  • пьезоизлучатель (пьезопищалка).

Пьезоизлучатель, или пьезоэлектрический излучатель, или «пьезопищалка» – это электроакустическое устройство воспроизведения звука, использующие обратный пьезоэлектрический эффект.

Принцип действия его основан на том, что под действием электрического поля возникает механическое движение мембраны, которое и вызывает слышимые нами звуковые волны.

Обычно такие излучатели звука устанавливают в бытовую электронную аппаратуру в качестве звуковых сигнализаторов, в корпуса настольных персональных компьютеров, в телефоны, в игрушки, в громкоговорители и много куда ещё.

Пьезоизлучатель имеет 2 вывода, причём полярность имеет значение. Поэтому чёрный вывод подключаем к земле (GND), а красный – к любому цифровому пину с функцией ШИМ (PWM). В данном примере положительный вывод излучателя подключён к выводу “D3”.

Схема подключения пьезоизлучателя к Arduino и схема, собранная на макетной плате

2 Извлекаем звук из пьезоизлучателяс помощью функции analogWrite()

Пьезопищалку можно задействовать разными способами. Самый простой из них – это использовать функцию analogWrite(). Пример скетча – во врезке. Данный скетч попеременно включает и выключает звук с частотой 1 раз в 2 секунды.

/* Объявляем переменную с номером вывода, к которому подключён пьезоэлемент: */ int soundPin = 3; void setup() { // ставим пин “3” в режим работы “Выход”: pinMode(soundPin, OUTPUT); } void loop() { analogWrite(soundPin, 50); // включаем пьезоизлучатель delay(1000); // на 1000 мс (1 сек), analogWrite(soundPin, 0); // выключаем звук delay(1000); // на 1 сек. }

Задаём номер пина, определяем его как выход. Функция analogWrite() принимает в качестве аргументов номер вывода и уровень, который может быть от 0 до 255, т.к. ШИМ-выводы Ардуино имеют 8-битный ЦАП. Это значение будет изменять громкость пьезопищалки в небольших пределах. Чтобы выключить пьезопищалку, нужно послать в порт значение “0”.

Используя функцию analogWrite(), нельзя изменять тональность звука, к сожалению. Пьезоизлучатель всегда будет звучать на частоте примерно 980 Гц, что соответствует частоте работы выводов с широтно-импульсной модуляцией сигнала (ШИМ) на платах Arduino UNO и подобных.

3 Извлекаем звук из пьезоизлучателяс помощью функции tone()

Но частоту звучания можно менять по-другому. Для этого извлечём звук из пьезоизлучателя посредством встроенной функции tone(). Пример простейшего скетча приведён на врезке.

int soundPin = 3; /* объявляем переменную с номером пина, на который мы подключили пьезоэлемент */ void setup() { pinMode(soundPin, OUTPUT); //объявляем пин 3 как выход. Serial.begin(9600); // будем выводить в порт текущую частоту } void loop() { for (int i=20; i

Образовательная робототехника для всех

Курс arduino – звук

Приступим к изучению языка программирования C# (си шарп). Будем программировать в среде Visual Studio, которую бесплатно можно скачать с сайта Microsoft. У меня установлена версия 2015, но если у вас другая, то все будет работать так же. При запуске вас…
ДАЛЕЕ

Сделаем машинку, управляемую по bluetooth. Для этого нам понадобится приводная платформа, драйвер двигателя (я использую l293d) и bluetooth-модуль (hc-05 или hc-06). Подключение: Также нам понадобится приложение под Android для управления машинкой. Сделаем его в MIT App Inventor. Внешний вид: Ничего…
ДАЛЕЕ

Продолжим краткий обзор работы с stm32 в Arduino IDE. На платах Ардуино обозначено, какие пины можно использовать для считывания аналоговых сигналов, какие генерируют ШИМ и т.д. На blue pill такого нет и мы должны посмотреть распиновку (кликабельно, оригинал: здесь). Можно…
ДАЛЕЕ

Большинство плат Arduino основаны на микроконтроллерах AVR, которые не отличаются высокой производительностью. Есть платы типа Arduino Due, в которой установлен 32-разрядный микроконтроллер, но она значительно дороже Uno, и размером с Arduino Mega. Однако существуют производительные микроконтроллеры stm32, и с ними…
ДАЛЕЕ

Сегодня сделаем необычный музыкальный инструмент, у которого вместо клавиш будут использоваться съедобные продукты. Тут у нас цукат, хлеб, яблоко, пастила, огурец, сыр, колбаса и капуста и их мы превратим в кнопки. За основу взята вот эта статья с сайта instructables….
ДАЛЕЕ

В этой статье я покажу, как подключить светодиодную матрицу 8×8 к Arduino и вывести на нее символы. Вот так выглядит матрица с драйвером max7219: Подключение: Led matrix -> Arduino Vcc -> 5v GND -> GND DIN -> pin 2 CS…
ДАЛЕЕ

Рассмотрим как подключить и использовать данные джойстика, вот такого: Джойстик позволяет посмотреть наклон по осям X и Y, а также определить нажатие. По сути это два потенциометра и кнопка в одном модуле. Модуль имеет 5 контактов: GND +5V VRx VRy…
ДАЛЕЕ

Сделаем простую игру, в которой задачей игрока будет нажать кнопку быстрее соперника. Для этого нам понадобятся: 3 светодиода 3 резистора 220 ом 3 кнопки Игра будет начинаться с того, что один из игроков нажмет кнопку старт (центральная кнопка). Через случайное…
ДАЛЕЕ

Рассмотрим, как можно измерить напряжение аккумулятора и передать полученные данные в Arduino. Для этого будем использовать очень простой аналоговый датчик напряжения, представляющий собой делитель напряжения. Данный модуль позволяет измерять напряжение до 25 вольт. В нем используются резисторы сопротивлением 30 кОм…
ДАЛЕЕ

Рассмотрим работу с четырехразрядным семисегментным индикатором на чипе TM1637. Управляется данный дисплей по I2C, т.е. нам понадобится всего 2 управляющих пина. Распиновка: 1 — CLK 2 — DIO 3 — VCC 4 — GND Подключим дисплей и потенциометр к Ардуино….
ДАЛЕЕ

Простой индикатор уровня звука на WS2812B. Программа для Arduino Pro Mini

Курс arduino – звук

Всем привет ?

В предыдущей статье я показывал как подключить источник аудиосигнала к индикатору уровня звука. Но чтобы индикатор «заиграл», этого недостаточно. Поэтому в этот раз я расскажу о программной части устройства. И чтобы любой мог повторить/модернизировать VU-метр – приложу программный код для Arduino Pro Mini к статье и объясню как он работает. Поехали.

Для более лёгкого представления работы индикатора уровня звука предлагаю ознакомиться с блок-схемой программы:

Заметка: Блог не поддерживает подсветку программного кода, что, конечно же, меня расстроило. Как жить дальше?) На просторах интернета удалось найти решение проблемы.

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

возможно, я что-то делал не так)) В итоге всё без проблем получилось с сервисом Gist от GitHub.

P.S. Первое решение заработало только на третьем блоге, но мне больше понравился сервис Gist))

Теперь, глядя на блок-схему, можно разбираться с самой программой. Первым делом, до зацикливания программы, контроллер нужно настроить. Т.к. я использую среду Arduino не совсем стандартным способом, то необходимо сбросить настройки контроллера, которые среда делает скрытно от пользователя скетча:

Как я уже говорил, нам необходимо 3 канала АЦП: опорный – для измерения постоянной составляющей и два канала для измерения аудиосигналов. Поэтому далее инициализируем АЦП микроконтроллера:

Для улучшения точности измерений частоту работы АЦП уменьшаем до минимально возможной: 125 кГц. Будем использовать все 10 бит, выдаваемых преобразователем. Обратите внимание, что в качестве максимально возможного измеренного значения берётся напряжение с ножки AVCC (аналоговое питание контроллера), а не AREF, как это указано на схеме из предыдущей статьи:

Это сделано для упрощения подключения сигналов к Arduino. Ножка AVCC объединена с VCC, поэтому и подключать её уже не нужно. А ножка AREF в Arduino Pro Mini никуда не выведена, а лишь подключена на общий провод через конденсатор для уменьшения помех во время измерений АЦП.

Для передачи кода цветов на умные светодиоды я захотел использовать аппаратный интерфейс SPI. Как выяснилось, из-за жёстких таймингов прерывать передачу нельзя, а хочется)… хочется в это время получать измеренные значения с АЦП. Поэтому сделано наоборот: передача очередного значения на WS2812B прерывает выполнение основной программы.

Прерывание от SPI разрешается непосредственно перед передачей первого байта и запрещается – после последнего. Очень важно, чтобы после передачи на шине MOSI был логический ноль, иначе светодиоды “запутаются” в принятых данных.

Вопрос: Если не настроить ножку 10 Arduino (аппаратный сигнал CS => PORTB 2) на выход или вход с подтяжкой, то передача по SPI не работает. При программировании контроллеров Atmel в IAR с таким не сталкивался. Возможно у кого-то есть ответ на такое поведение Arduino ?

SPI настраивается на максимальную частоту 8 МГц, равную половине тактовой частоты контроллера. В этом случае 1 бит цвета можно закодировать 1 байтом. И получим скорость передачи 1 Мбит информации о цвете в секунду. Таким образом можно рассчитать время, которое требуется для разовой передачи данных на все светодиоды. Один умный светодиод требует 24 бит – у меня их 64 штуки. Тогда на одну передачу уйдёт времени: 24 бит * 64 / 1 Мбит/с = 1.536 мс.

Эксперименты показали, что времени уходит в 5 с половиной раз больше, а именно 8.5 мс. Всему виной оказались прерывания – очень много времени теряется на вход в подпрограмму обработки прерывания и выход из неё. Это создавало сложности в виде ограничения времени нахождении в прерывании, но их удалось разрешить. Также я исследовал передачу по SPI без прерываний, на неё потребовалось 2.2 мс. Это уже ближе к теории :). “Почему обязательно нужны прерывания?” – спросите Вы. Не нужны, также как и не обязательно использовать SPI. С таким же успехом можно применить UART или просто программно дёргать ножкой. В программе простого VU-метра я даже заложил возможность выбора режима передачи по SPI с прерываниями и без. Это можно сделать с помощью макроса TRANSMISSION_INTERRUPT_DATA. Так что можно поэкспериментировать.

АЦП и SPI настроили – можно измерять сигналы, обрабатывать данные и передавать закодированные цвета на умные светодиоды WS2812B – да, всё верно. Вот только не хватает периодичности передачи – без таймера не обойтись :). Нам хватит 8-битного таймера, например, возьмём второй и настроим:

Снова прерывания. И опять можно обойтись без них, т. к. временная точность не нужна. Но так захотелось, и, возможно, кому-то это пригодится. Таймер после прерывания перезапускается автоматически, поэтому дополнительно что-то настраивать не придётся. Выбранный делитель 1024 даёт возможность настроить периодичность прерывания от 1 до 16 мс. Это задаётся макросом TIME_UPDATE_LEDS. Кстати, период прерывания будет точным, если значение кратно числу 1.6. Это значение нужно выбрать так, чтобы прерывание не вклинилось в передачу по SPI. То есть время должно быть больше времени, затрачиваемого на полную посылку. У нас она занимает 8.5 мс, поэтому выбрано значение 10.0. Необходимо ещё учесть, что перед отправкой данные нужно подготовить, поэтому сделал запас.

Ну что ж, всё настроено, теперь начинается самое интересное – двигаемся дальше :). После подачи питания в контроллеры умных светодиодов может попасть какой-то сигнал – “мусор”. И чтобы мы этого не заметили, после инициализации нужно затушить все светодиоды:

В цикле для каждого из 64-х светодиодов передаётся по 8*3 бита. А так как 1 бит информации о цвете кодируется одним байтом (макросы LOGIC_1 и LOGIC_0), то необходимо передать 8*3 байт для одного светодиода. В качестве полного количества элементов, которое нужно передать на светодиоды использую количество байт цветов. То есть в качестве базиса взят байт цвета, что очень удобно.

Инициализация завершена, можно приступить к основной части программы. Во-первых, это периодическое считывание данных с АЦП для каждого из трёх каналов:

Последовательно по готовности узнаём отсчёты канала опорного напряжения, первого и второго каналов аудиосигнала. Функция возвращает номер канала, значение которого было получено от АЦП.

Во-вторых, если есть измеренные значения, то их можно куда-то сложить, обработать. Этим занимается следующая функция:

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

Этот квадрат кладём в ячейку массива и попутно вычисляем сумму всех значений массива.

Сумма квадратов нам нужна, чтобы потом (когда это будет необходимо) быстро вычислить среднеквадратичное значение, а массив нужен для того, чтобы потом вычитать из суммы неактуальные более значения (что ускорит процесс вычисления) и заполнять его новыми квадратами.

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

Отличие вычислений только в заполненности массива фильтрации и величине значения суммы квадратов. С заполненностью всё ясно – тут просто разный делитель. А что касается функции вычисления квадратного корня, то тут 2 нюанса.

Стандартная функция, которая работает с типом float, требует для себя длительного времени вычисления, поэтому решено было использовать приближённые методы вычисления квадратного корня. Для более быстрого вычисления решил применить 2 функции, оптимизированные под размер значения.

Одна работает только с числами размером до 2-х байт, включительно, а вторая до 4-х байт, включительно. 

В-третьих, необходимо подготовить данные для отправки на светодиоды. Это самая “творческая” функция, потому как от неё зависит в каком виде будет отображаться уровень звука на умных светодиодах. У нас простой VU-метр, поэтому способ отображения только один:

Разберём функцию void set_leds_buf(). Для начала, об этом я писал чуть выше, вычисляется для обоих каналов среднеквадратичное значение, которое говорит о том, сколько светодиодов должно зажечься. Далее, во вспомогательные буферы записываются яркости светодиодов, которые будут светиться.

Яркости берутся из таблицы: user_multicolored_table (по сути двумерный массив). Столбец отвечает за номер светодиода канала, а строка за цвет. Порядок цветов можно задать с помощью макросов COLOR1COLOR2COLOR3.

Сейчас установлен общепринятый порядок: RGB. 

Заметка: Стандартный порядок цветов (то есть последовательность байт, которую нужно передать) у светодиодов WS2812B: GRB. Чтобы не путаться тем, кто использует GRB и тем, кто привык к RGB, решил сделать возможность быстрой смены порядка отправки цветов.

Во время выполнения программы таблица эта хранится в энергонезависимой flash памяти, что экономит ОЗУ и не вызовет никаких проблем, если мы захотим создать много таких цветовых таблиц.

После того как цветовые буферы сформированы, остаётся их объединить в один массив и передать на светодиоды.

И тут я предусмотрел ещё небольшое удобство, и связано оно вот с чем: от того как будут объединяться буферы зависит в каком порядке будут следовать каналы (первый -> второй или второй -> первый) и в каком порядке будут следовать светодиоды в каждом из каналов (в прямом или обратном). Всё это можно задать с помощью макросов: DISPLAY_PRIORITY_CH1 и DISPLAY_PRIORITY_CH2 (порядок отображения каналов), DIRECTION_LEDS_CH1 и DIRECTION_LEDS_CH2 (порядок отображения светодиодов в канале).

Приближаемся к финишу. В-четвёртых, осталось передать сформированные данные. Покажу только вариант с прерыванием по SPI (вариант без использования прерывания отличается незначительно). Он состоит из функции, которая запускает передачу и разрешает прерывание по SPI и непосредственно самого прерывания:

Вот, по большому счёту, вся программа. Ссылку на проект простого индикатора уровня звука на умных светодиодах WS2812B для Arduino Pro Mini со скетчем прилагаю: https://github.com/onikita/Simple-VU-meter.git Для скачивания проекта нужно нажать зелёную кнопку Clone or download и выбрать Download ZIP.

Чтобы запустить проект, необходимо скачанную папку поместить в папку libraries среды Arduino. Проект проверен и работает в Arduino-1.0.6. Также напоминаю: узнать о схеме подключения VU-метра можно в этой статье.

P.S. Мы разобрали программу простого индикатора уровня – без “излишеств”.

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

 Например, у нас получился такой индикатор уровня:

С уважением, Никита О.

Оцените статью
Просто о технологиях
Добавить комментарии

;-) :| :x :twisted: :smile: :shock: :sad: :roll: :razz: :oops: :o :mrgreen: :lol: :idea: :grin: :evil: :cry: :cool: :arrow: :???: :?: :!: