Inhoudsopgave:

Audio geluidsbestanden (Wav) afspelen met een Arduino en een DAC: 9 stappen
Audio geluidsbestanden (Wav) afspelen met een Arduino en een DAC: 9 stappen

Video: Audio geluidsbestanden (Wav) afspelen met een Arduino en een DAC: 9 stappen

Video: Audio geluidsbestanden (Wav) afspelen met een Arduino en een DAC: 9 stappen
Video: Audacity in 1,5 min - knip, plak en bewerk je geluid 2024, Juli-
Anonim
Audio geluidsbestanden (Wav) afspelen met een Arduino en een DAC
Audio geluidsbestanden (Wav) afspelen met een Arduino en een DAC
Audio geluidsbestanden (Wav) afspelen met een Arduino en een DAC
Audio geluidsbestanden (Wav) afspelen met een Arduino en een DAC
Audio geluidsbestanden (Wav) afspelen met een Arduino en een DAC
Audio geluidsbestanden (Wav) afspelen met een Arduino en een DAC

Speel wav-bestand Audio van uw Audino SD-kaart. Deze Instructable laat je zien hoe een wav-bestand op je SD-kaart kan worden afgespeeld via een eenvoudig circuit naar een luidspreker.

Het wav-bestand moet 8 bit mono zijn. Ik heb geen probleem gehad met het afspelen van 44 KHz-bestanden.

Hoewel niet hi-fidelity, is de geluidskwaliteit zeer bevredigend.

De seriële monitor wordt gebruikt om het bestand te selecteren. De bestanden moeten zich in een map met de naam adlog bevinden.

Deze instructable volgt uit een eerder project waar ik wav-opnames op de SdCard heb opgeslagen:

De schakeling maakt gebruik van een goedkope 8 bit digitaal naar analoog converter (DAC) en een enkele chip audioversterker.

De belangrijkste secties voor het instellen van interrupts zijn overgenomen uit het uitstekende artikel van Amanda Ghassaei:

Stap 1: Vereisten

Vereisten
Vereisten
Vereisten
Vereisten

Arduino- Ik gebruik de Mega, maar er is geen reden waarom de Uno niet zou werken.

SdCard-lezer - het programma is geconfigureerd voor: MicroSD Breakout Board Regulated with Logic Conversion V2

Zie dit instructable voor SdCard setup details:

DAC0832 LCN- een uitstekende 8 bit digitaal naar analoog converter- Een paar pond.

LM386 N-1 Opamp - goedkoop als chips

20-weg chip socket

8-weg chip socket

9 volt voeding - een batterij is voldoende.

LM336 2,5 V spanningsreferentie

10uF Condensator * 3 (elke spanning meer dan 9V)

10 ohm weerstand

50nF condensator- (of ergens in de buurt van-47nF, 56nf, 68nf- zal doen)

220uF condensator

64 ohm luidspreker

10K lineaire potentiometer

Kabel om de 8 datalijnen tussen de Arduino en het circuit te verbinden-

Bij de Uno staan de 8 aansluitingen in lijn, bij de Mega staan ze paarsgewijs.

Op de Mega gebruikte ik een 10-wegs lintkabel met een 10-weg IDC-header. (2 draden zijn reserve)

Socket connectoren voor 0V, 9V en DAC out

Koper strip board, soldeer, draad, scharen etc

Stap 2: De specificaties:

De specificaties
De specificaties

Serieel ingesteld op 115200 baud.

Er is ondersteuning voor het Hobbytronics MicroSD Breakout Board met behulp van een Mega. De chip select en andere poorten zullen veranderen tussen Mega en Uno.

De Wav-bestanden moeten bestaan in een map met de naam adlog. Voel je vrij om het een andere naam te geven en de benodigde codering opnieuw te ordenen.

Het wav-bestand moet 8 bit mono zijn. Ik heb tot 44KHz getest.

De seriële monitor toont de wav-bestanden in de adlog-map. Bestandsnamen worden verzonden vanaf de monitoruitgangslijn.

De bestandsgrootte wordt alleen beperkt door de grootte van de SD-kaart.

Stap 3: Aan de slag

Beginnen
Beginnen

Sluit de SD-kaartlezer aan. Dit zijn de aansluitingen voor de Mega.

0, 5V

CLK naar pin 52

D0 naar pin 50

D1 naar pin 51

CS naar pin 53

(Zie leverancierswebsite voor Uno-poortverbinding)

U zult in dit stadium willen testen of uw kaart werkt - gebruik de scripts die door de leverancier zijn geleverd.

We moeten een klein circuit maken

We gaan een stroom audiobytes sturen vanaf de Arduino.

Deze getallen liggen tussen 0 en 255. Ze vertegenwoordigen de spanning.

Stilte is 127-128.

255 is een luidsprekerconus die in één richting hard is.

0 is de luidsprekerconus hard andersom.

Dus audio wordt opgenomen als opgeslagen nummers, die verschillende spanningen creëren, die bewegende luidsprekerconussen creëren.

We kunnen de nummers van 8 regels tegelijkertijd naar de Arduino sturen door een "poort" te gebruiken.

Als we de 8 lijnen in een digitaal naar analoog converter voeren, doet hij wat het zegt op het blikje en levert hij een analoge spanning op die evenredig is met het digitale getal.

Het enige wat we dan hoeven te doen, is de spanning naar een kleine operationele versterker en vervolgens naar een luidspreker brengen.

Stap 4: Het kleine circuit

Het kleine circuit
Het kleine circuit
Het kleine circuit
Het kleine circuit
Het kleine circuit
Het kleine circuit
Het kleine circuit
Het kleine circuit

De DAC0832 LCN

Dit is een uitstekende, goedkope 8 bit digitaal naar analoog converter. (DAC)

Het kan volledig worden bestuurd met een reeks data hold, data sample-lijnen.

Of het kan worden ingesteld om het allemaal automatisch te doen in "Doorstroombediening".

Om de handleiding te citeren:

Door eenvoudig CS, WR1, WR2 en XFER te aarden en ILE hoog te koppelen, kunnen beide interne registers de toegepaste digitale ingangen volgen (doorstroom) en direct de analoge DAC-uitgang beïnvloeden.

OK, dat zijn vier aansluitingen op de chipset laag en één op 9V - makkelijk.

We willen geen negatieve spanningen, dus de handleiding zegt dat we "spanningsschakelmodus" moeten gebruiken en zij leveren het diagram.

Het enige dat we hoeven te doen, is een kleine audioversterker vervangen in plaats van degene die ze voorstellen.

De LM386-N audioversterker

De handleiding van de versterker geeft een diagram van de minimale onderdelen - wat een versterking van 20 oplevert (veel te veel voor ons - maar het heeft een volumeregeling).

Het enige dat we hoeven te doen, is een condensator tussen de DAC en de versterker toevoegen, zodat we alleen AC-signalen versterken.

We moeten ook een paar condensatoren toevoegen in de buurt van de voedingspin van elk van onze chips, anders krijgen we brom van onze 9V-voeding.

Stap 5: Haal de soldeerbout eruit

Haal de soldeerbout tevoorschijn
Haal de soldeerbout tevoorschijn
Haal de soldeerbout tevoorschijn
Haal de soldeerbout tevoorschijn
Haal de soldeerbout tevoorschijn
Haal de soldeerbout tevoorschijn

Omdat het circuit eenvoudig is, ben ik niet van plan om een klapper te geven.

Hier zijn enkele aanwijzingen:

  • Bereid een stuk koperstripplaat voor met minimaal 28 bij 28 gaten. (Ja, ik weet dat hersenchirurgen het kleiner kunnen maken)
  • Als u van plan bent om het met schroeven te monteren, houd hier dan in het begin rekening mee!
  • Monteer de chips op sockets. Plaats de chips pas als alles is gecontroleerd.
  • Houd de ingangsdraden uit de buurt van de uitgang.
  • Let op de juiste polariteit van de condensatoren.
  • Raadpleeg het diagram voor het basisaanzicht van de LM336-spanningsreferentie. De stelpoot wordt niet gebruikt en kan worden ingekort.
  • Let op de directe verbinding met pin 8 van de DAC- Het is erg handig om te testen.
  • Ik heb verbinding gemaakt met de Audino met een lintkabel en een 10-weg IDC-connector.
  • Op de Uno zijn de aansluitingen in een rechte lijn - het kan zijn dat u door de 8 ingangsaansluitingen in een enkele rechte lijn te rangschikken, u naar de Arduino kunt linken met een gekochte, kant-en-klare 8-weg connector,

