tas2580

Musik mit Diskettenlaufwerken

tas2580  

Vor einigen Tagen hat mir eine Freundin ein Link zu einem Youtube Video geschickt in dem jemand auf alten Diskettenlaufwerken Musik gespielt hat und gemeint ich sollte sowas doch auch mal bauen. Zufällig hatte ich noch zwei alte Laufwerke und ein Netzgerät hier rumliegen. Zum ansteuern habe ich dann einfach kurz das Rasberry Pi das ich als Mediacenter verwende missbraucht.

Die Hardware

Als erstes benötigt man ein bisschen Hardware, das meiste davon findet man auf dem Sperrmüll oder bei der Sammlung alter Computer im Keller. Ich verlinkte trotzdem einfach mal alles was man benötigt.

Wenn man die benötigte Hardware zusammen hat kann man mit dem basteln beginnen.

Netzgerät modifizieren

Normalerweise benötigt man ein Mainboard um ein ATX-Netzgerät einzuschalten. Mit einem kleinen Trick kann man das Netzteil aber auch ohne Mainboard starten.

ATX Netzteil
Mit einem Stück Lötzinn überbrückter einschalter eines ATX Netzgerätes.

Dazu verbindet man einfach das grüne Kabel mit dem schwarzen rechts daneben. Ich habe dazu einfach ein Stück Lötzinn in den Stecker gesteckt, alternativ kann man natürlich auch eine Lüsterklemme verwenden. Wenn man jetzt das Netzgerät einsteckt und einschaltet sollte sich der Lüfter anfangen zu drehen.

Um die Diskettenlaufwerke mit Strom zu versorgen benötigt man genügend Stecker für Diskettenlaufwerke am Netzgerät. Da bei mir nur einer vorhanden war habe ich einfach die Kabel für die Festplatten umgebaut. Hier benötigt man immer nur das gelbe und das schwarze Kabel daneben, an die man einfach Jumper Kabel anklemmt die man dann nachher mit der Stromzufuhr der Diskettenlaufwerke verbinden kann. Atlernativ kann man natürlich auch Stecker für Diskettenlaufwerke von anderen Netzgeräten benutzen.


Diskettenlaufwerk(e) modifizieren

Die Diskettenlaufwerke müssen zu erst mal mit Strom versorgt werden, dazu verwendet man entweder den passenden Stecker vom Netzgerät oder schließt seine Jumperkabel die man mit dem Netzgerät verbunden hat an die beiden rechten Pins der Strombuchse an.

Nun geht es an die Pins die das Laufwerk steuern. Floppy Pins Das Diskettenlaufwerk hat hinten 36 Pins in zwei Reihen, in der oberen Reihe befinden sich die Pins mit den geraden Nummern und in der unteren Reihe die mit den ungeraden. Um das Laufwerk einzuschalten müssen Pin 11 und Pin 12 miteinander verbunden werden. Ich habe dazu einfach einen Jumper der sonst in Festplatten oder auf irgend welchen Karten im PC verwendet werden benutzt. Nachdem man die Pins miteinander verbunden hat sollte das Licht am Laufwerk leuchten.

Floppy Pins
Diskettenlaufwerk mit angeschlossenen Kabeln.

Nun muss man die Kabel zur Steuerung des Motors im Laufwerk anschließen. Die Pins 17 und 19 sind die Masse Pins, hier steckt man je Pin ein Jumperkabel ein und verbindet sie miteinander. Am besten verbindet man zusätzlich noch ein 3. Kabel mit den Kabelenden das man später in die GPIO Ports des Rasberry Pi stecken kann. Pin 18 steuert die Richtung des Motors, hier muss auch wieder ein Jumper Kabel angeschlossen werden. Pin 20 ist der step Pin an den auch ein Kabel angeschlossen werden muss.

Wenn alles richtig angeschlossen ist müsste man 3 Kabel in der Hand halten, die Masse Pins werden ja miteinander verbunden und ergeben ein Kabel. Wenn man mehrere Diskettenlaufwerke verwendet kann man wiederum alle Massekabel zu einem verbinden.

Laufwerke am Rasberry Pi anschließen

Zum Schluss muss man die Jumper Kabel von den Laufwerken noch mit den GPIO Pins des Rasberry Pi verbinden. Das Masse Kabel kann man an einen beliebigen Masse Pin anschließen, ich habe dazu bei mir Pin 6 verwendet, die anderen sollen aber auch funktionieren. Das Kabel das von Pin 18 am Diskettenlaufwerk kommt verbindet man mit Pin 11 am Rasberry Pi und das Kabel das von Pin 20 am Laufwerk kommt mit Pin 12 am Rasberry Pi. Wenn man mehrere Diskettenlaufwerke verwendet sucht man sich einfach freie GPIO Pins und schließt dort die entsprechenden Kabel an. Wichtig ist das man sich die Nummern merkt da man die Später zur Konfiguration benötigt.

Wie die Pin Belegung des Raspberry Pi aussieht findet man zu genüge bei Google. Wenn man alles richtig verbunden hat ist man mit dem Hardware Teil fertig und kann sich der Software widmen.

Die Software

Als erstes muss man auf der SD Karte des Rasberry Pi das Betriebssystem installieren, Raspbian, Anleitungen wie man das installiert gibt es im Internet genug.

Als nächstes benötigt man einen Compiler um den Code zum Abspielen der Musik zu kompilieren.

apt-get install g++

Nun benötigt man die Software um die Diskettenlaufwerke anzusteuern. Hier habe ich zwei Lösungen gefunden die bei mir funktioniert haben.

Lösung 1

Im Rasberry Pi Forum gibt es eine recht einfache Lösung mit der man nur ein Diskettenlaufwerk ansteuern kann. Die Musik dazu muss im Code direkt angegeben werden, man muss also für neue Lieder die Noten erst in Code umwandeln und das Programm danach neu kompilieren. Der im Code enthaltene Star Wars Soundtrack klingt dafür aber auf Anhieb sehr gut.

Zur Installation des Programms legt man sich am besten erst mal einen neuen Ordner an in dem man eine Datei mit dem Namen main.cpp anlegt und mit folgendem Inhalt füllt:

/* --------------------------------------
 * Written by Scott Vincent
 * 16 Feb 2014
 * --------------------------------------
 */
#include 
#include 
#include 
#include 

// pin 11 = wiringPi Pin 0. Use this for motor direction.
const int dirPin = 0;

// pin 12 supports pwm mode but it turns out I didn't need pwm mode in the end!
// pin 12 = wiringPi Pin 1. Use this for stepper motor.
const int stepPin = 1;

// Define an octave with naturals and sharps (Zz = rest)
enum { Cn, Cs, Dn, Ds, En, Fn, Fs, Gn, Gs, An, As, Bn, Zz };

// Define another one with flats and remaining sharps
enum { Bs, Df, Dn2, Ef, En2, Es, Gf, Gn2, Af, An2, Bf, Bn2, Zz2 };

/**
 * Frequencies in hundredths of Hz, e.g. middle A = 44000
 * 4 Octaves with 12 notes per octave, i.e. C to B
 */
const int freq[4][12] = {
   { 13081,13859,14683,15556,16481,17461,18500,19600,20765,22000,23308,24694 },
   { 26163,27718,29366,31113,32963,34923,36999,39200,41530,44000,46616,49388 },
   { 52325,55437,58733,62225,65925,69846,73999,78399,83061,88000,93233,98777 },
   { 104650,110873,117466,124451,131851,139691,147998,156798,166122,176000,186466,197553 }
};

/**
 * Frequency (in Hz) is converted to Floppy Delay using the formula:
 *   314000 / frequency = floppy delay
 * so middle A = 314000 / 440 = 714
 *
 * Lowest realistic note is delay = 1550
 * Highest realistic note is delay = 210
 */
const int floppyConv = 31400000;

// Calculate all our floppy delays at the start
int floppyDelay[4][12];

// Song1 is the C major scale (note, octave, length)
const int song1_tempo = 120;
const int song1[][3] = {
   { Cn, 1, 1 },
   { Dn, 1, 1 },
   { En, 1, 1 },
   { Fn, 1, 1 },
   { Gn, 1, 1 },
   { An, 1, 1 },
   { Bn, 1, 1 },
   { Cn, 2, 1 },
   { -1, -1, -1 }
};


// Song2 is The Imperial March from Star Wars (note, octave, length)
const int song2_tempo = 104 * 8;
const int song2[][3] = {
   { Gn, 1, 8 },      // Bar 1
   { Gn, 1, 8 },
   { Gn, 1, 8 },
   { Ef, 1, 6 },
   { Bf, 1, 2 },

   { Gn, 1, 8 },
   { Ef, 1, 6 },
   { Bf, 1, 2 },
   { Gn, 1, 16 },

   { Dn, 2, 8 },
   { Dn, 2, 8 },
   { Dn, 2, 8 },
   { Ef, 2, 6 },
   { Bf, 1, 2 },

   { Gf, 1, 8 },      // Bar 4
   { Ef, 1, 6 },
   { Bf, 1, 2 },
   { Gn, 1, 16 },

   { Gn, 2, 8 },
   { Gn, 1, 6 },
   { Gn, 1, 2 },
   { Gn, 2, 8 },
   { Gf, 2, 6 },
   { Fn, 2, 2 },

   { En, 2, 2 },
   { Ds, 2, 2 },
   { En, 2, 4 },
   { Zz, 0, 4 },
   { Gs, 1, 4 },
   { Cs, 2, 8 },
   { Bs, 2, 6 },
   { Bn, 1, 2 },

   { Bf, 1, 2 },      // Bar 7
   { An, 1, 2 },
   { Bf, 1, 4 },
   { Zz, 0, 4 },
   { Ef, 1, 4 },
   { Gf, 1, 8 },
   { Ef, 1, 6 },
   { Gf, 1, 2 },

   { Bf, 1, 8 },
   { Gn, 1, 6 },
   { Bf, 1, 2 },
   { Dn, 2, 16 },

   { Gn, 2, 8 },
   { Gn, 1, 6 },
   { Gn, 1, 2 },
   { Gn, 2, 8 },
   { Gf, 2, 6 },
   { Fn, 2, 2 },

   { En, 2, 2 },      // Bar 10
   { Ds, 2, 2 },
   { En, 2, 4 },
   { Zz, 0, 4 },
   { Gs, 1, 4 },
   { Cs, 2, 8 },
   { Bs, 2, 6 },
   { Bn, 1, 2 },

   { Bf, 1, 2 },
   { An, 1, 2 },
   { Bf, 1, 4 },
   { Zz, 0, 4 },
   { Ef, 1, 4 },
   { Gf, 1, 8 },
   { Ef, 1, 6 },
   { Bf, 1, 2 },

   { Gn, 1, 8 },
   { Ef, 1, 6 },
   { Bf, 1, 2 },
   { Gn, 1, 16 },

   { -1, -1, -1 }
};


/**
 *
 */
static void resetMotor()
{
   // To reset head position move back 10 then forward 5
   digitalWrite(dirPin, LOW);
   for (int i=0; i < 10; i++){
      digitalWrite(stepPin, HIGH);
      digitalWrite(stepPin, LOW);
      delay(1);
   }

   digitalWrite(dirPin, HIGH);
   for (int i=0; i < 5; i++){
      digitalWrite(stepPin, HIGH);
      digitalWrite(stepPin, LOW);
      delay(1);
   }

   delay(400);
}


/**
 *
 */
