[155] Arduino Hi-Fi

Czy jest możliwe, by bardzo prosty – jak na dzisiejsze standardy – ośmiobitowy mikrokontroler klasy ATmega328, któremu w zasadzie bliżej do Z80 z lat siedemdziesiątych, niż do tego, co siedzi w smartfonach, mógł odtwarzać muzykę z kart SD i to z jakością więcej niż przyzwoitą? I tak, i nie. Nie – jeśli byśmy chcieli napisać całą obsługę tego procederu sami, bez wstawek asemblerowych. Tak – bo zdolni ludzie zrobili to za nas i takie rozwiązanie dziś właśnie opiszę.


Na początek wiadomość zła i dobra. Arduino Uno i pochodne nie mają przetworników cyfrowo-analogowych, więc teoretycznie żadnego audio nie może tu być bez podłączenia przetworników zewnętrznych. Ale możemy tutaj znaleźć sześć wyjść PWM, które – o czym już pisałem niejeden raz – autonomicznie generują przebieg o ustalonej częstotliwości, ale o zmiennym wypełnieniu. Po scałkowaniu takiego sygnału, czy to filtrem dolnoprzepustowym, czy samym odbiornikiem (żarówką, głośnikiem itd.), może się okazać, że oczekiwane rezultaty będą satysfakcjonujące.

To działa świetnie w przypadku diod świecących, gdzie elementem całkującym są nasze oczy, widzące powyżej pewnej częstotliwości sterującej jedynie różne poziomy świecenia, a nie mruganie. W przypadku silników także to działa dobrze. I tutaj całkowanie zapewniała bezwładność samego silnika, co najwyżej brzęczącego cicho do taktu częstotliwości pracy wyjścia PWM. A czy da się taką sztukę zrobić z dźwiękiem, skoro wymienione doświadczenia z silnikami dostarczały nam zakłócających pisków?

Owszem, pod jednym warunkiem: częstotliwość pracy generatora musi znajdować się dużo wyżej od podwójnej wartości najwyższej częstotliwości, którą chcemy odtworzyć. A najlepiej daleko w ultradźwiękach, żeby wszelkie zakłócenia brzęczały sobie tam, gdzie i tak ich nie usłyszymy. Z tego wynika, że częstotliwość pracy przetworników musi wynosić co najmniej 40 kHz. Jak się to ma do wartości 490 Hz, która jest typową częstotliwością PWM w Arduino?

Otóż nie jest to jedyna dostępna wartość. Dla każdego z trzech timerów, które sterują przetwornikami, mamy kilka ustalonych częstotliwości i na szczęście znajdziemy tam jedną z pasma ultradźwięków, równą 62,5 kHz. Zatem przynajmniej teoretycznie – da się zrealizować przetwornik cyfrowo analogowy do zadań audio, z wykorzystaniem wyjść PWM w Arduino Uno R3.

Czas na drugą wiadomość złą i dobrą. Pamięć pokładowa to 32 kB. Przy czym musi się tam zmieścić jeszcze program. To śmiesznie mała ilość, jeśli przechowywać w niej sample, aczkolwiek da się i przykład całkiem praktycznego rozwiązania przedstawiałem niedawno. Zatem do mówienia „dzień dobry” urządzenie nadaje się już i na tym etapie moglibyśmy opowieść zakończyć. Zapewne jednak każdy chciałby słuchać własnego „dzień dobry”, a nie mojego. Nic prostszego: należy na kartę wrzucić własne nagranie. Ale nie tak hop-siup.

I tutaj mamy drugie ograniczenie, związane z częstotliwością wyjścia PWM. Jak mówiłem, pracuje ono z szybkością 62,5 kHz i taką właśnie częstotliwość próbkowania winny mieć pliki wrzucane na kartę. Mało tego, powinny być to pliki ośmiobitowe w standardzie bezznakowym i pozbawione nagłówka. Zatem popularne WAV-y czy empetrójki należy przekonwertować do takiego formatu. Źródła biblioteki opisują metody takiej konwersji i można z nich skorzystać, ale ja za chwilę zaproponuję coś lepszego. Bo skoro już wszystko gra, przyszedł czas na analizę jakości owego grania.

Wśród załączników przygotowałem kilka testów. Są to kompilacje tak często prezentowane przeze mnie w filmach na moim kanale o różnych urządzeniach audio. Pierwszym z nich będzie 8bit.asf, który jest właśnie przekonwertowanym – zgodnie z zaleceniem autora biblioteki – plikiem testowym. Ach, bo nie wspomniałem: przełączymy teraz pracę w tryb stereo, wyciskając ostatnie poty z małego Arduino. Zatem należy także odłączyć głośnik i podłączyć wyjście 9 i 10 do wzmacniacza, na wejście liniowe, dla bezpieczeństwa najlepiej przez rezystor 1k.

#include <SimpleSDAudio.h>  // Biblioteka odtwarzania sampli z karty SD.

void setup() {
  SdPlay.init(SSDA_MODE_FULLRATE | SSDA_MODE_STEREO | SSDA_MODE_AUTOWORKER);  // Inicjalizacja biblioteki.
  SdPlay.setFile("8bit.afs");                                                 // Pobierz plik "8bit.afm"
  SdPlay.play();                                                              // Odtwórz go.
}
void loop() {}

Program nie różni się niczym od tego, co prezentowałem w poprzednim artykule, z jedną jednak różnicą: wymuszamy pracę stereo. Po skompilowaniu programu i oczywiście wrzuceniu pliku na kartę powinniśmy usłyszeć mniej więcej to, co możemy pod nazwą 8bit.mp3 znaleźć wśród załączników.

Niestety, to jest plik ośmiobitowy i słychać całe dobrodziejstwo ubogiej rozdzielczości. W każdym, nieco cichszym miejscu, coś tam namolnie trzeszczy, a gdy głośność spada poniżej pewnego poziomu nagle robi się głucha cisza. I teoretycznie tutaj byśmy sprawę mogli zamknąć jako nierozwiązywalną. Na szczęście rozwiązanie autora biblioteki przewiduje pracę szesnastobitową, ale w mono bądź z połową częstotliwości, co niestety miałoby wpływ na utratę wysokich tonów.

I teraz wjeżdża, cała na biało, fizyka, a w zasadzie psychoakustyka, z bohaterem o nazwie dithering. O zjawisku napisano tomy, w uproszczeniu polega na dodaniu szumu o bardzo niskim poziomie, który maskuje zniekształcenia harmoniczne i wszelkie błędy kwantyzacji, na przykład te, które było wyraźnie słychać na przegwiździe. A będzie jeszcze lepiej, gdy użyjemy dodatkowej metody, tak zwanego kształtowania szumu, która to ów dodany szum w większości wrzuci – no właśnie, mając tak wysoką częstotliwość próbkowania – poza zakres słyszalny, czyli w ultradźwięki.

Jednak sprawna kontrola tego zjawiska jest możliwa tylko w bardziej zaawansowanych programach do obróbki dźwięku. Użyłem wspomnianego już programu Adobe Audition, w którym można sobie włączyć ową opcję z wieloma różnymi funkcjami. Plik nazwałem stereo.afs i tym będziemy się teraz bawić. Zatem kompilujemy i… możemy od razu posłuchać płytki z Arduino albo wersji zgranej do załącznika o nazwie stereo.mp3. To naprawdę dalej jest osiem bitów? Brzmi świetnie! Choć trochę szumi, zupełnie jak magnetofon. W paśmie do 18 kHz mamy tutaj dynamikę około 45 dB. Zważywszy, że to szum, który nie robi uszom takiej krzywdy, jest dobrze. Ale o czymś zapomniałem.

Spójrzmy na widmo: powyżej 20 kHz mamy stały, spory poziom szumów, który robi dla nas dobrą robotę, ale zarazem także wpada na wejście wzmacniacza, a tego już robić nie powinien. Zatem należy sprzętowo ograniczyć pasmo. Najprościej – wsadzając dwa ceramiczne kondensatory 10 bądź 22 nF. Ambitniej należałoby zrobić porządne filtry albo ukraść te z lepszych radioodbiorników, blokujących sygnał MPX. Często są to filtry wyższego rzędu, wykorzystujące cewki i poradziłyby sobie tutaj znakomicie. Ograniczyłem się jednak do filtrów najprostszych, które niestety obcinają nieco pasmo słyszalne. Dlatego już po nagraniu wyrównałem charakterystykę, ale bez podbijania dźwięków wyższych niż 20 kHz. Po takich zabiegach całość zabrzmi świetnie. Dynamika do 18 kHz sięgnie 52 dB i żadnych świerszczy tutaj słychać nie będzie. Oczywiście nie jest to tak doskonałe jak prawdziwe 16 bitów ze współczesnych przetworników audio, ale w zasadzie do wszystkich zadań stawianych przed Arduino wystarczy. Trzeba też pamiętać, ze przetworniki cyfrowo – analogowe zrealizowane w ten sposób mają cyfrową liniowość, na pewno lepszą niż wszelkie drabinki rezystorów i tego typu rozwiązania tanie.

W kolejnym artykule zbudujemy sobie coś praktycznego… a, nie będę zdradzał, niech to będzie niespodzianką :)

Płytka edukacyjna TME-EDU-ARD-2Płytka edukacyjna TME-EDU-ARD-2

Inne artykuły z tej kategorii

Nasi partnerzy

TMETech Master EventTME EducationPoweredby
Copyright © 2026 arduino.pl