Als het klaar is, controleer dan het solderen en controleer de openingen tussen de koperen sporen.

Ik vind een junior zaagblad van 36 tpi erg handig voor het opruimen van puin. Ik verwijder de paspennen van het mes en schuif de punt van het mes in de baan. Het is duidelijk dat het mes niet in een frame zit.

Stap 6: De DAC testen

De DAC testen
De DAC testen

Laat de verbinding tussen het circuit en de Arduino uitgeschakeld.

Zet de volumeregeling op uw circuit op halverwege.

Schakel de 9V DC-voeding in op uw nieuwe circuit.

Controleer of het circuit in orde is - ik kan geen enkele aansprakelijkheid aanvaarden voor uw circuit!

Uitschakelen

Verbind je circuit met de Arduino.

Gebruik op de Mega pinnen 22-29. (PORTA) Vergis je niet in de twee 5V-pinnen hierboven!

Gebruik op de Uno pinnen 0-7. Dit is PORTD

Sluit de 0V van je voeding aan op de 0V op de Arduino.

Opstarten.

Open dit testprogramma DAC_TEST

Vervang voor de UNO alle verwijzingen naar PORTA naar PORTD

Vervang DDRA door DDRD - met deze instructie worden alle 8 regels in één keer uitgevoerd. Dit is het gegevensrichtingregister.

Stel uw seriële monitor in op 115200.

Sluit een voltmeter aan tussen de DAC out en OV

Het programma stelt de uitgang in op 255 - alle lijnen aan - maximale spanning.

Uitgang 128 - halve maximale spanning.

Uitgang 0- nul spanning (of waarschijnlijk bijna nul).

Het zal dan bitsgewijs stappen: 1, 2, 4, 8, 16, 32, 64, 128

De spanning moet gestaag toenemen.

Als de spanning terugvalt terwijl het aantal toeneemt, hebt u waarschijnlijk twee van de verbindingsdraden verwisseld.

Je zou de luidspreker ook zachtjes moeten horen klikken als de spanning verandert

Stap 7: De Wav-header lezen

De Wav-header lezen
De Wav-header lezen

Wav-bestanden worden opgeslagen met een opgegeven frequentie en gegevensgrootte.

Deze informatie staat in een header van 44 bytes aan het begin van een wav-bestand.

Hoewel sommige software de header uitbreidt (na byte 35), waardoor de locatie van de gegevensgrootte moeilijker te vinden is.

Om de header te lezen, maken we een buffer en kopiëren we het begin van het bestand.

De frequentie wordt opgeslagen in 4 bytes vanaf 24 bytes in het bestand.

// leesfrequentie gespecificeerd in wav-bestandsheader

byte-headbuf[60]

tempbestand.seek(0);

tempfile.read(headbuf, 60);

retval=headbuf[27];

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

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

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

Serial.print(F("Bestandsfrequentie"));

Seriële.afdruk (opnieuw);

De beste manier om informatie over de gegevensgrootte te vinden, is door te zoeken naar het woord 'gegevens' in de koptekst.

Extraheer vervolgens de 4 bytes die erop volgen, die de lange waarde vormen

niet-ondertekende lange reval;

int mijnpos=40;

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

if (headbuf == 'd') {

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

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

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

// Eindelijk hebben we het

mijnpos=i+4;

ik=60;

}

}

}

}

}

tempfile.seek(mijnpos);

retval=headbuf[mijnpos+3];

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

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

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

OK, we hebben de gegevenslengte en -frequentie!

De audiogegevens volgen de 4 bytes die de gegevenslengte vormen.

Stap 8: Onderbreken, Onderbreken…

Onderbreken, onderbreken…
Onderbreken, onderbreken…

We gebruiken de frequentie-informatie om een software-interrupt te creëren op of in de buurt van de vereiste frequentie.

De interrupt kan niet altijd precies worden ingesteld, maar is voldoende. De frequentie die uit het bestand wordt gelezen, wordt doorgegeven aan de subroutine setintrupt.

void setintrupt(float freq){float bitval=8; // 8 voor 8 bit timers 0 en 2, 1024 voor timer 1 byte

setocroa=(16000000/(freq*bitval)) - 0,5;

// De setocroa-waarde vereist een aftrekking van -1. Maar 0,5 rondes toevoegen aan de dichtstbijzijnde 0,5

// De resolutie van de timer is beperkt

// Uiteindelijk bepaald door de grootte van bitval

cli(); // interrupts uitschakelen// timer2 interrupt instellen

TCCR2A = 0; // zet het hele TCCR2A-register op 0

TCCR2B = 0; // hetzelfde voor TCCR2B

TCNT2 = 0; // initialiseer de tellerwaarde op 0

// stel vergelijk match register in voor frequentie (hz) stappen

OCR2A = setocroa; // = (16*10^6) / (frequentie*8) - 1 (moet <256) zijn

// zet CTC-modus aan

TCCR2A |= (1 << WGM21); // Stel CS21 bit in voor 8 prescaler

TCCR2B |= (1 << CS21); // schakel timer vergelijk interrupt in

// TIMSK2 |= (1 << OCIE2A); // dit werkt, net als de volgende regel

sbi(TIMSK2, OCIE2A); // schakel interrupt in op timer 2

zie(); // schakel onderbrekingen in

Veeleisende lezers zullen sbi (TIMSK2, OCIE2A) hebben gezien

Ik heb een aantal (internet verworven) functies ingesteld voor het instellen en wissen van registerbits:

// Definieert voor het wissen van registerbits #ifndef cbi

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

#stop als

// Definieert voor het instellen van registerbits

#ifndef sbi

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

#stop als

Deze functies bieden een eenvoudige oproep om de onderbreking in te stellen of te wissen.

Dus de interrupt is actief, wat kunnen we ervoor zorgen?

Stap 9: Onderbrekingen en dubbele buffering

Onderbrekingen en dubbele buffering
Onderbrekingen en dubbele buffering
Onderbrekingen en dubbele buffering
Onderbrekingen en dubbele buffering

Bij 22 Khz wordt elke 0,045 ms een byte aan audiogegevens uitgevoerd

512 bytes (de buffergrootte) wordt gelezen in 2,08 ms.

De buffer kan dus niet in één schrijfcyclus van de SDCard worden gelezen.

Er worden echter 512 bytes in 23,22 ms naar de poort geschreven.

Dus alles wat we hoeven te doen is een nieuw bestand in te stellen dat elke keer wordt gelezen als de buffer leeg raakt en we hebben genoeg tijd om de gegevens op te halen voordat een nieuw gegevensblok nodig is… Ervan uitgaande dat we twee buffers gebruiken, waarbij we de ene leegmaken terwijl we de andere vullen.

Dit is dubbel bufferen.

Het lezen van het bestand wordt vertraagd door de herhaalde onderbreking, maar het wordt gedaan.

Ik heb twee buffers van 512 bytes ingesteld, bufa en bufb genaamd.

Als de vlag aready waar is, lezen we uit porta, anders lezen we uit portb

Wanneer de bufferpositie (bufcount) de buffergrootte (BUF_SIZE 512) bereikt, stellen we een vlag met de naam readit in op true.

De void loop-routine zoekt naar deze vlag en begint een blok te lezen:

if(readit){if (! aready){

// initieer SDCard-blok lezen naar bufa

tempfile.read(bufa, BUF_SIZE);

} anders {

// initieer SDCard-blok lezen naar bufb

tempfile.read(bufb, BUF_SIZE);

}

readit=false;

}

Als het klaar is, markeert de routine readit=false.

Binnen de interruptroutine moeten we controleren of de void-lus is voltooid door te controleren of readit== false.

Als dit het geval is, geven we aan dat nog een leesbewerking nodig is en schakelen we de aready-vlag in om van buffer te wisselen.

Als de SD-kaart nog steeds aan het lezen is, moeten we één meting terugdraaien (teller--; bufcount--;) en de onderbreking afsluiten om het later opnieuw te proberen. (Klikken in het audio-uitgangssignaal geven aan dat dit is gebeurd.)

Wanneer alle gegevens zijn gelezen, wordt de interrupt geannuleerd, wordt de poort opnieuw ingesteld op de middenspanningswaarde van 128 en wordt het audiobestand gesloten.

Stel uw volume in op 50% voordat u het dac2.ino-script voor de eerste keer uitvoert. Dit zal te luid zijn, maar het is beter dan 100%!

Als uw volumeregeling omgekeerd werkt, verwissel dan de draden aan de tegenovergestelde uiteinden van de 10K-potentiometer.

Laat me weten hoe het klinkt.

Aanbevolen: