Spisu treści:

Bluetooth Audio i cyfrowe przetwarzanie sygnału: struktura Arduino: 10 kroków
Bluetooth Audio i cyfrowe przetwarzanie sygnału: struktura Arduino: 10 kroków

Wideo: Bluetooth Audio i cyfrowe przetwarzanie sygnału: struktura Arduino: 10 kroków

Wideo: Bluetooth Audio i cyfrowe przetwarzanie sygnału: struktura Arduino: 10 kroków
Wideo: Jak działa DAC? Jak stworzyć Centrum Cyfrowej Muzyki za pomocą DAC? Podpowiada Konrad Siemientkowski 2024, Listopad
Anonim
Image
Image
Bluetooth Audio i cyfrowe przetwarzanie sygnału: platforma Arduino
Bluetooth Audio i cyfrowe przetwarzanie sygnału: platforma Arduino

Streszczenie

Kiedy myślę o Bluetooth, myślę o muzyce, ale niestety większość mikrokontrolerów nie może odtwarzać muzyki przez Bluetooth. Raspberry Pi może, ale to jest komputer. Chcę opracować platformę opartą na Arduino dla mikrokontrolerów do odtwarzania dźwięku przez Bluetooth. Aby w pełni naprężyć mięśnie mojego mikrokontrolera, zamierzam dodać do dźwięku cyfrowe przetwarzanie sygnału (DSP) w czasie rzeczywistym (filtrowanie górnoprzepustowe, filtrowanie dolnoprzepustowe i kompresję zakresu dynamiki). Wisienką na torcie dodam serwer sieciowy, który można wykorzystać do bezprzewodowej konfiguracji DSP. Osadzone wideo pokazuje podstawy dźwięku Bluetooth w akcji. Pokazuje również, jak używam serwera WWW do filtrowania górnoprzepustowego, dolnoprzepustowego i kompresji zakresu dynamicznego. Pierwsze użycie kompresji zakresu dynamiki celowo powoduje zniekształcenia jako przykład złego wyboru parametrów. Drugi przykład eliminuje to zniekształcenie.

W przypadku tego projektu mikrokontrolerem z wyboru jest ESP32. Kosztuje mniej niż 10 funtów i jest wyposażony w przetworniki ADC, DAC, Wi-Fi, Bluetooth Low Energy, Bluetooth Classic i dwurdzeniowy procesor 240 MHz. Wbudowany przetwornik cyfrowo-analogowy może technicznie odtwarzać dźwięk, ale nie będzie brzmiał świetnie. Zamiast tego użyję dekodera stereo Adafruit I2S do wytworzenia sygnału wyjścia liniowego. Ten sygnał można łatwo wysłać do dowolnego systemu HiFi, aby natychmiast dodać bezprzewodowy dźwięk do istniejącego systemu HiFi.

Kieszonkowe dzieci

Miejmy nadzieję, że większość producentów będzie miała płytki stykowe, zworki, kable USB, lutownice zasilające i będzie musiała wydać tylko 15 funtów na ESP32 i dekoder stereo. Jeśli nie, wszystkie wymagane części są wymienione poniżej.

  • ESP32 - testowany na ESP32-PICO-KIT i TinyPico - 9,50 £ / 24 £
  • Dekoder stereo Adafruit I2S - 5,51 £
  • Deska do krojenia chleba - £3-£5 za sztukę
  • Przewody połączeniowe - £3
  • Słuchawki przewodowe/system Hi-Fi - £££
  • Nagłówki wciskane lub lutownica - 2,10 £ / 30 £
  • Kabel micro USB - 2,10 £ / 3 £
  • Złącze 3,5 mm do RCA / gniazdo 3,5 mm do gniazda (lub cokolwiek, czego potrzebuje twój głośnik) - 2,40 GBP / 1,50 GBP
  • Zasilacz USB - £5

Krok 1: Budowa - tablica do krojenia chleba

Budowa - deska do krojenia chleba
Budowa - deska do krojenia chleba

Jeśli kupiłeś ESP32-PICO-KIT, nie będziesz musiał lutować żadnych pinów, ponieważ jest fabrycznie wlutowany. Po prostu umieść go na płytce stykowej.

Krok 2: Budowa - nagłówki wciskane/lutowanie

Budowa - Nagłówki Push/lutowanie
Budowa - Nagłówki Push/lutowanie
Budowa - Nagłówki Push/lutowanie
Budowa - Nagłówki Push/lutowanie

Jeśli masz lutownicę, przylutuj piny do dekodera stereo zgodnie z instrukcją na stronie Adafruit. W momencie pisania tego tekstu moja lutownica była w pracy, która była zablokowana. Nie chciałem płacić za tymczasową lutownicę, więc wyciąłem kilka nagłówków pchających z pimoroni. Pociąłem je, żeby pasowały do dekodera stereo. Nie jest to najlepsze rozwiązanie (i nie sposób, w jaki miały być używane nagłówki), ale jest to najtańsza alternatywa dla lutownicy. Wsuń pocięty nagłówek do płytki stykowej. Powinieneś potrzebować tylko 1 linii 6 pinów do dekodera. Możesz dodać kolejne sześć po drugiej stronie, aby uzyskać stabilność, ale nie jest to konieczne w przypadku tego prototypowego systemu. Piny, w które można włożyć nagłówki, to vin, 3vo, gnd, wsel, din i bclk.

Krok 3: Budowa - okablowanie pinów zasilania

Budowa - okablowanie pinów zasilania
Budowa - okablowanie pinów zasilania

Umieść dekoder stereo na złączach wciskanych (piny vin, 3vo, gnd, wsel, din i bclk) i mocno je dociśnij. Ponownie, najlepiej byłoby to zrobić za pomocą lutownicy, ale musiałem improwizować. Zauważysz, że wszystkie przewody w tej instrukcji są niebieskie. To dlatego, że nie miałem żadnych zworek, więc pociąłem 1 długi przewód na mniejsze kawałki. Poza tym jestem daltonistą i nie dbam o kolor drutu. Piny zasilania są przymocowane w następujący sposób:

3v3 (ESP32) -> do vin na dekoderze stereo

gnd (ESP32) -> do gnd na dekoderze stereo

Krok 4: Budowa - okablowanie I2S

Budowa - Okablowanie I2S
Budowa - Okablowanie I2S

Aby przesłać dźwięk Bluetooth z ESP32 do dekodera stereo, użyjemy metody komunikacji cyfrowej zwanej I2S. Dekoder stereo weźmie ten sygnał cyfrowy i zamieni go w sygnał analogowy, który można podłączyć do głośnika lub HiFi. I2S wymaga tylko 3 przewodów i jest dość prosty do zrozumienia. Linia zegara bitowego (bclk) zmienia się na wysoki i niski, aby wskazać, że przesyłany jest nowy bit. Linia wyjścia danych (dout) staje się wysoka lub niska, aby wskazać, czy ten bit ma wartość 0 czy 1, a linia wyboru słowa (wsel) staje się wysoka lub niska, aby wskazać, czy transmitowany jest lewy czy prawy kanał. Nie każdy mikrokontroler obsługuje I2S, ale ESP32 ma 2 linie I2S. To sprawia, że jest to oczywisty wybór dla tego projektu.

Okablowanie wygląda następująco:

27 (ESP32) -> wsel (dekoder stereo)

25 (ESP32) -> din (dekoder stereo)

26 (ESP32) -> bclk (dekoder stereo)

Krok 5: Instalacja biblioteki BtAudio

Instalowanie biblioteki BtAudio
Instalowanie biblioteki BtAudio
Instalowanie biblioteki BtAudio
Instalowanie biblioteki BtAudio

Jeśli nie masz ich jeszcze zainstalowanych, zainstaluj Arduino IDE i rdzeń Arduino dla ESP32. Po ich zainstalowaniu odwiedź moją stronę Github i pobierz repozytorium. W Arduino IDE w Sketch>>Include Library>> wybierz „Dodaj bibliotekę. ZIP”. Następnie wybierz pobrany plik zip. To powinno dodać moją bibliotekę btAudio do twoich bibliotek Arduino. Aby skorzystać z biblioteki, musisz dołączyć odpowiedni nagłówek w szkicu Arduino. Zobaczysz to w następnym kroku.

Krok 6: Korzystanie z biblioteki BtAudio

Korzystanie z biblioteki BtAudio
Korzystanie z biblioteki BtAudio
Korzystanie z biblioteki BtAudio
Korzystanie z biblioteki BtAudio

Po zainstalowaniu podłącz ESP32 do komputera przez micro USB, a następnie podłącz dekoder stereo do głośnika za pomocą przewodu 3,5 mm. Zanim prześlesz szkic, będziesz musiał zmienić kilka rzeczy w edytorze Arduino. Po wybraniu płyty musisz edytować schemat partycji w menu Narzędzia >> Schemat partycji i wybrać „Brak OTA (duża aplikacja)” lub „Minimal SPIFFS (duże aplikacje z OTA)”. Jest to konieczne, ponieważ ten projekt wykorzystuje zarówno WiFi, jak i Bluetooth, które są bibliotekami bardzo obciążającymi pamięć. Po wykonaniu tej czynności wgraj następujący szkic do ESP32.

#włączać

// Ustawia nazwę urządzenia audio btAudio audio = btAudio("ESP_Speaker"); void setup() { // przesyła strumieniowo dane audio do ESP32 audio.begin(); // wysyła odebrane dane do przetwornika I2S DAC int bck = 26; int ws = 27; dout = 25; audio. I2S(bck, dout, ws); } void loop() { }

Szkic można ogólnie podzielić na 3 kroki:

  1. Utwórz globalny obiekt btAudio, który ustawia „nazwę Bluetooth” Twojego ESP32
  2. Skonfiguruj ESP32 do odbierania dźwięku za pomocą metody btAudio::begin
  3. Ustaw piny I2S metodą btAudio::I2S.

To wszystko po stronie oprogramowania! Teraz wszystko, co musisz zrobić, to zainicjować połączenie Bluetooth z ESP32. Po prostu wyszukaj nowe urządzenia w telefonie/laptopie/odtwarzaczu MP3, a pojawi się „ESP_Speaker”. Gdy będziesz zadowolony, że wszystko działa (muzyka gra) możesz odłączyć ESP32 od komputera. Zasil go zasilaczem USB, a zapamięta ostatni kod, który do niego wgrałeś. W ten sposób możesz na zawsze zostawić swojego ESP32 ukrytego za systemem HiFi.

Krok 7: DSP - filtrowanie

Rozszerzenie odbiornika o cyfrowe przetwarzanie sygnału

Jeśli wykonałeś wszystkie kroki (i niczego nie pominąłem), masz teraz w pełni działający odbiornik Bluetooth do swojego systemu HiFi. Chociaż jest to fajne, tak naprawdę nie zmusza mikrokontrolera do granic możliwości. ESP32 ma dwa rdzenie pracujące z częstotliwością 240 MHz. Oznacza to, że ten projekt to znacznie więcej niż tylko odbiornik. Może być odbiornikiem Bluetooth z cyfrowym procesorem sygnału (DSP). Procesory DSP zasadniczo wykonują operacje matematyczne na sygnale w czasie rzeczywistym. Jedną z użytecznych operacji jest filtrowanie cyfrowe. Ten proces tłumi częstotliwości sygnału poniżej lub powyżej określonej częstotliwości odcięcia, w zależności od tego, czy używasz filtra górnoprzepustowego, czy dolnoprzepustowego.

Filtry górnoprzepustowe

Filtry górnoprzepustowe tłumią częstotliwości poniżej pewnego pasma. Zbudowałem bibliotekę filtrów dla systemów Arduino w oparciu o kod z earlevel.com. Główna różnica polega na tym, że zmieniłem strukturę klas, aby łatwiej było budować filtry wyższego rzędu. Filtry wyższego rzędu skuteczniej tłumią częstotliwości przekraczające granicę, ale wymagają znacznie więcej obliczeń. Jednak przy obecnej implementacji możesz nawet używać filtrów 6. rzędu do dźwięku w czasie rzeczywistym!

Szkic jest taki sam jak ten znaleziony w poprzednim kroku, z tą różnicą, że zmieniliśmy główną pętlę. Do włączenia filtrów używamy metody btAudio::createFilter. Ta metoda akceptuje 3 argumenty. Pierwsza to liczba kaskad filtrów. Liczba kaskad filtrów jest o połowę mniejsza niż liczba filtrów. Dla filtra szóstego rzędu pierwszy argument powinien wynosić 3. Dla filtra ósmego rzędu byłby to 4. Drugi argument to odcięcie filtra. Ustawiłem to na 1000 Hz, aby mieć naprawdę dramatyczny wpływ na dane. Na koniec podajemy typ pliku z trzecim argumentem. Powinno to być górnoprzepustowy dla filtra górnoprzepustowego i dolnoprzepustowy dla filtra dolnoprzepustowego. Poniższy skrypt przełącza odcięcie tej częstotliwości między 1000Hz a 2Hz. Powinieneś usłyszeć dramatyczny wpływ na dane.

#włączać

btAudio audio = btAudio("Głośnik_ESP"); void setup() { audio.początek(); int bck = 26; int ws = 27; dout = 25; audio. I2S(bck, dout, ws); } void loop() { opóźnienie(5000); audio.createFilter(3, 1000, górnoprzepustowy); opóźnienie(5000); audio.createFilter(3, 2, górnoprzepustowy); }

Filtry dolnoprzepustowe

Filtry dolnoprzepustowe działają odwrotnie niż filtry górnoprzepustowe i tłumią częstotliwości powyżej określonej częstotliwości. Mogą być zaimplementowane w taki sam sposób jak filtry górnoprzepustowe, z tym wyjątkiem, że wymagają zmiany trzeciego argumentu na dolnoprzepustowy. W poniższym szkicu zmieniam odcięcie dolnoprzepustowe między 2000Hz a 20000Hz. Mam nadzieję, że usłyszysz różnicę. Powinno to brzmieć dość przytłumione, gdy filtr dolnoprzepustowy ma częstotliwość 2000 Hz.

#włączać

btAudio audio = btAudio("Głośnik_ESP"); void setup() { audio.początek(); int bck = 26; int ws = 27; dout = 25; audio. I2S(bck, dout, ws); } void loop() { opóźnienie(5000); audio.createFilter(3, 2000, dolnoprzepustowy); opóźnienie(5000); audio.createFilter(3, 20000, dolnoprzepustowy); }

Krok 8: DSP - kompresja zakresu dynamicznego

Tło

Kompresja zakresu dynamiki to metoda przetwarzania sygnału, która próbuje wyrównać głośność dźwięku. Kompresuje głośne dźwięki, które wznoszą się powyżej pewnego progu, do poziomu cichych, a następnie opcjonalnie wzmacnia oba. Rezultatem jest znacznie bardziej wyrównane wrażenia słuchowe. Przydało się to, gdy oglądałem program z bardzo głośną muzyką w tle i bardzo cichym wokalem. W tym przypadku samo zwiększenie głośności nie pomogło, ponieważ wzmocniło to tylko muzykę w tle. Dzięki kompresji zakresu dynamiki mogłem zredukować głośną muzykę w tle do poziomu wokali i ponownie wszystko usłyszeć.

Kod

Kompresja zakresu dynamiki to nie tylko obniżanie głośności lub progowanie sygnału. To trochę sprytniejsze. Jeśli zmniejszysz głośność, ciche dźwięki zostaną wyciszone, a także głośne. Jednym ze sposobów obejścia tego jest progowanie sygnału, ale powoduje to poważne zniekształcenia. Kompresja zakresu dynamiki obejmuje kombinację miękkiego progowania i filtrowania w celu zminimalizowania zniekształceń, jakie można uzyskać, gdybyśmy mieli progować/przycinać sygnał. W efekcie otrzymujemy sygnał, w którym głośne dźwięki są „obcinane” bez zniekształceń, a ciche pozostają bez zmian. Poniższy kod przełącza między trzema różnymi poziomami kompresji.

  1. Kompresja ze zniekształceniami
  2. Kompresja bez zniekształceń
  3. Brak kompresji

#włączać

btAudio audio = btAudio("Głośnik_ESP"); void setup() { audio.początek(); int bck = 26; int ws = 27; dout = 25; audio. I2S(bck, dout, ws); } void loop() { opóźnienie(5000); kompresja audio(30, 0,0001, 0,0001, 10, 10, 0); opóźnienie(5000); kompresja audio(30, 0,0001, 0,1, 10, 10, 0); opóźnienie(5000); audio.dekompresja(); }

Kompresja zakresu dynamiki jest skomplikowana, a metody btAudio::compress mają wiele parametrów. Postaram się je wyjaśnić (w kolejności) tutaj:

  1. Próg - poziom, przy którym dźwięk zostaje zmniejszony (mierzony w decybelach)
  2. Attack time - Czas potrzebny do rozpoczęcia pracy sprężarki po przekroczeniu progu
  3. Czas zwolnienia - czas, po którym sprężarka przestaje działać.
  4. Współczynnik redukcji - współczynnik kompresji dźwięku.
  5. Knee Width - Szerokość (w decybelach) wokół progu, przy której kompresor działa częściowo (bardziej naturalny dźwięk).
  6. Wzmocnienie (decybele) dodawane do sygnału po kompresji (zwiększenie/zmniejszenie głośności)

Bardzo słyszalne zniekształcenia przy pierwszym użyciu kompresji wynikają z tego, że próg jest bardzo niski, a zarówno czas ataku, jak i czas zwalniania są bardzo krótkie, co skutkuje twardym zachowaniem progowym. Jest to wyraźnie rozwiązane w drugim przypadku poprzez wydłużenie czasu wydania. To zasadniczo powoduje, że kompresor działa w znacznie płynniejszy sposób. Tutaj pokazałem tylko, jak zmiana 1 parametru może mieć dramatyczny wpływ na dźwięk. Teraz twoja kolej na eksperymentowanie z różnymi parametrami.

Implementacja (magiczna matematyka - opcjonalnie)

Odkryłem, że naiwne zaimplementowanie kompresji zakresu dynamicznego jest wyzwaniem. Algorytm wymaga konwersji 16-bitowej liczby całkowitej na decybele, a następnie przekształcenia jej z powrotem na 16-bitową liczbę całkowitą po przetworzeniu sygnału. Zauważyłem, że jedna linia kodu zajmuje 10 mikrosekund, aby przetworzyć dane stereo. Ponieważ dźwięk stereo próbkowany z częstotliwością 44,1 kHz pozostawia tylko 11,3 mikrosekund dla DSP, jest to niedopuszczalnie powolne… Jednak łącząc małą tablicę przeglądową (400 bajtów) i procedurę interpolacji opartą na podzielonych różnicach Netwona, możemy uzyskać prawie 17 bitową precyzję w 0,2 mikrosekundy. Załączam dokument pdf z całą matematyką dla naprawdę zainteresowanych. To skomplikowane, zostałeś ostrzeżony!

Krok 9: Interfejs Wi-Fi

Interfejs Wi-Fi
Interfejs Wi-Fi
Interfejs Wi-Fi
Interfejs Wi-Fi

Teraz masz odbiornik Bluetooth, który może obsługiwać DSP w czasie rzeczywistym. Niestety, jeśli chcesz zmienić którykolwiek z parametrów DSP, będziesz musiał odłączyć się od HiFi, przesłać nowy szkic, a następnie ponownie się połączyć. To jest niezgrabne. Aby to naprawić, opracowałem serwer sieciowy, którego możesz użyć do edycji wszystkich parametrów DSP bez ponownego łączenia się z komputerem. Poniżej znajduje się szkic do korzystania z serwera WWW.

#włączać

#include btAudio audio = btAudio("Głośnik_ESP"); webDSP sieć; void setup() { Serial.begin(115200); audio.początek(); int bck = 26; int ws = 27; dout = 25; audio. I2S(bck, dout, ws); // zastąp swoim identyfikatorem WiFi i hasłem const char* ssid = "SSID"; const char* hasło = "HASŁO"; web.begin(ssid, hasło, &audio); } void loop() { web._server.handleClient(); }

Kod przypisuje adres IP do twojego ESP32, którego możesz użyć, aby uzyskać dostęp do strony internetowej. Przy pierwszym uruchomieniu tego kodu powinien on być podłączony do komputera. W ten sposób możesz zobaczyć adres IP przypisany do Twojego ESP32 na monitorze szeregowym. Jeśli chcesz uzyskać dostęp do tej strony internetowej, po prostu wprowadź ten adres IP w dowolnej przeglądarce internetowej (testowane na chrome).

Do tej pory powinniśmy znać metodę włączania Bluetooth i I2S. Kluczową różnicą jest użycie obiektu webDSP. Ten obiekt pobiera Twój identyfikator SSID Wi-Fi i hasło jako argumenty, a także wskaźnik do obiektu btAudio. W głównej pętli nieustannie otrzymujemy obiekt webDSP, który nasłuchuje danych przychodzących ze strony internetowej, a następnie aktualizuje parametry DSP. Na zakończenie należy zauważyć, że zarówno Bluetooth, jak i Wifi używają tego samego radia na ESP32. Oznacza to, że od momentu wprowadzenia parametrów na stronie internetowej do momentu, gdy informacje faktycznie dotrą do ESP32, konieczne może być odczekanie do 10 sekund.

Krok 10: Plany na przyszłość

Mamy nadzieję, że podobało ci się to, a teraz masz Bluetooth Audio i DSP dodany do twojego HiFi. Myślę jednak, że w tym projekcie jest dużo miejsca na rozwój i chciałem tylko wskazać kilka przyszłych kierunków, które mogę obrać.

  • Włącz strumieniowe przesyłanie dźwięku przez Wi-Fi (w celu uzyskania najlepszej jakości dźwięku)
  • Użyj mikrofonu I2S, aby włączyć polecenia głosowe
  • opracować korektor sterowany przez Wi-Fi
  • Zrób to ładnie (płyta do krojenia chleba nie krzyczy o świetnym projekcie produktu)

Kiedy zajmę się wdrażaniem tych pomysłów, zrobię więcej instrukcji. A może ktoś inny zaimplementuje te funkcje. To radość, że wszystko jest open source!

Zalecana: