Enregistrement audio Arduino (Mega): 9 étapes (avec images)

Enregistrement audio Arduino (Mega): 9 étapes (avec images)

Table des matières:

Anonim

Enregistrement audio sur votre carte Audino Mega SD.

Le fichier audio peut être lu sur une application audio standard ou analysé octet par octet.

Cet Instructable vous montrera comment une entrée audio peut être répétée ajoutée à une mémoire tampon de 512 octets, puis transférée sur une carte SD en temps réel. La période enregistrée peut être modifiée.

La fréquence d'échantillonnage est de 9,4 kHz et la sortie du fichier wav est de 8 bits, mono. Bien que non hi-fidelity, la qualité sonore est parfaitement adéquate.

Le fichier wav enregistré peut être sauvegardé sous forme de données tabulées. Il peut également être affiché sous forme de simple graphique défilant sur le moniteur.

Tous les fichiers sont horodatés à l'aide d'un code temporel Unix envoyé à partir du moniteur série.

L’inspiration de cet article est venue de la lecture d’Amanda Ghassaei: http: //www.instructables.com/id/Arduino-Audio-Inp …

Ma dernière mise à jour du programme à la fin de cet instructable, augmente la fréquence d'échantillonnage à 19 KHz avec une amélioration significative de la qualité audio.

Vous pouvez également être intéressé par mes instructables sur:

UNE haute vitesse Oscilloscope Arduino: http: //www.instructables.com/id/Arduino-High-speed …

Ppose de fichiers wav de l'Arduino: http: //www.instructables.com/id/Arduino-playing-wa …

Inévitablement, la technologie de la carte SD s'est déjà améliorée. J'ai testé avec une carte SD Sandisk Ultra 8 Go. C'est nettement plus rapide que la carte Kingston de 4 Go avec laquelle j'ai commencé. En utilisant mon logiciel mis à jour, je peux enregistrer à 38,3 KHz, sans dégradation de la qualité. (08/04/2014)

Provisions:

Étape 1: Exigences

Arduino Mega 2560

Les composants suivants fonctionnent - les alternatives peuvent être viables (avec le programme peaufiné - je vous laisse ça!)

LCD Keypad Shield http: //www.hobbytronics.co.uk/arduino-lcd-keypad -…

MicroSD Breakout Board régulée avec Logic Conversion V2

http: //www.hobbytronics.co.uk/microsd-card-regula …

Carte mémoire Micro SD 4 Go http: //www.hobbytronics.co.uk/microsd-card-regula …

Préamplificateur de microphone

couplé à un diviseur de potentiel pour centrer la tension entre le rail Arduino 0-5 V

Amanda Ghassaei a publié un circuit à l'adresse http: //www.instructables.com/id/Arduino-Audio-Inpu …

J'ai conçu le mien avec des commandes de basses, d'aigus et de volume. Cependant, il existe de nombreux modèles de préamplis sur le Web.

Étape 2: Les spécifications

Prise en charge des mémoires série, LCD, SD et flash.

Série fixée à 115200 bauds.

Horodatage au format Linux à partir du moniteur série.

L'entrée série peut initier une nouvelle capture de données en utilisant la commande "à nouveau".

L'entrée série peut définir le nombre de kilo-octets de données lues et donc la durée du fichier audio en utilisant la commande 'alter'.

Sortie en série des données après demande de saisie - commande 'read' - la sortie peut être arrêtée avec la commande 'q'

Graphique de base tracé sur le moniteur série.

Données brutes enregistrées dans un fichier compatible wav.

Les données brutes traduites dans la commande de fichier tabulée 'write'.

Mise à jour répétée de 60 s en eeprom. L’écran LCD s’assombrit au cours de la mise à jour de l’eprom

PWM 3 Onde carrée disponible pour les tests avec la commande 'test'.

L'entrée 2 définie haute évite d'attendre que la série soit configurée.

Une utilisation unique peut être possible avec un réglage de programme incluant la relocalisation des octets de stockage de temps (variable ememory). Je vous laisse ce travail.

Remarque: la meilleure qualité audio est obtenue avec une entrée variant autour de la valeur de moyenne tension de 128. C'est important!

Sortie LCD des informations de base.

Lcd adc port spécifié avec la variable lcdport.

Prise en charge du bouton LCD:

Sélectionnez initie un nouvel échantillon. Gauche modifie le numéro d'échantillon en kilo-octets - puis +10, inférieur -10, gauche -1, droite +1.

Étape 3: Commencer

Connectez le blindage du clavier LCD.

Connecter le lecteur de carte SD

0, 5V

CLK à la broche 52

D0 à la broche 50

D1 à la broche 51

CS à épingler 53

J'ai monté le lecteur SD sur un morceau de bande avec des broches de passage pour correspondre aux points de connexion requis.

(Détails à suivre)

Vous voudrez probablement tester les lecteurs de cartes lcd et sd en utilisant des exemples de scripts à partir du point de vente.

Cela parait un peu décontracté, mais tout est détaillé ailleurs:

Construisez un préampli micro et connectez-le à travers un diviseur potentiel, comme décrit par Amanda.

Ou utilisez un autre design.

Je vous recommande d'inclure une résistance variable dans la section du diviseur de potentiel afin que l'entrée puisse être soigneusement ajustée pour se centrer autour d'une valeur d'entrée mesurée de 128 (La moitié de la tension d'alimentation 0-5. Sur mon PC, "5V" est inférieur à 5V lorsqu'il est alimenté par l'USB.)

L’écran LCD que j’ai spécifié utilise le port analogique zéro pour les boutons LCD. Vous devez donc connecter votre entrée audio à A1.

Étape 4: Monter le lecteur de carte SD

La carte SD peut être facilement montée sur un morceau de bande et localisée à l’aide de broches de passage.

J'ai utilisé deux jeux de connecteurs à broches (haut et bas) pour stabiliser la carte.

Les connexions sont côte à côte sur le Arduino Mega. Ainsi, les pistes de cartes en cuivre entre les connexions doivent être Couper. J'ai utilisé une lame de scie à main junior (pas dans le cadre de la scie) avec une goupille de positionnement éjectée. Assurez-vous d'utiliser une bonne qualité bien lame dentée. Il est également très utile pour nettoyer l’espace entre les bandes de cuivre. J'ai trouvé plus facile de couper la piste de 5V tout en coupant les deux prochaines. (Voir photo 4) Il est alors simple de souder un fil sur la coupe.

Pour les broches, j'ai utilisé une bande de broches standard. La longueur des broches du côté cuivre a été ajustée à la profondeur de la douille Arduino avant la soudure. La longueur des broches de rechange du côté des composants a été coupée et limée propre après la soudure.

Un connecteur d'en-tête à huit voies a été soudé et un connecteur à broches à 90 degrés a été branché. Un petit morceau de goujon fin a été utilisé pour soutenir le lecteur. Un petit trou percé dans le coin de la planche permet à une vis de retenir le goujon, bien que la colle soit acceptable.

J'ai ajouté un en-tête de broche à la ligne 0V sur la bande. Cela garantissait que je n'avais pas perdu la disponibilité du point de connexion 0V.

Le lecteur de carte SD aura besoin d’un en-tête de socket soudé à 90 degrés.

L’alimentation 5V peut être collectée avec un câble volant sur l’une des broches entre 21 et 22 (marquée 5V).

Vérifiez que vous avez coupé toutes les pistes montrées dans l'image, y compris les pistes coupées avec un foret!

Vérifiez votre mise en page et la soudure avant brancher!

Étape 5: Format de fichier Wave

Un en-tête de fichier wave est un bloc de 44 octets.

L'en-tête est au début du fichier wav.

Le bloc d'en-tête doit être initialisé globalement avec:

tête d'onde en octets 44;

Les données audio suivent l'en-tête.

Pour un fichier 8 bits mono, les données de fichier wav mono sont comprises entre 0 et 255.

Le script lit le port A1 et interprète l'audio entrant comme une tension comprise entre 0 et 255. Parfait!

Seules 4 sections de l'en-tête doivent être mises à jour lorsque le fichier wav est enregistré.

Celles-ci sont présentées sous forme de sections commentées dans l'image.

Les octets à l'offset 4 contiennent la longueur des données + la longueur de l'en-tête - 2 * 4 octets

Ou plus simplement le nombre de données +36.

Chaque section commentée est un nombre de 4 octets.

Les quatre octets apparaissent avec l'octet le moins significatif en premier - il s'agit du "format little endian".

La routine suivante acceptera une valeur longue et l'écrira à un point spécifié dans l'en-tête wav sous la forme de 4 octets successifs:

void headmod (valeur longue, emplacement d'octet) {

// écrit quatre octets pendant longtemps

tempfile.seek (emplacement); // trouve l'emplacement dans le fichier

octet tbuf 4;

tbuf 0 = valeur & 0xFF; // lo octet

tbuf 1 = (valeur >> 8) & 0xFF;

tbuf 2 = (valeur >> 16) & 0xFF;

tbuf 3 = (valeur >> 24) & 0xFF; // salut octet

tempfile.write (tbuf, 4); // écrit le tampon de 4 octets

}

Étape 6: Configuration de l'interruption qui lit le port analogique

Nous pouvons configurer une interruption de sorte qu'un port analogique soit lu à plusieurs reprises.

(Voir l'article d'Amanda pour plus de détails.)

Mon sous-programme "startad" utilise un pré-scalaire de 128.

Cela crée une interruption répétée afin que le port A1 soit lu en permanence à 9,4 kHz.

Le sous-programme d'interruption a une double fonction:

1) Si le compteur est moins que le nombre de lectures:

  • Ajoutez l'octet de données audio au tampon de 512 octets.
  • lorsque la mémoire tampon est pleine, écrivez-la en une fois sur la carte mémoire. 512 octets sont la taille optimale pour une sauvegarde rapide des données. Réinitialise le nombre de tampons à zéro pour le prochain octet audio entrant.

2) Quand le compteur est égal à le nombre de lectures requis:

Arrêtez l'interruption à nouveau

  • Calculez combien de temps le processus a pris, fréquence etc.
  • Utilisez la fréquence et la taille du fichier pour mettre à jour l'en-tête du fichier wave.
  • Libérez le port analogique A1 et activez le port A0 pour que les boutons LCD fonctionnent.

Étape 7: Réglage de la date et de l'heure et enregistrement sournois

L'Arduino peut garder le temps, mais doit être indiqué un point de départ.

Quand il est redémarré, il faut le répéter. (Sauf si vous avez une horloge en temps réel).

L'heure peut être spécifiée sous la forme d'une chaîne de temps unix, qui correspond au nombre de secondes écoulées depuis "l 'époque standard du 1/1/1970".

La console série peut être utilisée pour envoyer un T suivi de la chaîne de temps unix.

T1403524800 représente 12h le 3 juin 2014

Voir le sous-programme "waitfordate" et "processSyncMessage"

if (Serial.find (TIME_HEADER)) {// Cherchez le T

pctime = Serial.parseInt (); // extrait l'heure

if (pctime> = DEFAULT_TIME) {// vérification limitée que l'heure est après default_time

setTime (pctime); // Synchronise l'horloge Arduino avec l'heure reçue sur le port série

Ce site propose des valeurs d'heure Unix:

Les valeurs de temps peuvent être stockées dans la mémoire eeprom, qui est conservée après la réinitialisation.

Les valeurs stockées sont historiques, elles ne sont pas mises à jour lors de la réinitialisation.

Cependant, ils sont utiles comme point de départ pour de nouveaux noms de fichiers. Lorsque le script est exécuté sans horodatage, la valeur temporelle précédente est utilisée avec un ajout de 60 secondes.

writeeeprom et readeeprom permettent le stockage et la récupération des chaînes de temps.

L'heure est écrite dans la mémoire de l'eeprom toutes les 60 secondes.

Sachez que la mémoire eeprom a une limite de réutilisation - mais les sockets de la carte vont probablement s’user en premier.

Étape 8: Qu'est-ce que la sortie et comment est-elle contrôlée?

Un dossier appelé adlog est utilisé pour les données.

La sortie suivante est disponible:

1) Un fichier wav pour chaque lecture. Le nom du fichier est au format ddhhmmss.wav. La capture audio peut être répétée avec la commande "again".

2) Suite à la commande série "write" de la console série, un fichier texte est généré avec le numéro et la valeur de données en colonnes. Ceci est délimité par des virgules et peut facilement être importé dans d'autres programmes pour l'analyse graphique. Le format du fichier est ddhhmmss.txt

3) La commande "read" de la console série produit une représentation graphique défilant verticalement de l'audio. Cela peut être arrêté en envoyant un "q" depuis la console.

Les boutons lcd peuvent également être utilisés pour enregistrer un nouveau fichier audio et modifier le nombre d'octets enregistrés. Select lance un nouveau fichier et reste à gauche la fonction "select" qui met à jour le numéro de données. Le port lcd A0 est lu et, selon que le bouton haut, bas, gauche ou droit est enfoncé, le numéro de données est modifié.

La commande de console série "test" génère une onde carrée sur PWM3. Ceci est utile pour tester sans microphone ni pré-ampli.

Si PWM2 est élevé, le programme n'attend pas d'horodatage de la console série. La date et l'heure ne seront plus actuelles. Cependant, cela est utile si le port USB n’est pas connecté.

Étape 9: Mise à jour du programme

J'ai réussi à augmenter la fréquence d'acquisition des données à 19 KHz.

Cela a nécessité l’utilisation de deux mémoires tampon de 512 octets (double mise en mémoire tampon) et d’une réécriture des sections de boucle d’interruption et de boucle vide.

Le son est beaucoup plus propre.

J'ai également testé à 38 kHz, avec des résultats très prometteurs. Cependant, à cette fréquence, des périodes d’attente tampon ponctuelles sont présentes. Il est probable que les améliorations futures de la conception de la carte SD et de la vitesse de la fonction de bibliothèque SD permettront de surmonter ce problème. Pour ceux qui veulent expérimenter, modifiez le prescalaire variable juste avant la configuration vide.

J'ai mis en place bufa et bufb.

Dans la routine d'interruption, je mets un drapeau appelé déjà prêt - C’est vrai quand on écrit sur bufa, faux pour bufb.

Le drapeau écris le est true lorsqu'une écriture est requise et définie sur false lorsque la carte SD est terminée.

Lorsqu'un tampon est plein (buffcount == BUF_SIZE):

  • Je vérifie si la carte SD a fini d'écrire. Dans ce cas, writeit == false et je remets le pointeur de mémoire tampon à zéro, je mets l'indicateur de mémoire tampon en place et place la marque writeit à la valeur true.
  • Si la carte Sdcard est encore en train d'écrire, je relis (bufcount--; et counter--;) et quitte l'interruption.

Une fois que j'ai le nombre correct de lectures, je ferme l'interruption, écris le dernier bloc de données et range.

La majorité des données sont écrites dans la boucle vide:

if (writeit) {// les données sont prêtes à être écrites

si (déjà) {

tempfile.write (bufb, BUF_SIZE); // écrit le bloc de données de bufb

} autre {

// initie l'écriture de bloc depuis bufa

tempfile.write (bufa, BUF_SIZE); // écrit le bloc de données

}

writeit = false; // signale que l'écriture est terminée

}