Table des matières:

Lire des fichiers audio (Wav) avec un Arduino et un DAC : 9 étapes
Lire des fichiers audio (Wav) avec un Arduino et un DAC : 9 étapes

Vidéo: Lire des fichiers audio (Wav) avec un Arduino et un DAC : 9 étapes

Vidéo: Lire des fichiers audio (Wav) avec un Arduino et un DAC : 9 étapes
Vidéo: Как воспроизводить аудио с помощью Arduino, аудиоплеера PCM с помощью Arduino | Аудиоплеер своими руками без SD-карты 2024, Juillet
Anonim
Lecture de fichiers audio (Wav) avec un Arduino et un DAC
Lecture de fichiers audio (Wav) avec un Arduino et un DAC
Lecture de fichiers audio (Wav) avec un Arduino et un DAC
Lecture de fichiers audio (Wav) avec un Arduino et un DAC
Lecture de fichiers audio (Wav) avec un Arduino et un DAC
Lecture de fichiers audio (Wav) avec un Arduino et un DAC

Lisez le fichier audio wav à partir de votre carte SD Audino. Ce Instructable va vous montrer comment un fichier wav sur votre SdCard peut être lu via un circuit simple à un haut-parleur.

Le fichier wav doit être en 8 bits mono. Je n'ai eu aucun problème à lire des fichiers 44 KHz.

Bien qu'il ne s'agisse pas d'une haute fidélité, la qualité sonore est très satisfaisante.

Le moniteur série est utilisé pour sélectionner le fichier. Les fichiers doivent être dans un dossier appelé adlog.

Cette instructable découle d'un projet antérieur où j'ai enregistré des enregistrements wav sur la SdCard:

Le circuit utilise un convertisseur numérique-analogique (DAC) 8 bits bon marché et un amplificateur audio à puce unique.

Les sections clés pour la configuration des interruptions sont extraites de l'excellent article d'Amanda Ghassaei:

Étape 1: Exigences

Conditions
Conditions
Conditions
Conditions

Arduino - J'utilise le Mega, mais il n'y a aucune raison pour que l'Uno ne fonctionne pas.

Lecteur SdCard - le programme est configuré pour: MicroSD Breakout Board Regulated with Logic Conversion V2

Voir cette instructable pour les détails de configuration SdCard:

DAC0832 LCN- un excellent convertisseur numérique-analogique 8 bits- Quelques livres.

LM386 N-1 Op amp-pas cher comme des puces

Prise de puce à 20 voies

Prise de puce à 8 voies

Alimentation 9 volts - une batterie fera l'affaire.

Référence de tension LM336 2,5 V

Condensateur 10 uF * 3 (toute tension supérieure à 9 V)

résistance de 10 ohms

