Spisu treści:

Odtwarzanie plików dźwiękowych audio (Wav) za pomocą Arduino i DAC: 9 kroków
Odtwarzanie plików dźwiękowych audio (Wav) za pomocą Arduino i DAC: 9 kroków

Wideo: Odtwarzanie plików dźwiękowych audio (Wav) za pomocą Arduino i DAC: 9 kroków

Wideo: Odtwarzanie plików dźwiękowych audio (Wav) za pomocą Arduino i DAC: 9 kroków
Wideo: Arduino 47: Naśladujemy dźwięki silnika spalinowego 2024, Lipiec
Anonim
Odtwarzanie plików dźwiękowych audio (Wav) za pomocą Arduino i DAC
Odtwarzanie plików dźwiękowych audio (Wav) za pomocą Arduino i DAC
Odtwarzanie plików dźwiękowych audio (Wav) za pomocą Arduino i DAC
Odtwarzanie plików dźwiękowych audio (Wav) za pomocą Arduino i DAC
Odtwarzanie plików dźwiękowych audio (Wav) za pomocą Arduino i DAC
Odtwarzanie plików dźwiękowych audio (Wav) za pomocą Arduino i DAC

Odtwórz plik wav Audio z karty SD Audino. Ta instrukcja pokaże Ci, jak plik wav na karcie SD można odtworzyć za pomocą prostego obwodu do głośnika.

Plik wav musi być 8-bitowym plikiem mono. Nie miałem problemu z odtwarzaniem plików 44 KHz.

Choć nie jest to hi-fidelity, jakość dźwięku jest bardzo zadowalająca.

Do wyboru pliku używany jest monitor szeregowy. Pliki muszą znajdować się w folderze o nazwie adlog.

Ta instrukcja wynika z wcześniejszego projektu, w którym zapisałem nagrania wav na karcie SdCard:

Obwód wykorzystuje tani 8-bitowy przetwornik cyfrowo-analogowy (DAC) i jednoukładowy wzmacniacz audio.

Kluczowe sekcje dotyczące konfiguracji przerwań zostały zaczerpnięte z doskonałego artykułu Amandy Ghassaei:

Krok 1: Wymagania

Wymagania
Wymagania
Wymagania
Wymagania

Arduino- używam Mega, jednak nie ma powodu, dla którego Uno miałoby nie działać.

Czytnik kart SD - program jest skonfigurowany dla: MicroSD Breakout Board Regulated with Logic Conversion V2

Zobacz tę instrukcję dotyczącą szczegółów konfiguracji karty SD:

DAC0832 LCN- doskonały 8-bitowy przetwornik cyfrowo-analogowy- Kilka funtów.

Wzmacniacz operacyjny LM386 N-1 - tani jak chipy

20-stykowe gniazdo chipowe

8-kierunkowe gniazdo chipowe

Zasilanie 9 V - wystarczy bateria.

LM336 napięcie odniesienia 2,5 V

Kondensator 10uF * 3 (dowolne napięcie powyżej 9 V)

Rezystor 10 omów

Kondensator 50nF- (lub gdzieś w pobliżu-47nF, 56nf, 68nf- zrobi)

Kondensator 220uF

Głośnik 64 omów

Potencjometr liniowy 10 K

Kabel do połączenia 8 linii danych między Arduino a obwodem-

W Uno 8 połączeń jest w linii, w Mega są parami.

W Mega użyłem 10-stykowego kabla wstążkowego z 10-drożnym nagłówkiem IDC. (2 przewody są zapasowe)

Złącza gniazdowe dla wyjść 0V, 9V i DAC

Płyta miedziana, lut, drut, noże itp

Krok 2: Specyfikacje

Specyfikacja
Specyfikacja

Szeregowy ustawiony na 115200 bodów.

Wsparcie dla płytki zaciskowej MicroSD firmy Hobbytronics przy użyciu Mega. Wybór chipa i inne porty będą się zmieniać między Mega i Uno.

Pliki Wav muszą znajdować się w katalogu o nazwie adlog. Możesz nadać mu inną nazwę i ponownie ułożyć niezbędne kodowanie.

Plik wav musi być 8-bitowym plikiem mono. Testowałem do 44KHz.

Monitor Serial wyświetla pliki wav w folderze adlog. Nazwy plików są wysyłane z linii wyjściowej monitora.

Rozmiar pliku jest ograniczony tylko rozmiarem karty SD.

Krok 3: Pierwsze kroki

Pierwsze kroki
Pierwsze kroki

Podłącz czytnik kart SD. To są połączenia dla Mega.

0,5V

CLK do pinu 52

