Для синтезу складних звукових ефектів є багато недорогих модулів, які легко інтегрувати з Arduino. Включно з модулями, які можуть відтворювати MP3 файли із внутрішньої пам'яті або micro-SD карт.
В нас поки нічого такого нема. Але завжди можна знайти якийсь вихід.
Із старої зламаної китайської іграшки добули пищалку - думаю в кожній хаті, де є діти, таких знайдеться пару штук
До провідників припаяли шматки дроту від використаних бенгальських вогнів. Тепер їх стало зручно комутувати до виходів Arduino або до макетної плати. Треба буде ще їх зафіксувати шматками трубки-термоусадки..
Справа застопорилася на програмній частині. Сам по собі Arduino не вміє генерувати звуки (ну тобто красиві сигнали у вигляді синусоїд, які мають частоти чутні людським вухом). Тому для генерування звуку використовують побічний ефект Широтно-Імпульсної Модуляції (ШІМ або PWM) яку використовують для симулювання різних рівнів напруги на виходах Arduino.
Ідея ШІМ в тому, щоб замість будування складних схем для пониження напруги, просто зменшується час, протягом якого подаються 5-вольтові імпульси. Якщо треба видати всі 5 вольт - подається безконечно широкий імпульс. Якщо треба подати напругу схожу на 4 вольта - 4/5 часу подається напруга 5 вольт, а решту - 0 вольт. Для створення напруги схожої на 2.5 вольт, ширина 5-вольтового імпульсу становить 50% часу періоду.
Таким чином, подаючи на вихід за допомогою analogWrite() сигнал різного рівня, можна генерувати коливання напруги, які при потраплянні на пищалку даватимуть звук. Цей звук буде дещо одноманітним, з досить металічним тембром, але ж в тому і є суть роботівського голосу!
В комплекті з Arduino надається бібліотека Tone, яка дозволяє дуже простим способом подавати на вихід звуковий сигнал певної частоти. Для цього достатньо написати таку команду:
tone(<номер PWM виходу>, <частота ноти>)Наприклад:
tone(9, 440) ; // пищати ля першої октави на виході 9Пищалку слід одним контактом підключити до виходу 9, а іншим - на землю (GND).
З використанням бібліотеки Tone є дві проблеми:
- Використання нот не дуже добре годиться для синтезування роботського пищання. Доведеться виписувати великі масиви нот дуже короткої тривалості.
- Використання бібліотеки псує роботу PWM на виходах 3 та 11. Як саме - в документації не сказано.
Блукання Інтернетом привело мене до ось цієї теми "Звуки R2D2 на Ардуіно (рос.)". Дописувачі створили просто суперову бібліотеку для генерування R2D2-подібних звуків. Зі всіх десятків вже готових варіантів, ми скомпілювали для нашого робота кілька звуків, які він має видавати в різних ситуаціях.
- Привітання
- Згода
- Питання
- Переляк
Як це звучить вживу:
Ядро бібліотеки дуже компактне і базується лише на двох функціях - тому ми ті функції просто перенесли у свій код. Текст пробної програмки подаю нижче. Пищіть собі на здоров'я.
// запам'ятовуємо номер виходу, до якого підключений динамік int voicePin = 9; void setup() { pinMode(voicePin, OUTPUT); // Привіт playTone(1600,100); playTone(2600,24); playTone(1900,92); delay(4); playFreqGlissando(2500, 3600, 1, 1900); playFreqGlissando(3600, 4200, 1, 1900); playFreqGlissando(4200, 3600, 1, 1900); playFreqGlissando(3600, 1900, 1, 1900); playFreqGlissando(550, 750, 1, 500); playFreqGlissando(750, 1200, 1, 500); playFreqGlissando(1200, 2000, 1, 500); playFreqGlissando(2000, 2100, 1, 300); delay(32); playTone(2350,36); playFreqGlissando(2350, 1600, 1, 500); delay(1000); // OK playFreqGlissando(2300, 1900, 1, 1100); delay(28); playFreqGlissando(1800, 1700, 1, 1000); delay(36); playFreqGlissando(2000, 2200, 1, 1100); delay(1000); // Питання playTone(2400,40); playTone(1000,32); delay(28); playFreqGlissando(1700, 2400, 1, 1000); playTone(2400,32); delay(28); playFreqGlissando(2200, 1700, 1, 800); playTone(1700,24); delay(28); playFreqGlissando(1900, 2700, 1, 800); playTone(2700,21); delay(28); playFreqGlissando(2200, 1700, 1, 800); playTone(1700,24); delay(28); playFreqGlissando(1900, 2700, 1, 800); playTone(2700,21); delay(1000); // Переляк playFreqGlissando(400, 550, 1, 14000); playFreqGlissando(550, 400, 1, 1200); playTone(2400,36); playFreqGlissando(1800, 2400, 1, 700); playTone(2400,36); delay(32); playFreqGlissando(2200, 1800, 1, 700); playFreqGlissando(1800, 1750, 1, 900); playTone(2350,36); playFreqGlissando(2350, 1200, 1, 700); delay(32); playFreqGlissando(700, 600, 1, 300); playFreqGlissando(600, 750, 1, 900); } void playTone(unsigned int toneFrequency, byte beats) { int tone = (1000000 / toneFrequency)/2; //recalculate frequency to pause value between pulses for (long i = 0; i < beats * 1000L; i += tone * 2) { digitalWrite(voicePin, HIGH); delayMicroseconds(tone); digitalWrite(voicePin, LOW); delayMicroseconds(tone); } } void playFreqGlissando( float freqFrom, float freqTo, float duty, float duration ) { duration=duration/8*3; int stepLength = 20; //30 int i, numberOfSteps; float freqStep, freq; numberOfSteps = duration/stepLength; freqStep = (freqTo - freqFrom)/numberOfSteps; freq = freqFrom; for ( i=0; i < numberOfSteps; i++ ) { //summer.playTone(freq, stepLength); playTone(freq, duty); freq = freq + freqStep ; } playTone(freqTo, stepLength); } void loop() { }
Немає коментарів:
Дописати коментар