static int init()
{
   if (wiringPiSetup() == -1){
      printf("Failed to initialize wiringPi\n");
      return 1;
   }

   pinMode(stepPin, OUTPUT);
   pinMode(dirPin, OUTPUT);

   resetMotor();

   for (int octave = 0; octave < 4; octave++){
      for (int note = 0; note < 12; note++){
         floppyDelay[octave][note] = floppyConv / freq[octave][note];
      }
   }

   return 0;
}


/**
 *
 */
static void playNote(int note, int octave, int length)
{
   static int dir = 1;
   int pause = floppyDelay[octave][note] * 10;

   int endTime = millis() + length;
   while (millis() < endTime){
      digitalWrite(dirPin, dir);
      if (dir == 0)
         dir = 1;
      else
         dir = 0;

      digitalWrite(stepPin, HIGH);
      digitalWrite(stepPin, LOW);
      delayMicroseconds(pause);
   }
}


/**
 *
 */
static void rest(int length)
{
   int endTime = millis() + length;
   while (millis() < endTime){
      delay(5);
   }
}


/**
 * song[note_num][note, octave, length]
 */
static void playSong(const int song[][3], const int tempo)
{
   // Convert tempo in BPM to millisecs
   int noteLen = 60000 / tempo;

   for (int i = 0; song[i][0] != -1; i++){
      int length = song[i][2] * noteLen;
      if (song[i][0] == Zz){
         rest(length);
      }
      else {
         playNote(song[i][0], song[i][1], (7 * length) / 8);
         rest(length / 8);
      }
   }
}


/**
 *
 */
int main()
{
   if (init() != 0){
      printf("init failed - Exiting\n");
      return 1;
   }

   playSong(song2, song2_tempo);

   return 0;
}

Im oberen Teil kann man angeben an welchen Pins das Laufwerk angeschlossen ist, wenn man das Laufwerk wie hier beschrieben an die Pins 11 und 12 angeschlossen hat muss man hier nichts ändern. Wenn man andere Pins verwendet muss man die entsprechenden Pin IDs angeben.

Danach muss man das Programm kompilieren, dazu führt man auf der Konsole in dem Ordner in dem sich die Datei befindet folgendes aus:

g++ main.cpp -lwiringPi

Jetzt erhält man eine Datei mit dem Namen a.out, wenn man die mit ./a.out aufruft sollte das Laufwerk den Star Wars Soundtrack abspielen.

Lösung 2

Auf Github gibt es ein Programm das mehrere Laufwerke zum abspielen der Musik benutzt. Außerdem können damit MIDI Dateien abgespielt werden. Zum installieren des Programms erstellt man sich einen Ordner und läd den Code dort rein, alternativ kann man das auch einfach per Git machen.

git clone https://github.com/Kingdread/floppymusic.git

Jetzt muss man das Programm noch kompilieren, dazu führt man in dem Ordner in dem sich der Code befindet einfach make aus. Sollte man einen neuen Raspberry Pi verwenden muss man make MODEL=PI2 ausführen.

Danach muss man noch eine Datei mit dem Namen drives.cfg anlegen oder die drives.cfg.example umbenennen. In der Datei wird angegeben welche Pins für die Laufwerke verwendet werden sollen. Wenn man mehrere Laufwerke verwenden möchte muss man für jedes Laufwerk einen Eintrag in eine neue Zeile schreiben.

Jetzt kann man mit ./floppymusic MIDIFILE.mid MIDI Dateien auf dem Laufwerk abspielen.

Um ein besseres Ergebnis zu bekommen muss man evtl. den d Parameter mit angeben, bei mir klingt es mit d 1 am besten, der Befehl sieht dann also folgendermaßen aus:

./floppymusic -d 1 -l MIDIFILE.mid

Kommentare


Kommentar schreiben

URLs werden automatisch umgewandelt.
[b]DEIN TEXT[/b] für Fett gedruckt
[quote]DEIN ZITAT[/quote] für Zitate
[code]DEIN CODE[/code] für Code
captcha