Musik und Geräusche mit einem Arduino abspielen? Kein Problem mit dem guten alten WAVE-Format, einem SD-Kartenleser und der TMRpcm Library.

Arduino WAV Musik SD-Karte Eins gleich vorweg: Hifi-Qualität darf man von der hier beschriebenen Lösung nicht erwarten. Aber als Low-Budget-Player für einfache Zwecke reicht es auf jeden Fall. Habe ich beispielsweise hier im Kunstprojekt RIBB@TACKING Bruce Lee – a C64 game tribute and homage verwendet.

Was man braucht

Natürlich einen Arduino; der hier beschriebene Aufbau wurde mit einem Uno getestet. Alle 328er basierten, also auch Nano, LilyPad, Pro etc. sollten gleichermaßen funktionieren.

Da die WAVE-Dateien irgendwo abgespeichert sein müssen, bietet sich ein SD Kartenleser an. Es gibt Breakout Boards mit Micro-SD-Karten Slot oder andere Shields, auf denen solch ein Slot bereits integriert ist, bspw. das Ethernet-Shield. Hier kommt ein sehr einfacher 1 EUR SD-Kartenleser von eBay zum Einsatz. Dazu eine (alte) SD Karte.

Damit man etwas hört, braucht es einen Verstärker. Bryan beschreibt in diesem Blog-Artikel, wie man mit einem einzigen Transistor nebst Widerstand (4,7 kOhm) einen simplen Verstärker zusammenschustert. Der BC548B hat nicht ausreichend verstärkt. Mit dem 2N3904 (eBay) macht es mehr Spaß.

Dazu natürlich ein Lautsprecher, da hatte ich noch einen mit 0,25 Watt 4 Ohm auf Halde liegen.

Verkabelung / Aufbau

Die Anbindung des SD-Kartenlesers erfolgt über die Hardware SPI Pins des Arduino. Welche Pins das genau sind, hängt vom Arduino-Typ ab. Die hier gezeigte Verkabelung sollte für alle 328er Typen (Nano, Uno, etc.) funktionieren. Chip Select ist frei wählbar; vgl. auch der weiter unten stehende Arduino Sketch. Die Schaltung auf dem Breadboard ist der erwähnte Ein-Transistor-Verstärker. Wenn man hier den Widerstand zwischen Arduino-Ausgang (Pin 9) und der Transistorbasis zu klein wählt, kann man nach kurzer Zeit auf dem Transistor Eier braten, da zu viel Strom durch die Collector-Emitter-Strecke fliesst.

Arduino-WAVE-Player-Steckplatine-Breadboard-450x345

Wagemutige können den Widerstand einfach mal ganz weglassen und sich an einer, dann, recht ordentlichen Beschallung nebst Transistorheizung erfreuen. Das sei hiermit also ausdrücklich nicht empfohlen.

Kartenleser PIN Arduino PIN Was ist das?
GND GND Ground
+5V 5V Volle Power! 🙂
MOSI 11 DATA, MOSI DATA, SDA, Hardware MOSI
MISO 12 MISO, Hardware MISO
CLK 13 CLK, SCL, Hardware SCK
CS 4 CS, Chip Select
GND GND Ground

In der Tabelle ist die PIN-Verkabelung noch einmal aufgeführt. Der verwendete SD-Kartenleser hat zwei GND-Anschlüsse und funktioniert auch nur zuverlässig, wenn tatsächlich beide mit Masse verbunden werden. Der Lautsprecherausgang ist, ebenso wie Chip Select, über den Arduino Sketch frei wählbar (hier PIN 9).

Zwei Blog Posts haben bei Verkabelung und Inbetriebnahme gut geholfen. Zum einen dieser Beitrag bei maxoffsky.com sowie insbesondere diese Anleitung auf instructables.com.

Format der SD Karte

Die verwendete SD-Library unterstützt prinzipiell die Dateisysteme FAT16 und FAT32. Es wird jedoch empfohlen, wenn möglich, FAT16 einzusetzen. Bei mir hat’s mit einer FAT32-formatierten SD-Karte nicht funktioniert, daher wollte ich sie “mal eben” auf FAT16 formatieren. Das geht auch mit MacOS Bordmitteln, ist aber etwas komplizierter, als erwartet. Dieser Post im Adafruit-Forum beschreibt den Weg in Englisch; hier in knappem Deutsch:

  1. SD-Karte in den Mac stecken.
  2. Terminal-Fenster öffnen. Bspw. mit CMD+Space, dort “terminal” tippen und Return.
  3. Geräte-ID finden. Dazu im Terminal df gefolgt von Return eingeben. Es erscheint eine Filesystem-Übersicht, die unter anderem die folgenden Informationen enthält. Ganz unten ist die SD-Karte “NO NAME” zu sehen. Wer auf Nummer sicher gehen will, gibt seiner Karte einen eindeutigen Namen. Dann kann man sie in dieser Übersicht schneller finden. Die in den folgenden Schritten benötigte Geräte-ID lautet /dev/disk3s1.
    Filesystem        Used Available Capacity   iused   ifree %iused  Mounted on
    /dev/disk1   909007896  65197032    94% 113689985 8149629   93%   /
    devfs              371         0   100%       642       0  100%   /dev
    map -hosts           0         0   100%         0       0  100%   /net
    map auto_home        0         0   100%         0       0  100%   /home
    /dev/disk3s1     20928   4172608     1%       512       0  100%   /Volumes/NO NAME
    
  4. SD-Karte unmounten (nicht auswerfen!). Im Terminal diskutil unmount /dev/disk3s1 gefolgt von Return eingeben. Dabei disk3s1 natürlich durch die eigene Geräte-ID ersetzen. Erfolgreiches unmounten wird bspw. mit Volume NO NAME on disk3s1 unmounted quittiert.
  5. FAT16 Filesystem auf SD-Karte schreiben. ACHTUNG! Der folgende Befehl löscht alle Daten auf dem Gerät. Wenn die Geräte-ID nicht die von der eingesteckten SD-Karte ist, sondern bspw. aus Versehen die der eingebauten Festplatte, dann wird diese gelöscht. U have been warned.
    Folgendes Kommando im Terminal eingeben und nicht vergessen die Geräte-ID anzupassen. newfs_msdos -F 16 /dev/disk3s1
    Ich habe alle Warnmeldungen, die der Befehl produziert hat, konsequent ignoriert und als Lohn der Mühe im Anschluß eine lauffähige FAT16-formatierte SD-Karte gehabt.

Format der WAVE Dateien

Die Library TMRpcm benötigt zum Abspielen die WAVE-Dateien im Format acht Bit, acht bis 32 kHz Sample Rate, mono. Im WIKI zur Library werden zwei Wege beschrieben, wie man iTunes oder Audacity verwenden kann, um aus dem musikalischen Quellmaterial das Zielformat zu generieren. Audacity ist prima, und so geht’s damit:

  1. Hauptmenü “Tracks”, dort “Stereo Track to Mono” wählen.
  2. Unten links die “Project Rate (Hz)” mit dem Popup auf 8000, 11025, 16000, 22050 oder 32000 setzen. Je niedriger die Sampling Rate, desto schlechter die Qualität.
  3. Hauptmenü “File”, dort “Export Audio…” und im File Selection Dialog unten als Format “Other uncompressed files” wählen. Dann “Options…” klicken und als Header “WAV (Microsoft)” sowie bei Encoding “Unsigned 8-bit PCM” wählen. OK.
  4. Datei mit “Save” speichern.

Dateinamen

Dateinamen müssen zwingend dem – aus alten MS-DOS Zeiten bekannten – 8.3-Format folgen, also maximal acht Zeichen für den Dateinamen gefolgt von Punkt und einer Endung mit drei Zeichen beispielsweise “NAME0001.EXT”. Der Dateiname kann kürzer als acht Zeichen sein, in keinem Fall aber länger. Die Wikipedia widmet dem 8.3 short filename (SFN) tatsächlich einen eigenen Artikel.

Arduino Sketch

Der folgende Sketch bindet zunächst die benötigten Libraries ein, definiert Chip Select- und Lautsprecherausgangs-PIN, initialisiert die SD-Karte mit SD.begin() und spielt im Erfolgsfall die Wave-Datei snakec16.wav direkt von der SD-Karte ab. Im Fehlerfall wird eine kurze Meldung über den seriellen Monitor ausgegeben.

#include 
#include 
#include 
#define CHIP_SELECT_PIN  4
#define SPEAKER_PIN      9
TMRpcm tmrpcm;

void setup( ) {
  tmrpcm.speakerPin = SPEAKER_PIN;
  Serial.begin( 9600 );
  while ( !Serial ) /*mt*/ ;
  if ( !SD.begin( CHIP_SELECT_PIN ) )
    Serial.println( "SD fail" );
  else {
    tmrpcm.play( "snakec16.wav" );
    delay( 5 );
  }
}

void loop( ) {
}

Wenn alles läuft…

…dann sollte das in etwa so aussehen, wie in dem Video.

Musik © Snake Charmer (Synapsis) / CC BY-ND 4.0

Join the conversation!

  • Klasse Bericht, leider lässt sich das Anschlussdiagramm nicht vergrößern.

    • Hallo Peter! Danke für die Blumen und den wichtigen Hinweis! Das sollte nicht so sein. Habe ich gerade korrigiert! Viele Grüße, Axel

    • Ahoi! Habe die Schaltung sowohl mit 4 als auch 8 Ohm Lautsprechern ausprobiert. Geht.
      Generell würde ich aber zur Verwendung eines kleinen Verstärkermoduls raten, bspw. sowas hier http://www.ebay.de/itm/LM386-200-Gain-Audio-Verstarker-Modul-Board-Arduino-/282104829385?hash=item41aec215c9:g:FDIAAOSwdzVXutKq
      Die kosten nicht die Welt und machen ausreichend krach. Ist natürlich, nach wie vor, kein Hifi, und falls du sowas in China orderst, würde ich gleich mehrere Module nehmen – da gibt es immer mal Blindgänger.

      • Hallo! Danke für diese super Anleitung! Ich würde aber gerne einen 80 Ohm Lautsprecher verwenden. Wie binde ich den Verstärker ein? Muss ich einfach den Transistor und den Widerstand entfernen und den Pluspol des Verstärkers an die 5V anschließen? Was mache ich mit dem Minuspol des Verstärkers?

        MfG

        • Hi Lars,
          ein achtzig(?) Ohm LS? Really? Bestimmt ein Typo. 😉 Schau’ Dir mal das Schaltbild in diesem Artikel http://zeropage.io/ribbattacking-bruce-lee-c64-game-tribute-and-homage/ an. Da habe ich so einen kleinen LM386-basierten Verstärker eingebaut. Der hat drei Eingänge: +5V und Masse ist klar und den Eingang für’s Tonsignal. Da geht der Speaker Pin (in meinem Sketch Pin 9) rein. Die beiden Ausgänge in den Lautsprecher.
          VGxl

  • Hallo! Super erklärt, bei mir funktioniert das ganze aber trotzdem noch nicht. Ich bekomme folgende Fehlermeldung:
    C:\Users\Elena\Documents\Arduino\musikkkk\musikkkk.ino: In function 'void setup()':

    C:\Users\Elena\Documents\Arduino\musikkkk\musikkkk.ino:16:25: warning: deprecated conversion from string constant to 'char*' [-Wwrite-strings]

    tmrpcm.play( "test" );

    Der Sketch wird trotzdem hochgeladen und Ich habe zu dem tmrpcm.play() noch ein Serial.println( “SD ok” ); eingebaut, welches in meinem Fall ausgegeben wird. Demnach muss das Lesen von der SD-Karte doch funktioniert haben, oder? Es wird trotzdem nichts über den Speaker ausgegeben. Den Speaker habe ich mit anderen Programmen getestet und der funktioniert dort einwandfrei. Ich habe für Testzwecke zwar erstmal nur einen piezo Speaker, aber das dürfte doch kein Problem sein, oder?

    Ich hoffe du kannst mir helfen, bin ein ziemlicher Anfänger und etwas aufgeschmissen…

    • Hallo ln(a),
      die Fehlermeldung beim Kompilieren weist Dich darauf hin, dass der implizite Cast “überholt” (deprecated) ist. Mag irgendwann vom Compiler nicht mehr unterstützt werden, aber jetzt ist es nur eine Warnung. Daher klappt auch der Upload auf den Arduino.
      Das ist also nicht die Ursache, warum es bei Dir nicht geht. Wenn “SD ok” ausgegeben wird, dann konnte er zumindest die SD Karte initialisieren. Das ist schonmal gut.
      Heisst Deine Wave-Datei auf der SD Karte wirklich nur “test”? Ohne Dateiendung?
      Viele Grüße
      Axel

  • Ich habe versucht die sache nachzubauen. In soweit funktioniert auch alles. Mit einem Uno.
    geht SUPER.
    Nur möchte ich einen mini pro verweden.
    und das geht gar nicht so gut.
    der Sound läuft langsam Warum auch immer.
    Nun bin ich auck kein Programiermeister soll heißen ich nehme den Sketch wie er ist.
    konnte mir jemand sagen ,was wo und wie
    Danke
    Thomas

    • Hallo Thomas,
      schön, dass es mit dem Uno geklappt hat.
      Ich habe nur eine Hypothese: Es könnte sein, dass die TMRpcm-Library nur auf 16MHz Arduinos vernünftig läuft. Falls Du einen einen 8MHz Pro Mini einsetzt, könnte es zu Problemen kommen.
      Mehr fällt mir aktuell nicht ein, warum es mit dem Pro Mini nicht geht bzw. langsam ist.
      Viele Grüße
      Axel

  • Es ist ein 16 mhz pro.
    ich möchte einen Alarm Sound in ein Modellschiff bringen und der Uno ist 1. zu groß und2. habe ich nur einen (immer zu Testzwecken.)

  • Hi,
    Könntet ihr mir sagen was ich für einen Befehl brauche damit die Audiodatei in Dauerschleife abgespielt wird?

    • Hi Henrik,

      die Library arbeitet generell asynchron, d.h. es gibt keinen Befehl, um eine Sound-Datei in einer Dauerschleife abzuspielen. Das muss man sich selber bauen. Ich würde es so machen:

      #include 
      #include 
      #include 
      #define CHIP_SELECT_PIN  4
      #define SPEAKER_PIN      9
      TMRpcm tmrpcm;
       void setup( ) {
        tmrpcm.speakerPin = SPEAKER_PIN;
        Serial.begin( 9600 );
        while ( !Serial ) /*mt*/ ;
        if ( !SD.begin( CHIP_SELECT_PIN ) )
          Serial.println( "SD fail" );
      }
      void loop( ) {
        if ( !audio.isPlaying( ) )
          tmrpcm.play( "sndfile.wav" );
      }
      

      Hab’s nicht getestet!
      VG Axel

  • Vielen Dank für deine ausführliche Anleitung. Das hat mir sehr geholfen.
    Bei meinem Aufbau funktioniert alles. Nur leider wird meine Datein in ungefährt doppelter Geschwindikgkeit ab gespielt, obwohl ich sie in 32000 hz und 8 bit wav umgewandelt hatte. Ich habe dann Versuche mit anderer Hz-Rate gemacht und fest gestellt, dass zw. 48000 und 82000 hz irrgendwo die richtige Hz-Zahl liegt für die korrekte Geschwindigkeit meiner Datein (~64000 hz). Das ist irrgenwie komisch. Hast du vlt. einen tipp, was ich noch umstellen kann? Liegt es an meinem Wav-Datei Format ? Oder kann ich die Taktung des Auslesens auch in der Libary/ bzw. im code einstellen?

    • Hi Alex,
      ich war bei meinen Versuchen über keine Möglichkeit gestolpert, die Abspielgeschwindigkeit über den Kode zu beeinflussen. Mir war jedoch aufgefallen, dass die Library sehr empfindlich reagiert, wenn das WAV-Format nicht exakt wie beschrieben ist: Also 8-32kHz, 8 Bit, Mono.
      Wenn Du sicher bist, dass das Format stimmt, könntest Du mit den Advanced Features experimentieren (https://github.com/TMRh20/TMRpcm/wiki/Advanced-Features); dort insbesondere:
      – buffsize variieren
      – stereo_or_16bit
      – use_timer2
      Kannst gerne mal schreiben, ob Du es lösen konntest!
      Viele Grüße
      Axel

  • Hi,
    echte coole Anleitung.
    Ist es möglich anstatt dem Lautsprecher einen Klinkeanschluss anzuschliessen, um damit einen Musikbox zu betreiben?
    Viele Grüße,
    Sebastian

    • Hi Sebastian,
      das sollte auf jeden Fall gehen! Da hättest Du den Vorteil, dass die Musikbox (wahrscheinlich) einen eigenen Verstärker hat und Du somit auch ordentlich was hören kannst. Das mit dem Transistor ist ja wirklich nur ein Notbehelf und eher was zum Testen.
      Viele Grüße
      Axel

  • Klappt soweit sehr gut. Nur brummt bzw knackt der Lautsprecher.
    Hast nen Tipp wie ich das weg bekomme?

    • Hi Thomas,
      bei mir knackt es, wenn ich Titel starte oder stoppe. Knackt es bei Dir ständig? Hast Du schon die Lautstärke über setVolume() variiert? Zum Thema hier auch zwei Anmerkungen des Programmierers von der zugehörigen WIKI Seite:
      1. Pop or click when playback is started or stopped:
      Ramps are built into the library to prevent popping when PWM is engaged, disabled, and between music tracks of the same
      sample rate. See the [Advanced Features wiki page](https://github.com/TMRh20/TMRpcm/wiki/Advanced-Features) for causes and fixes.
      2. Popping or clicking when music is playing
      If pops or clicks are heard during playback, it is most likely that buffer underruns are occurring or the volume is just too high.
      Ensure that #define SD_FULLSPEED is uncommented in pcmConfig.h. The value in #define buffSize 128 can be increased to provide
      additional memory for playback, which will reduce these issues. Audio can be encoded at a lower sample rate otherwise.
      Hoffe, das hilft Dir weiter!
      VG Axel

  • Hallo Axel,
    danke für den coolen Artikel!
    Habs auf Anhieb hinbekommen.
    Allerdings gibt es da ein Problem. Da ist – ab dem Zeitpunkt des Abspielens – ein sehr hohes, lautes Pfeifen dabei. Bei mir sinds je nach wav-file ca. 12 oder 16 kHz. Also so hoch, dass es jüngere Menschen eher hören als ältere. Auch in deinem Video ist ein deutliches 16khz Pfeifen dabei. (Kann man übrigens mit der PC Freeware AudioAnalyser leicht nachprüfen).
    Ich kann das so nicht nutzen – meine Familie stört das sehr =P
    Hat irgendwer eine Lösung für das Problem?
    LG Stefan

    • Hi Stefan,
      so, jetzt habe ich mich auch endlich Deines Kommentars entsonnen, der ja noch gar nicht freigegeben war. Sorry!
      Tatsächlich höre ich das Pfeifen überhaupt nicht. Was dann wohl bedeutet, dass ich irgendeine Alters-Schallmauer schon durchbrochen habe. Uäh!
      Ich habe auch wirklich gar keine Ahnung, was man dagegen tun könnte!
      Falls das hier einer liest: Hat jemand eine Lösung dafür?
      VGvAxel

  • Hey,
    Ich wollte die Schaltung für ein Schulprojekt verwenden, allerdings kommt nur ein rauschen aus dem Lautsprecher und nichts anderes. Auch wenn ich den Lautsprecher ohne Transistor (BC547B) anschließe kommt nur ein rauschen, aber eben leiser. Der Lautsprecher hat 0.1W und eine Impedanz von 8 Ohm.
    Hatten andere das Problem auch oder bin ich der einzige bzw. erste?

    • Hi Viktor,
      bisher hat hier keiner von einem solchen Phänomen berichtet.
      Bist Du _ganz_ sicher, dass das Dateiformat der WAV-Files korrekt ist?
      Das solltest Du auf jeden Fall noch einmal überprüfen.
      Viele Grüße
      Cpt. Zeropage

  • Hallo
    Sehr schönes Programm bei mir funktioniert auch alles.
    Ich habe nur ein Problem und zwar ist die Sound Qualität extrem schlecht und zwar egal ob mit oder ohne wiederstand. Ich habe auch schon einen anderen Lautsprecher ausprobiert, Ergebnis war dasselbe.
    Ich benutze einen leicht anderen Code aber ich glaube nicht das dies die Ursache meines Problems ist.
    Mir ist bewusst das man keine hohen Ansprüche an die Qualität haben sollte aber der Ton ist extrem verzerrt und rauschend.
    Vielleicht kann mir ja jemand weiterhelfen?
    Lg

  • Hallo
    Bei Funktioniert an sich alles an dem Programm aber die Sound Qualität ist extrem schlecht.
    Ich habe bereits einen anderen Lautsprecher ausprobiert was aber nicht geholfen hat.
    Irgendwelche Tipps?
    Lg Moritz

    • Ja, die Soundqualität mit dieser Lösung ist sehr schlecht. Es gibt aber mittlwerweile bestimmt viel bessere Lösungen, um mp3s mit einem Arduino abzuspielen! VGxl

Leave a Reply

Your email address will not be published. Required fields are marked *