Condensateur 50nF- (Ou quelque part près de 47nF, 56nf, 68nf- fera l'affaire)

Condensateur 220uF

haut-parleur 64 ohms

Potentiomètre linéaire 10K

Câble pour relier les 8 lignes de données entre l'Arduino et le circuit-

Sur la Uno les 8 connexions sont alignées, sur la Mega elles sont par paires.

Sur le Mega, j'ai utilisé un câble plat à 10 voies avec un en-tête IDC à 10 voies. (2 fils sont de rechange)

Connecteurs femelles pour sortie 0V, 9V et DAC

Panneau de bande de cuivre, soudure, fil, couteaux, etc.

Étape 2: les spécifications

Les spécifications
Les spécifications

Série réglée à 115200 bauds.

Un support est en place pour la carte Breakout MicroSD Hobbytronics utilisant un Mega. La sélection de puce et d'autres ports changeront entre Mega et Uno.

Les fichiers Wav doivent exister dans un répertoire appelé adlog. N'hésitez pas à le nommer autrement et à réorganiser le codage nécessaire.

Le fichier wav doit être en 8 bits mono. J'ai testé jusqu'à 44KHz.

Le moniteur série affiche les fichiers wav dans le dossier adlog. Les noms de fichiers sont envoyés depuis la ligne de sortie du moniteur.

La taille du fichier n'est limitée que par la taille de la carte Sd.

Étape 3: Commencer

Commencer
Commencer

Connectez le lecteur de carte SD. Ce sont les connexions pour le Mega.

0, 5V

CLK à la broche 52

D0 à la broche 50

D1 à la broche 51

CS à la broche 53

(Voir le site Web des fournisseurs pour la connexion au port Uno)

Vous voudrez tester que votre carte fonctionne à ce stade - utilisez les scripts fournis par le fournisseur.

Nous devons faire un petit circuit

Nous allons envoyer un flux d'octets audio depuis l'Arduino.

Ces nombres sont compris entre 0 et 255. Ils représentent la tension.

Le silence est 127-128.

255 est un haut-parleur conique dur dans un sens.

0 est le cône du haut-parleur dur dans l'autre sens.

Ainsi, l'audio est enregistré sous forme de nombres enregistrés, ce qui crée des tensions variables, ce qui crée des cônes de haut-parleur en mouvement.

Nous pouvons envoyer les numéros sur 8 lignes sur l'Arduino, simultanément, en utilisant un "port".

Si nous alimentons les 8 lignes dans un convertisseur numérique-analogique, il fait ce qu'il dit sur l'étain et produit une tension analogique qui est proportionnelle au nombre numérique.

Tout ce que nous avons à faire est alors de couper la tension dans un petit amplificateur opérationnel, puis dans un haut-parleur.

Étape 4: Le petit circuit

Le Petit Circuit
Le Petit Circuit
Le Petit Circuit
Le Petit Circuit
Le Petit Circuit
Le Petit Circuit
Le Petit Circuit
Le Petit Circuit

Le DAC0832 LCN

Il s'agit d'un superbe convertisseur numérique-analogique 8 bits bon marché. (CAD)

Il peut être entièrement contrôlé avec un ensemble de lignes d'échantillonnage de données et de maintien de données.

Ou il peut être configuré pour tout faire automatiquement dans "Flow through operation".

Pour citer le manuel:

Le simple fait de mettre à la terre CS, WR1, WR2 et XFER et de lier ILE haut permet aux deux registres internes de suivre les entrées numériques appliquées (flux) et d'affecter directement la sortie analogique du DAC.

OK, c'est quatre connexions au jeu de puces basses et une à 9V - facile.

Nous ne voulons pas de tensions négatives, donc le manuel dit que nous devons utiliser le "mode de commutation de tension" et ils fournissent le schéma.

Tout ce que nous avons à faire est de substituer un petit ampli audio au lieu de celui qu'ils suggèrent.

L'ampli audio LM386-N

Le manuel de l'ampli fournit un schéma de pièces minimum - offrant un gain de 20 (beaucoup trop pour nous - mais il a un contrôle de volume).

Il suffit d'ajouter un condensateur entre le DAC et l'ampli pour n'amplifier que les signaux AC.

Nous devons également ajouter quelques condensateurs à proximité de la broche d'alimentation de chacune de nos puces, sinon nous aurons un bourdonnement de notre alimentation 9V.

Étape 5: Sortez le fer à souder

Sortez le fer à souder
Sortez le fer à souder
Sortez le fer à souder
Sortez le fer à souder
Sortez le fer à souder
Sortez le fer à souder

Comme le circuit est simple je n'ai pas l'intention de rendre compte coup par coup.

Voici quelques repères:

  • Préparez un morceau de panneau de cuivre au moins 28 par 28 trous. (Oui, je sais que les chirurgiens du cerveau peuvent le rendre plus petit)
  • Si vous avez l'intention de le monter avec des vis, prévoyez-les au début !
  • Montez les puces sur les sockets. Insérez les puces uniquement lorsque tout a été vérifié.
  • Gardez les fils d'entrée éloignés de la sortie.
  • Respectez la polarité correcte des condensateurs.
  • Reportez-vous au schéma pour la vue de base de la référence de tension LM336. La jambe de réglage n'est pas utilisée et peut être coupée.
  • Notez la connexion directe à la broche 8 du DAC- C'est très utile pour les tests.
  • Je me suis connecté à l'Audino avec un câble plat et un connecteur IDC à 10 voies.
  • Sur l'Uno, les connexions sont en ligne droite - vous constaterez peut-être que la disposition des 8 connexions d'entrée en une seule ligne droite vous permet de vous connecter à l'Arduino avec un connecteur à 8 voies acheté et prêt à l'emploi,

Lorsque c'est fait, vérifiez la soudure et vérifiez les écarts entre les pistes de cuivre.

Je trouve une lame de scie à métaux junior de 36 tpi très utile pour nettoyer les débris. Je retire les goupilles de positionnement de la lame et glisse la pointe de la lame dans le rail. Évidemment, la lame n'est pas dans un cadre.

Étape 6: Tester le DAC

Tester le DAC
Tester le DAC

Laissez la connexion entre le circuit et l'Arduino désactivée.

Réglez le contrôle du volume sur votre circuit à mi-chemin.

Allumez l'alimentation 9V DC à votre nouveau circuit.

Vérifiez que le circuit est ok, je ne peux accepter aucune responsabilité pour votre circuit !

Éteindre

Connectez votre circuit à l'Arduino.

Sur le Mega, utilisez les broches 22-29. (PORTA) Ne confondez pas les deux broches 5V ci-dessus !

Sur l'Uno, utilisez les broches 0-7. C'est PORTD

Connectez le 0V de votre alimentation au 0V de l'Arduino.

Mettez sous tension.

Ouvrez ce programme de test DAC_TEST

Pour l'ONU, remplacer toutes les références de PORTA à PORTD

Remplacez DDRA par DDRD - cette instruction définit les 8 lignes à sortir en une seule fois. C'est le registre de direction des données.

Réglez votre moniteur série sur 115200.

Connectez un voltmètre entre la sortie DAC et OV

Le programme réglera la sortie sur 255 - toutes les lignes allumées - tension maximale.

Sortie 128- moitié tension maximale.

Sortie 0-tension nulle (ou probablement presque nulle).

Il passera ensuite au niveau du bit: 1, 2, 4, 8, 16, 32, 64, 128

La tension doit augmenter régulièrement.

Si la tension retombe alors que le nombre augmente, vous avez probablement deux des fils d'interconnexion inversés.

Vous devriez également entendre le haut-parleur cliquer doucement lorsque la tension change

Étape 7: Lecture de l'en-tête Wav

Lecture de l'en-tête Wav
Lecture de l'en-tête Wav

Les fichiers Wav sont enregistrés avec une fréquence et une taille de données spécifiées.

Cette information est contenue dans un en-tête de 44 octets au début d'un fichier wav.

Bien que certains logiciels étendent l'en-tête (après l'octet 35), l'emplacement de la taille des données est plus difficile à localiser.

Pour lire l'en-tête, nous créons un tampon et copions le début du fichier.

La fréquence est stockée sur 4 octets à partir de 24 octets dans le fichier.

// fréquence de lecture spécifiée dans l'en-tête du fichier wav

octet headbuff[60]

fichier temporaire.seek(0);

fichier temporaire.read(headbuf, 60);

retval=headbuf[27];

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

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

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

Serial.print(F("Fréquence des fichiers "));

Serial.print(retval);

La meilleure façon de trouver les informations sur la taille des données est de rechercher le mot « données » dans l'en-tête.

Extrayez ensuite les 4 octets qui le suivent, qui constituent la valeur longue

long retour non signé;

int mypos=40;

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

if (headbuf == 'd') {

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

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

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

// enfin nous l'avons

mypos=i+4;

i=60;

}

}

}

}

}

fichier temporaire.seek(mypos);

retval=headbuf[mypos+3];

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

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

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

OK, nous avons la longueur et la fréquence des données !

Les données audio suivent les 4 octets constituant la valeur de longueur des données.

Étape 8: Interrompre, Interrompre…

Interrompre, Interrompre…
Interrompre, Interrompre…

Nous utilisons les informations de fréquence pour créer une interruption logicielle à ou près de la fréquence requise.

L'interruption ne peut pas toujours être définie avec précision, mais elle est suffisante. La fréquence lue dans le fichier est transmise au sous-programme setintrupt.

void setintrupt(float freq){float bitval=8; // 8 pour les temporisateurs 8 bits 0 et 2, 1024 pour le temporisateur 1 octet

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

// La valeur setocroa nécessite une soustraction de -1. Cependant en ajoutant 0,5 tours au 0,5 le plus proche

// La résolution du timer est limitée

// En fin de compte déterminé par l'ampleur de bitval

cli(); // désactiver les interruptions // définir l'interruption timer2

TCCR2A = 0; // mettre tout le registre TCCR2A à 0

TCCR2B = 0; // idem pour TCCR2B

TCNT2 = 0; // initialise la valeur du compteur à 0

// définit le registre de correspondance de comparaison pour les incréments de fréquence (Hz)

OCR2A = sétocroe; // = (16*10^6) / (fréquence*8) - 1 (doit être <256)

// activer le mode CTC

TCCR2A |= (1 << WGM21); // Définir le bit CS21 pour le pré-échelonneur 8

TCCR2B |= (1 << CS21); // activer l'interruption de comparaison de minuterie

// TIMSK2 |= (1 << OCIE2A); // cela fonctionne, tout comme la ligne suivante

sbi(TIMSK2, OCIE2A); // activer l'interruption sur le timer 2

sei(); // activer les interruptions

Les lecteurs avisés auront repéré sbi(TIMSK2, OCIE2A)

J'ai configuré quelques fonctions (acquises sur Internet) pour définir et effacer les bits de registre:

// Définit pour effacer les bits du registre#ifndef cbi

#définir cbi(sfr, bit) (_SFR_BYTE(sfr) &= ~_BV(bit))

#fin si

// Définit pour le réglage des bits de registre

#ifndef sbi

#définir sbi(sfr, bit) (_SFR_BYTE(sfr) |= _BV(bit))

#fin si

Ces fonctions fournissent un appel facile pour définir ou effacer l'interruption.

L'interruption est donc en cours d'exécution, que pouvons-nous lui faire faire ?

Étape 9: interruptions et double mise en mémoire tampon

Interruptions et double tampon
Interruptions et double tampon
Interruptions et double tampon
Interruptions et double tampon

A 22 Khz, un octet de données audio est émis toutes les 0,045 ms

512 octets (la taille du tampon) sont lus en 2,08 ms.

Ainsi, le tampon ne peut pas être lu à partir de la carte SDC en un cycle d'écriture.

Cependant, 512 octets sont écrits sur le port en 23,22 ms.

Donc, tout ce que nous avons à faire est de configurer un nouveau fichier lu à chaque fois que le tampon se vide et nous avons suffisamment de temps pour obtenir les données avant qu'un nouveau bloc de données ne soit requis… En supposant que nous utilisions deux tampons, en vidant un au fur et à mesure que nous remplissons un autre.

Il s'agit d'une double mise en mémoire tampon.

La lecture du fichier sera ralentie par l'interruption répétée, mais cela se fera.

J'ai configuré deux tampons de 512 octets appelés bufa et bufb.

Si le drapeau aready est vrai, nous lisons à partir de porta, sinon nous lisons à partir de portb

Lorsque la position du tampon (bufcount) atteint la taille du tampon (BUF_SIZE 512), nous définissons un indicateur appelé readit sur true.

La routine de boucle void recherche ce drapeau et lance une lecture de bloc:

if(readit){if (! aready){

// lancer la lecture du bloc SDCard dans bufa

fichier temporaire.read(bufa, BUF_SIZE);

} autre {

// lance la lecture du bloc SDCard dans bufb

fichier temporaire.read(bufb, BUF_SIZE);

}

readit=false;

}

Lorsqu'elle a terminé, la routine signale readit=false.

Dans la routine d'interruption, nous devons vérifier que la boucle void est terminée en vérifiant si readit== false.

Ceci étant le cas, nous signalons qu'une autre lecture est requise et basculons l'indicateur aready pour changer de tampon.

Si la carte SD est toujours en train de lire, nous devons revenir en arrière d'une lecture (counter--; bufcount--;) et quitter l'interruption pour réessayer plus tard. (Les clics dans le signal de sortie audio impliquent que cela s'est produit.)

Lorsque toutes les données sont lues, l'interruption est annulée, le port réinitialisé à la valeur de tension moyenne de 128 et le fichier audio fermé.

Avant d'exécuter le script dac2.ino pour la première fois, réglez votre volume sur 50 %. Ce sera trop fort, mais c'est mieux que 100 % !

Si votre contrôle de volume fonctionne à l'envers, échangez les fils aux extrémités opposées du potentiomètre 10K.

Faites-moi savoir comment ça sonne.

Conseillé: