Arduino Трохи пошумимо

можна

Arduino: Трохи пошумимо

У цій гучній статті маестро Нік Вейч перетворює свій Arduino на музичний інструмент, вживаючи слово «налаштування» в буквальному сенсі.

У багатьох проектах Arduino - чи то хоровод світлодіодів, чи контакти РК-екрана - провідну роль відіграє світло. Це дуже мило, але є інші виміри, які ми поки що нехтували: це звук. Поблимати перед кимось світлодіодами - штука хороша, але люди повинні на них спочатку подивитися; краса ж звуку в тому, що його не так легко ігнорувати, в чому скоро переконаються ваші друзі та рідні.

Найпростіший спосіб добути звук-скористатися мікросхемою тонального генератора. Вони дуже дешеві, вимагають мінімуму додаткових компонентів для підключення динаміка і ними легко керувати за допомогою імпульсів з одного з цифрових виходів Arduino. Така схема надто проста, щоб описувати її тут.

Сформувати свій звук набагато складніше. Звук - це лише ударна хвиля, і з відповідним генератором хвиль (наприклад, динаміком) ми отримаємо прості звуки прямо з висновків Arduino. Мало того, при всій нескладності цієї задачі, в Arduino є ще й спеціальна бібліотека, яка про це піклується.

Бібліотека тонів формує прямокутні коливання (тобто "вкл" і "выкл"), маніпулюючи внутрішніми генераторами тактів мікросхеми Atmega. Вона просто задає частоту і спрямовує результат на потрібний висновок. Прямокутні коливання дають грубий і сирий звук, але в цьому є свої плюси. У реальному світі ви навряд чи підключите цю схему до своєї Hi-Fi системи, але вона

чудово підійде на роль дверного дзвінка. Пам'ятаючи про все це, давайте поскоримо класичний опус-«Оду на радість» Бетховена. Так чи інакше, вона нам підходить. Перше, що нам потрібно знати – якзгенерувати звук. Це просто:

tone(pin, pitch, duration);

Обов'язкових аргументів функції tone два: номер виведення (pin) і тон (pitch). Третій, необов'язковий аргумент-тривалість звучання (duration). Номер виводу – звичайний номер контакту Arduino. Тон – це довільно зазначена частота; відтворювати стандартні ноти ви не повинні.

Для вашої зручності, в бібліотеці є заголовний файл із визначеннями нот, тому можна користуватися такими позначеннями:

Обидва варіанти виклику відтворять ту саму ноту [«сіль» середньої октави, - прим. ред.]. Якщо тривалість звучання (ціле число мілісекунд на відтворення ноти) не вказано, то в потрібний момент доведеться зупинити його:

Одночасно можна відтворювати кілька нот; у стандартному Duemiianove Arduino - до трьох, але у більшості випадків на практиці є обмеження у дві ноти. Це пов'язано з тим, що для отримання прямокутної хвилі використовується вбудований генератор тактів, який також забезпечує генерацію ШІМ-сигналів та функцію внутрішнього таймера мілісекунд. Зайнявши його трьома нотами, ви більше не зможете відстежити час, що може стати проблемою. Враховуючи якість звуку, одержуваного з такою схемою, часто досить одного каналу.

Структуру для ноти можна організувати так:

struct note uint16_t pitch; uint8_t тривалість; uint8_t pause; >; note first=; int duration =first.duration*25;

Ми створили просту структуру даних із трьома значеннями. Частота - 16-бітове ціле число (0-65535), а тривалість звучання та пауза - 8-бітові числа (0-255). Два останні значення є скоріше умовними, ніж справжніми. Час потрібно задавати в мілісекундах у діапазоні десь від 50 до 2000. Але якщозберігати ці значення в 16-бітних числах, для зберігання кожної ноти знадобиться на 50% більше місця (шість байт замість чотирьох), і ми сильно роздмухуємо обсяг пам'яті, що потрібно. Так як нам навряд чи потрібно відтворювати ноти з мілісекундною точністю, простіше зберігати в пам'яті менші числа, а при використанні множити їх на коефіцієнт. Якщо множити їх у 25, вийде діапазон від 0 до 6375, тобто. більше шести секунд, і цього має бути цілком достатньо.

Самі ноти теж при бажанні можна вмістити в один байт - якщо ви гратимете музику, то швидше за все по нотах, а не звуками довільної частоти, тому можна обмежитися діапазоном 255 нот (уже цього вистачить!), Який поміститься в одному байті ( ще одне беззнакове 8-бітове ціле число). Зрештою, варто ввести позначення для нот, які ми хочемо відтворювати:

// notes in the melody: enum; static const uint16_t frequency[] = < 784, // GG 880, //A 988, //B 1047, 1175, 1319, 1397, 1568// G >;

Оголошення як статичних констант означає, що значення ніколи не будуть і не зможуть змінитися. Ви можете порахувати це скаредними спробами заощадити місце, але інакше пам'ять розтратиться досить швидко. Нехай наша мелодія не надто довга, але зберігання даних таким чином заощадить до 1 КБ навіть на короткому награші, і це важливо, якщо ви маєте намір зробити у програмі щось ще.

Тепер можна перейти до мелодії. Для стислості ми наведемо лише перший такт «Оди на радість», але в лістингу DVD наведена вся мелодія:

void loop() for (int i = 0; i

Цей код, зрозуміло, варто обернути на свою функцію, а чи не повторювати весь час у головному циклі. Хоча у цих рядках багато чого відбувається, код очевидний.

При ініціалізації циклуми можемо визначити кількість нот, отримавши розмір масиву (в байтах) і розділивши його на три, тому що для кожної ноти використовують три байти.

Висновок можна підключити до готового підсилювача (але спочатку підключіть дільник напруги! Лінійні входи зазвичай використовують напругу 1, а не 5) або зібрати свій власний. Існує безліч схем простих підсилювачів для великих динаміків, а оскільки якість звуку буде не надто гарною, якщо не пропустити його через кілька стадій фільтрації, вибирайте мелодії, що легко впізнаються.

трохи

Мал. 1. Підключення динаміка Arduino. Рекомендується, хоча і не обов'язково, використовувати конденсатор.

пошумимо

Мал. 2. За допомогою простого операційного підсилювача/підсилювача потужності можна підключити схему до більш потужним і гучним динамікам; або підключіть схему до окремого підсилювача через дільник напруги.

У наступному рядку ми відтворюємо ноту за допомогою функції бібліотеки тонів. Ми видаємо її на висновок 7 (він не гірший за будь-яке інше), і це перший аргумент функції. Частоту ноти візьмемо із раніше створеного масиву. Як індекс ми використовуємо значення з переліку, які зберігаються в нашому масиві tune у полі структури pitch. Так, tune[i].pitch містить число від Про до 7 (числами ми позначили ноти для простоти прочитання), яке використовується як індекс масиву, де зберігаються справжні частоти.

Останній потрібний нам параметр – тривалість звучання. Він має бути в мілісекундах, але ми для економії пам'яті ділили значення на 25 і тепер потрібно множити їх на 25.

Пауза між нотами реалізується стандартною функцією delay() , яка аналогічно використовує дані з масиву tune . Щоб гарантовано перервати відтворення, можна було викликатифункцію noTone(7) , але на практиці в цьому немає потреби.

Для відтворення мелодії можна підключити невеликий динамік безпосередньо до висновків Arduino. Але щоб не пошкодити сам динамік, знадобиться невеликий резистор десь у діапазоні від 100 Ом до 1 кОм. Якщо ви використовуєте п'єзоелемент або п'єзодинамік, без резистора можна й обійтися: вони часто мають великий внутрішній опір, розрахований на сигнали логічних рівнів. Формула, яку вам потрібно знати, виглядає так:

Це лише наближення! Динаміки влаштовані складніше, ніж ви думали - вони містять індуктивне навантаження, і у визначенні потужності по відношенню до динаміка є безліч тонкощів. Нам важливо просто його не спалити, тому достатньо і наближеної формули; але потрібні запобіжні заходи. В даному випадку R - резистивне навантаження (опір динаміка має бути зазначено на його задній поверхні - зазвичай це 4,8 або 16 Ом), а V - пікова напруга - у нашому випадку 5 без використання підсилювача потужності. З навантаженням 16 Ом це дасть приблизно 1,5 Вт.

Що станеться під час перевантаження динаміка? П'єзоелемент, якщо не доходити до свавілля, просто видаватиме жахливі звуки, поки не вийде з ладу, але взагалі на диво витривалий. У звичайному динаміці з паперовим конусом і осердям ви або пошкодите сердечник, або розтрусите його на частини, або пошкодите конус - а часто і те, і інше, і третє; тому тут теж потрібно вжити запобіжних заходів. Через спосіб свого виготовлення динаміки загрожують також небезпекою для Arduino.

Крихітний п'єзоелемент не завдасть йому шкоди, але чим більша індуктивність, тим більше шуми стрибків напруги і тим більша потужність ланцюга. Хоча в ланцюгах для керування динаміками за допомогою Arduino, які вам можуть зустрітися, йогозазвичай ні, рекомендується додати конденсатор, що розв'язує, ємністю близько 250 мкФ, підключивши його вихід до «плюсу» динаміка. Він не тільки згладжує перехідні процеси, а й поглинає постійну компоненту сигналу, і осердя переміщатиметься в обох напрямках, як і наказано його природою.

Ми вступаємо на територію аудіоланцюгів, і вона може здатися вам незнайомою, тому що в аудіоланцюзі присутні циклічні напруги, які ріднять їх з ланцюгами змінного, а не постійного струму - тому ми і додали конденсатор, що розв'язує, в нашу головну схему.

Ця поведінка залежить тільки від частоти прикладеної напруги і, зрозуміло, ємності самого конденсатора - якщо вникнути, то чим вище частота, тим більше циклів зарядки і розрядки виконується кожну секунду, і тим більше струм, що проходить через конденсатор. Властивість залежності від частоти називається реактивним опором компонента та визначається за формулою

Цей опір у чомусь аналогічний до звичайного опору резистора в ланцюгах постійного струму. Але оскільки воно залежить від частоти сигналу, що проходить через компонент, то надзвичайно зручно для створення аудіофільтрів.

Простий резистор і конденсатор (RC) можна використовувати як дільник напруги сигналу, що змінює рівень залежно від частоти. Це означає, що сигнали з одними частотами пройдуть через цей ланцюжок без змін, а сигнали з іншими істотно знизяться; що і знадобиться для придушення небажаних сигналів та наведень у нашій системі. Частотний діапазон звуку, що чує людське вухо, нам відомий, і можна відфільтрувати непотрібні коливання, підібравши відповідний конденсатор.

Залежно від резистора та конденсатора можна створити фільтр верхніх частот (тобто відрізати нижнічастоти - таким способом зручно позбавлятися шуму електромережі живлення) або фільтр нижніх частот (з його допомогою зручно відфільтровувати інші перешкоди, такі як шум від генератора тактів), або об'єднати два фільтри і отримати смуговий фільтр.

Ми не надто заглиблюватимемося в теорію звуку, тому що це не тема нашої серії, та й обчислення дуже ускладняться - але ми й не збираємося нею нехтувати. Приєднуйтесь до нас наступного разу для захоплюючої подорожі з генерацією синусоїдальної хвилі зі зсувом частоти для емуляції терменвоксу.

Хоча в нашій мелодії кожна нота описана трьома байтами, можна легко вмістити всі три значення висоти ноти, тривалість звучання та паузи в один байт. В одній мелодії навряд чи буде задіяно більше трьох октав – це 32 значення. Як видно з нашого прикладу, тривалість звучання та пауза також не перевищувала 32 кожна.

Склавши все це разом, ми отримаємо 96 – менше півбайта даних. Складання такої мелодії може вимагати більше зусиль, але вилучення інформації за допомогою бітових масок – не надто складне і не надто довге завдання для процесора, тому така можливість завжди є.

Коли зумер - не зумер

П'єзозумер - стандартний п'єзоелемент, який веде себе дуже схоже на динамік. П'єзо-кристали здійснюють коливання при впливі струму і генерують струм під впливом коливань, тому з них виходять чудові перетворювачі (їх також можна використовувати як датчики

тиску). Раніше зуммери містили якийсь осцилятор для створення власних сигналів. Тепер, навіть незважаючи на те, що іноді їх називають зумерами, багато п'єзоелементів є просто заміною динамікам (тобто вам потрібно подати на них свій сигнал), хоча за своїми звуковимихарактеристикам вони більше підходять для відтворення «виючих» звуків, а не музики - і це одна з причин, через яку аудіолистівки так дратують іменинників! Зібравшись придбати таку, попередньо подбайте прослуховуванням покупки.

можна

В онлайн-посібнику Arduino є прекрасний опис побітових функцій: http://www.arduino.ee/en/Reference/Bitwise.

Сигнали із простої схеми

Осцилографи є не у всіх, тому приклади вихідних сигналів нашої схеми.

можна

Вихід Arduino, якого нічого не підключено. Нульова точка – в середині, і ви бачите акуратні прямі лінії та чіткі перемикання.

arduino

З динаміком, підключеним через низькоомний резистор, сигнал набуває стрибків у точках переходу - вони викликаються осердями динаміка, але не особливо небезпечні при маленькому динаміці.

пошумимо

З розв'язаним виходом низькі значення опускаються нижче за центральну лінію. Ємність також дещо спотворює форму сигналу, але не надто її псує.