D0 do pinu 50

D1 do pinu 51

CS do pinu 53

(Patrz strona internetowa dostawcy dla połączenia z portem Uno)

Na tym etapie będziesz chciał przetestować, czy Twoja karta działa – użyj skryptów dostarczonych przez dostawcę.

Musimy zrobić mały obwód

Wyślemy strumień bajtów audio z Arduino.

Liczby te mieszczą się w zakresie od 0 do 255. Reprezentują napięcie.

Cisza to 127-128.

255 to stożek głośnika twardy w jedną stronę.

0 to stożek głośnika twardy w drugą stronę.

Tak więc dźwięk jest zapisywany jako zapisane liczby, które tworzą zmienne napięcia, które tworzą ruchome stożki głośników.

Liczby możemy wysyłać jednocześnie z 8 linii na Arduino, korzystając z „portu”.

Jeśli wprowadzimy 8 linii do przetwornika cyfrowo-analogowego, zrobi to, co mówi na puszce i wytworzy napięcie analogowe, które jest proporcjonalne do liczby cyfrowej.

Wystarczy wtedy odprowadzić napięcie do małego wzmacniacza operacyjnego, a następnie do głośnika.

Krok 4: Mały obwód

Mały obwód
Mały obwód
Mały obwód
Mały obwód
Mały obwód
Mały obwód
Mały obwód
Mały obwód

DAC0832 LCN

To znakomity, tani 8-bitowy konwerter cyfrowo-analogowy. (DAC)

Może być w pełni kontrolowany za pomocą szeregu zatrzymań danych, linii próbkowania danych.

Lub może być skonfigurowany tak, aby robił to wszystko automatycznie w "Operacji przepływowej".

Cytując instrukcję:

Proste uziemienie CS, WR1, WR2 i XFER oraz wiązanie wysokiego poziomu ILE pozwala obu rejestrom wewnętrznym podążać za zastosowanymi wejściami cyfrowymi (przepływ) i bezpośrednio wpływać na wyjście analogowe przetwornika cyfrowo-analogowego.

OK, czyli cztery połączenia z chipsetem na niskim poziomie i jedno ustawione na 9V - łatwe.

Nie chcemy żadnych ujemnych napięć, więc instrukcja mówi, że powinniśmy używać "trybu przełączania napięcia" i dostarczają schemat.

Wystarczy, że zamiast tego, co sugerują, podstawić mały wzmacniacz Audio.

Wzmacniacz audio LM386-N

Instrukcja wzmacniacza zawiera schemat minimalnej części - zapewniając wzmocnienie 20 (o wiele za dużo dla nas - ale ma regulację głośności).

Wszystko, co musimy zrobić, to dodać kondensator między DAC a wzmacniacz, aby wzmacniać tylko sygnały AC.

Musimy również dodać kilka kondensatorów blisko styku zasilania każdego z naszych chipów, w przeciwnym razie dostaniemy przydźwięk z naszego zasilacza 9V.

Krok 5: Wyjmij lutownicę

Wyjmij lutownicę
Wyjmij lutownicę
Wyjmij lutownicę
Wyjmij lutownicę
Wyjmij lutownicę
Wyjmij lutownicę

Ponieważ obwód jest prosty, nie zamierzam dawać konta cios za ciosem.

Oto kilka wskazówek:

  • Przygotuj kawałek płyty miedzianej o wymiarach co najmniej 28 na 28 otworów. (Tak, wiem, że neurochirurgowie mogą to zmniejszyć)
  • Jeśli zamierzasz montować go za pomocą śrub, uwzględnij je na początku!
  • Zamontuj żetony na gniazdach. Wkładać żetony dopiero po sprawdzeniu wszystkiego.
  • Trzymaj przewody wejściowe z dala od wyjścia.
  • Przestrzegaj prawidłowej polaryzacji kondensatorów.
  • Zapoznaj się ze schematem, aby uzyskać widok podstawy napięcia odniesienia LM336. Noga regulacyjna nie jest używana i można ją obciąć.
  • Zwróć uwagę na bezpośrednie połączenie z pinem 8 przetwornika cyfrowo-analogowego - jest to bardzo przydatne do testowania.
  • Podłączyłem się do Audino kablem taśmowym i 10-stykowym złączem IDC.
  • W Uno połączenia są w linii prostej - może się okazać, że ułożenie 8 wejść w jedną linię prostą pozwala połączyć się z Arduino za pomocą zakupionego, gotowego złącza 8-stykowego,

Po zakończeniu sprawdź lutowanie i sprawdź szczeliny między miedzianymi ścieżkami.

Uważam, że brzeszczot 36 tpi junior jest bardzo przydatny do usuwania gruzu. Usuwam kołki ustalające ostrza i wsuwam czubek ostrza w prowadnicę- Oczywiście ostrze nie jest w ramie.

Krok 6: Testowanie DAC

Testowanie DAC
Testowanie DAC

Pozostaw połączenie między obwodem a Arduino wyłączone.

Ustaw regulator głośności w obwodzie na środek.

Włącz zasilanie 9V DC do nowego obwodu.

Sprawdź, czy obwód jest w porządku - nie mogę przyjąć żadnej odpowiedzialności za twój obwód!

Wyłącz

Podłącz swój obwód do Arduino.

W Mega użyj pinów 22-29. (PORTA) Nie pomyl dwóch pinów 5V powyżej!

W Uno użyj pinów 0-7. To jest PORTD

Podłącz 0V twojego zasilacza do 0V na Arduino.

Wzmocnij.

Otwórz ten program testowy DAC_TEST

W przypadku UNO, zamień wszystkie odniesienia do PORTA na PORTD

Zamień DDRA na DDRD - ta instrukcja ustawia wszystkie 8 linii na wyjście za jednym razem. To jest rejestr kierunku danych.

Ustaw monitor szeregowy na 115200.

Podłącz woltomierz między wyjściem DAC a OV

Program ustawi wyjście na 255 – wszystkie linie włączone – maksymalne napięcie.

Wyjście 128- połowa maksymalnego napięcia.

Wyjście 0- zero napięcia (lub prawdopodobnie prawie zero).

Następnie będzie krok po kroku: 1, 2, 4, 8, 16, 32, 64, 128

Napięcie powinno stale rosnąć.

Jeśli napięcie spadnie, a liczba wzrośnie, prawdopodobnie masz zamienione dwa przewody łączące.

Powinieneś również słyszeć ciche klikanie głośnika wraz ze zmianą napięcia

Krok 7: Czytanie nagłówka Wav

Czytanie nagłówka WAV
Czytanie nagłówka WAV

Pliki wav są zapisywane z określoną częstotliwością i rozmiarem danych.

Ta informacja jest zawarta w 44 bajtowym nagłówku na początku pliku wav.

Chociaż niektóre programy rozszerzają nagłówek (po bajcie 35), co utrudnia zlokalizowanie lokalizacji rozmiaru danych.

Aby odczytać nagłówek tworzymy bufor i kopiujemy początek pliku.

Częstotliwość jest zapisywana w 4 bajtach, zaczynając od 24 bajtów w pliku.

// odczytaj częstotliwość określoną w nagłówku pliku wav

bajt headbuf[60]

plik tymczasowy.seek(0);

tempfile.read(headbuf, 60);

retval=headbuf[27];

retval=(retval<<8) | ochraniacz na głowę[26];

retval=(retval<<8) | ochraniacz na głowę[25];

retval=(retval<<8) | ochraniacz na głowę[24];

Serial.print(F("Częstotliwość Pliku"));

Serial.print(zwrot);

Najlepszym sposobem na znalezienie informacji o rozmiarze danych jest wyszukanie słowa „dane” w nagłówku.

Następnie wyodrębnij 4 bajty następujące po nim, które składają się na długą wartość

niepodpisany długi zwrot;

int mypoz=40;

dla (int i=36; i<60;i++) {

if (headbuf == 'd') {

if(headbuf[i+1]=='a') {

if(headbuf[i+2]=='t') {

if(headbuf[i+3]=='a') {

// w końcu to mamy

moja pozycja=i+4;

i=60;

}

}

}

}

}

plik tymczasowy.seek(moje poz);

retval=headbuf[mypos+3];

retval=(retval<<8) | headbuf[mypos+2];

retval=(retval<<8) | headbuf[mypos+1];

retval=(retval<<8) | headbuf[mypos];

OK, mamy długość i częstotliwość danych!

Dane audio następują po 4 bajtach tworzących wartość długości danych.

Krok 8: Przerwij, Przerwij…

Przerwanie, przerwanie…
Przerwanie, przerwanie…

Używamy informacji o częstotliwości, aby utworzyć przerwanie programowe na lub w pobliżu wymaganej częstotliwości.

Przerwanie nie zawsze można precyzyjnie ustawić, ale wystarczy. Częstotliwość odczytana z pliku jest przekazywana do podprogramu setintrupt.

void setintrupt(liczba zmiennoprzecinkowa){wartość zmiennoprzecinkowa=8; // 8 dla 8-bitowych timerów 0 i 2, 1024 dla timera 1 bajt

setocroa=(16000000/(częst.*bitwal)) - 0.5;

// Wartość setocroa wymaga odjęcia -1. Jednak dodanie 0,5 rundy do najbliższego 0,5

// Rozdzielczość timera jest ograniczona

// Ostatecznie określone przez wielkość bitval

cli(); // wyłącz przerwania// ustaw przerwanie timera2

TCCR2A = 0; // ustaw cały rejestr TCCR2A na 0

TCCR2B = 0; // to samo dla TCCR2B

TCNT2 = 0; // inicjalizuj wartość licznika na 0

// ustaw rejestr porównawczy dla przyrostów częstotliwości (hz)

OCR2A = setocroa; // = (16*10^6) / (częstotliwość*8) - 1 (musi być <256)

// włącz tryb CTC

TCCR2A |= (1 <<WGM21); // Ustaw bit CS21 dla 8 preskalerów

TCCR2B |= (1 << CS21); // włącz timer porównaj przerwanie

// TIMSK2 |= (1 << OCIE2A); // to działa, podobnie jak poniższa linia

sbi(TIMSK2, OCIE2A); // włącz przerwanie na zegarze 2

sei(); // włącz przerwania

Wymagający czytelnicy zauważą sbi(TIMSK2, OCIE2A)

Ustawiłem kilka (nabytych przez Internet) funkcji do ustawiania i czyszczenia bitów rejestru:

// Definiuje kasowanie bitów rejestru#ifndef cbi

#define cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))

#endif

// Definiuje ustawienie bitów rejestru

#ifndef sbi

#define sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))

#endif

Funkcje te zapewniają łatwe wywołanie w celu ustawienia lub usunięcia przerwania.

Więc przerwanie działa, co możemy zmusić do zrobienia?

Krok 9: Przerwania i podwójne buforowanie

Przerwania i podwójne buforowanie
Przerwania i podwójne buforowanie
Przerwania i podwójne buforowanie
Przerwania i podwójne buforowanie

Przy 22 Khz bajt danych audio jest wysyłany co 0,045 ms

512 bajtów (rozmiar bufora) jest odczytywanych w 2,08 ms.

Tak więc bufor nie może być odczytany z karty SD w jednym cyklu zapisu.

Jednak 512 bajtów jest zapisywanych w porcie w czasie 23,22 ms.

Więc wszystko, co musimy zrobić, to ustawić nowy plik odczytywany za każdym razem, gdy bufor się opróżni i mamy wystarczająco dużo czasu, aby pobrać dane, zanim wymagany będzie nowy blok danych… Zakładając, że używamy dwóch buforów, opróżniając jeden podczas wypełniania drugiego.

To jest podwójne buforowanie.

Odczyt pliku zostanie spowolniony przez powtarzające się przerwanie, ale zostanie wykonane.

Ustawiłem dwa 512 bajtowe bufory o nazwie bufa i bufb.

Jeśli flaga jest ustawiona na true, czytamy z porta, w przeciwnym razie czytamy z portb

Kiedy pozycja bufora (bufcount) osiągnie rozmiar bufora (BUF_SIZE 512) ustawiamy flagę o nazwie readit na true.

Procedura void loop szuka tej flagi i uruchamia blok odczytu:

if(readit){if (! gotowy){

// zainicjuj odczyt bloku SDCard do bufa

tempfile.read(bufa, BUF_SIZE);

} w przeciwnym razie {

// zainicjuj odczyt bloku SDCard do bufb

tempfile.read(bufb, BUF_SIZE);

}

readit=fałsz;

}

Po zakończeniu procedury flagi readit=false.

W ramach procedury przerwania musimy sprawdzić, czy pętla void zakończyła się, sprawdzając, czy readit== false.

W takim przypadku sygnalizujemy, że wymagany jest kolejny odczyt i przełączamy flagę aready, aby przełączyć bufory.

Jeśli karta SD nadal czyta, musimy cofnąć jeden odczyt (licznik--; bufcount--;) i wyjść z przerwania, aby spróbować ponownie później. (Kliknięcia w wyjściowym sygnale audio oznaczają, że tak się stało.)

Gdy wszystkie dane zostaną odczytane, przerwanie jest anulowane, port zostaje zresetowany do średniej wartości napięcia 128 i plik audio zostaje zamknięty.

Przed pierwszym uruchomieniem skryptu dac2.ino ustaw głośność na 50%. Będzie za głośno, ale to lepsze niż 100%!

Jeśli regulacja głośności działa w odwrotnej kolejności, zamień przewody na przeciwległych końcach potencjometru 10K.

Daj mi znać, jak to brzmi.

Zalecana: