Arduino Sound-Maschine Tutorial

Mit dem Microcontroller Arduino kann man wahlweise ein Mini-Piano, einen Synthesizer oder einen Sequencer bauen – oder alle drei Varianten aufeinmal. Auf einer kleinen Holzbox haben wir für unsere Ausstellung im Makerspace einen Sound-Arduino gebaut. Hier wollen wir euch zeigen, wie das funktioniert und was dafür nötig ist.

Grundlagen zur Sounderzeugung

Bei Arduino lässt sich sehr leicht Sound erzeugen. Einfach folgendes Programm kopieren, hochladen, Lautsprecher an Pin 3 und GND (Minus) anschließen und los gehts.

int Lautsprecher_Pin = 3;



void setup() {  
  pinMode(Lautsprecher_Pin, OUTPUT);
}

void loop() {
   tone(Lautsprecher_Pin, 110, 15);
   delay(1000);
}

Was ihr hören solltet, ist ein sich alle Sekunde wiederholender kurzer tiefer Ton.

Jetzt kann die Klangerzeugung aber auch in schneller Abfolge verschiedene Töne abspielen. Zum Beispiel so:

  tone(soundOut, 147, 30);
  delay(40);
  tone(soundOut, 220, 30);
  delay(40);
  tone(soundOut, 294, 30);
  delay(40);
  tone(soundOut, 349, 30);
  delay(40);
  tone(soundOut, 440, 30);
  delay(40);

So lassen sich nette Soundeffekte erzeugen. Das Beispiel ist einem YouTube-Video entnommen, an das wir unseren Sound-Erzeuger angelehnt haben. Link zum Video

Unsere Sound-Maschine

Jetzt fehlen noch folgende Dinge bis zur fertigen Soundmaschine

  • Ein Knopf für das durchschalten der Modi (Notenmodus, Synthesizer, Abspielen einer vorprogrammierten Sequenz).
  • Drei LEDs zum Anzeigen, in welchem Modus man sich gerade befindet.
  • 5 Knöpfe für die Noten zum Spielen

Verkabelt wird das Ganze folgendermaßen: Die Buttons werden mit einer Seite an GND (Minus) gelötet/verkabelt und die andere Seite geht an den jeweiligen Pin am Arduino (siehe hierfür den kompetten Code unten). Die Pins werden dafür in den Modus „INPUT_PULLUP“ gesetzt. Das funktioniert zuverlässig und man braucht keinen extra Widerstand.

Apropos Widerstand: Ein 330 Ohm Widerstand wird an die Minus-Seite der LEDs gepackt und die Plus-Seite wird an den jeweiligen Pin des Arduino verkabelt. Eigentlich müsste man die Widerstand für jede LED-Farbe einzeln ausrechnen und inidividuelle Widerstände nutzen, aber es geht eben auch mit einem gemeinsamen Widerstand für 3 LEDs, wenn sowieso immer nur eine davon leuchten soll.

Der fertige Code für die Sound-Maschine sieht so aus. Unten gibt es noch ein paar Erläuterungen.


long distance;
int echoNote = 220;


// A C D E G -> A-Moll Pentatonik
int buttonOne = 9;
int noteOne = 110; // A2

int buttonTwo = 10;
int noteTwo = 131; // C3

int buttonThree = 11; 
int noteThree = 147; // D3

int buttonFour = 12; 
int noteFour = 165; // E3


int buttonFive = 13;
int noteFive = 196; // G3


int buttonMode = 8;

int ledOne = 4;
int ledTwo = 5;
int ledThree = 6;

int soundOut = 3;

int mode = 0; // 0 = note, 1 = synth, 2 = sequencer

int bpm = 145;


void setup() {

  pinMode(buttonOne, INPUT_PULLUP);
  pinMode(buttonTwo, INPUT_PULLUP);
  pinMode(buttonThree, INPUT_PULLUP);
  pinMode(buttonFour, INPUT_PULLUP);
  pinMode(buttonFive, INPUT_PULLUP);
  pinMode(buttonSix, INPUT_PULLUP);
  pinMode(buttonSeven, INPUT_PULLUP);
  pinMode(buttonEight, INPUT_PULLUP);
  pinMode(buttonNine, INPUT_PULLUP);

  pinMode(buttonMode, INPUT_PULLUP);
  
  pinMode(soundOut, OUTPUT);
}


void loop() {


// ##################  NOTEN Modus ###########################

if (mode == 0) {
  digitalWrite(ledOne, HIGH);
  digitalWrite(ledTwo, LOW);
  digitalWrite(ledThree, LOW);
  
  if (digitalRead(buttonMode) == LOW) {
    mode = 1;
    digitalWrite(ledOne, LOW);
    digitalWrite(ledTwo, HIGH);
    digitalWrite(ledThree, LOW);
    delay(200); //debounce
  }

  if (digitalRead(buttonOne) == LOW)
  {
      tone(soundOut, noteOne, 15);
      delay(10);
    }
if (digitalRead(buttonTwo) == LOW)
  {
    tone(soundOut, noteTwo, 15);
    delay(10);
  }

  if (digitalRead(buttonThree) == LOW)
  {
    tone(soundOut, noteThree, 14);
    delay(12);
  } 

  if (digitalRead(buttonFour) == LOW)
  {
    tone(soundOut, noteFour, 15);
    delay(10);
  }

  if (digitalRead(buttonFive) == LOW)
  {
    tone(soundOut, noteFive, 15);
    delay(10);
  }


 } // ende mode synth

// ################### SYNTH Modus ############################

if (mode == 1) {

  if (digitalRead(buttonMode) == LOW) {
    mode = 2;
    digitalWrite(ledOne, LOW);
    digitalWrite(ledTwo, LOW);
    digitalWrite(ledThree, HIGH);
    delay(200); // debounce
  }

 if (digitalRead(buttonOne) == LOW) {
  for(int freq = 160; freq > 110; freq = freq - 5) {
      tone(soundOut, freq, 40);
      delay(40);
    }
 }

if (digitalRead(buttonTwo) == LOW) {
  tone(soundOut, 147, 30);
  delay(40);
  tone(soundOut, 220, 30);
  delay(40);
  tone(soundOut, 294, 30);
  delay(40);
  tone(soundOut, 349, 30);
  delay(40);
  tone(soundOut, 440, 30);
  delay(40);
}


 if (digitalRead(buttonThree) == LOW)  {
    tone(soundOut, 196, 30);
    delay(40);
    tone(soundOut, 294, 30);
    delay(40);
    tone(soundOut, 392, 30);
    delay(40);
    tone(soundOut, 494, 30);
    delay(40);
    tone(soundOut, 587, 30);
    delay(40);
  }

  if (digitalRead(buttonFour) == LOW)  {
    tone(soundOut, 220, 30);
    delay(40);
    tone(soundOut, 330, 30);
    delay(40);
    tone(soundOut, 440, 30);
    delay(40);
    tone(soundOut, 523, 30);
    delay(40);
    tone(soundOut, 659, 30);
    delay(40);
  }

  if (digitalRead(buttonFive) == LOW)  {
    tone(soundOut, 262, 30);
    delay(40);
    tone(soundOut, 392, 30);
    delay(40);
    tone(soundOut, 523, 30);
    delay(40);
    tone(soundOut, 659, 30);
    delay(40);
    tone(soundOut, 784, 30);
    delay(40);
  }

    
} // ende mode synth



// #################### SEQUENCER Modus ###################

if (mode == 2) {
 
  //seq1: Bass
  for (int i = 0; i<2; i++) {
    tone(soundOut, 110, 10);
    delay(60000/bpm*4/4);
    tone(soundOut, 110, 10);
    delay(60000/bpm*4/4);
    tone(soundOut, 110, 10);
    delay(60000/bpm*4/4);
    tone(soundOut, 110, 10);
    delay(60000/bpm*4/4);
  }

  // seq2: bass & clap  
  tone(soundOut, 110, 10);
  delay(60000/bpm*4/4);
  tone(soundOut, 110, 10);
  delay(10);
  tone(soundOut, 267, 15);
  delay(60000/bpm*4/4-10);

  tone(soundOut, 110, 10);
  delay(60000/bpm*4/4);
  tone(soundOut, 110, 10);
  delay(10);
  tone(soundOut, 267, 15);
  delay(60000/bpm*4/4-10);



  // seq3: Variation, zweimal abgespielt
    for (int i = 0; i<2; i++) {

      tone(soundOut, 110, 10);
      delay(60000/bpm*4/8);

      tone(soundOut, 110, 10);
      delay(60000/bpm*4/8);  

      tone(soundOut, 267, 15);
      delay(60000/bpm*4/8);

      delay(60000/bpm*4/8);

      tone(soundOut, 110, 10);
      delay(60000/bpm*4/8);
      delay(60000/bpm*4/8);

      tone(soundOut, 267, 15);
      delay(60000/bpm*4/8);
      delay(60000/bpm*4/8);
    }

  // letzte Sequence:    
  tone(soundOut, noteOne, 80);
  delay(60000/bpm*4/8);

  tone(soundOut, noteTwo, 80);
  delay(60000/bpm*4/8);

  tone(soundOut, noteThree, 80);  
  delay(60000/bpm*4/8);

  tone(soundOut, noteFour, 80);
  delay(60000/bpm*4/8);
  
  tone(soundOut, noteFive, 120);  
  delay(60000/bpm*4/8);

  tone(soundOut, noteFour, 80);
  delay(60000/bpm*4/8);

  tone(soundOut, noteThree, 80);
  delay(60000/bpm*4/8);

  tone(soundOut, noteOne, 80);
  delay(60000/bpm*4/8);

  tone(soundOut, noteTwo, 80);
  delay(60000/bpm*4/8);

  mode = 0; // Der Modus wechselt automatisch zurück in den Noten-Modus

 } // ende mode sequencer



} // ende loop


Der Code ist nicht schön. Aber er ist sehr simpel und lässt sich mit etwas Zeit und Mühe gut verstehen und nachbauen. Solltet ihr irgendwo hängen, kommt doch einfach mal im Makerspace vorbei und wir klären das direkt vor Ort. Ihr könnt euch auch gerne eine eigene Sound-Maschine bei uns bauen. Wir haben alles dafür vor Ort (Lötkolben, Widerstände, Kabel, Arduino und noch mehr).

Was ist „debouncen“? Antwort: Wenn man den Modus-Button drückt, dann wird der Modus direkt von z.B. 0 auf 1 geändert. Dann kommen wir in der if-Schleife an, die den Synth-Modus enthält. Wir als Mensch sind aber sehr langsam und haben den Finger immer noch auf dem Modus-Button. Das Programm erkennt: Ah, da drückt jemand den Modus-Button, ich schalte direkt in den nächsten Modus. Wir schaffen es also gar nicht in den Modus „Synth“ zu schalten, weil dort direkt weiter in Modus 2 geschaltet wird. Um das zu verhindern, setzen wir nach dem Erkennen des Button-Drückens einfach eine kurze Programmpause von 200 ms mittels „delay(200);“. Bis dahin sollten wir den Finger vom Knopf genommen haben und wir können gemütlich im Synth-Modus loslegen. Die Pause muss man eventuell größer oder kleiner ansetzen, je nachdem wie das Handhabungsgefühl ist.

Solltet ihr eine Melodie programmieren wollen, dann geht das sehr einfach mit folgenden Noten. Die Noten können an der Stelle der Frequenz einfach genutzt werden, also so: tone(soundOut, NOTE_C4, 40) -> es wird über den ganz oben definierten Pin „soundOut“ die Frequenz 262 für 40 ms wiedergegeben.


#define NOTE_B0 31
#define NOTE_C1 33
#define NOTE_CS1 35
#define NOTE_D1 37
#define NOTE_DS1 39
#define NOTE_E1 41
#define NOTE_F1 44
#define NOTE_FS1 46
#define NOTE_G1 49
#define NOTE_GS1 52
#define NOTE_A1 55
#define NOTE_AS1 58
#define NOTE_B1 62
#define NOTE_C2 65
#define NOTE_CS2 69
#define NOTE_D2 73
#define NOTE_DS2 78
#define NOTE_E2 82
#define NOTE_F2 87
#define NOTE_FS2 93
#define NOTE_G2 98
#define NOTE_GS2 104
#define NOTE_A2 110
#define NOTE_AS2 117
#define NOTE_B2 123
#define NOTE_C3 131
#define NOTE_CS3 139
#define NOTE_D3 147
#define NOTE_DS3 156
#define NOTE_E3 165
#define NOTE_F3 175
#define NOTE_FS3 185
#define NOTE_G3 196
#define NOTE_GS3 208
#define NOTE_A3 220
#define NOTE_AS3 233
#define NOTE_B3 247
#define NOTE_C4 262
#define NOTE_CS4 277
#define NOTE_D4 294
#define NOTE_DS4 311
#define NOTE_E4 330
#define NOTE_F4 349
#define NOTE_FS4 370
#define NOTE_G4 392
#define NOTE_GS4 415
#define NOTE_A4 440
#define NOTE_AS4 466
#define NOTE_B4 494
#define NOTE_C5 523
#define NOTE_CS5 554
#define NOTE_D5 587
#define NOTE_DS5 622
#define NOTE_E5 659
#define NOTE_F5 698
#define NOTE_FS5 740
#define NOTE_G5 784
#define NOTE_GS5 831
#define NOTE_A5 880
#define NOTE_AS5 932
#define NOTE_B5 988
#define NOTE_C6 1047
#define NOTE_CS6 1109
#define NOTE_D6 1175
#define NOTE_DS6 1245
#define NOTE_E6 1319
#define NOTE_F6 1397
#define NOTE_FS6 1480
#define NOTE_G6 1568
#define NOTE_GS6 1661
#define NOTE_A6 1760
#define NOTE_AS6 1865
#define NOTE_B6 1976
#define NOTE_C7 2093
#define NOTE_CS7 2217
#define NOTE_D7 2349
#define NOTE_DS7 2489
#define NOTE_E7 2637
#define NOTE_F7 2794
#define NOTE_FS7 2960
#define NOTE_G7 3136
#define NOTE_GS7 3322
#define NOTE_A7 3520
#define NOTE_AS7 3729
#define NOTE_B7 3951
#define NOTE_C8 4186
#define NOTE_CS8 4435
#define NOTE_D8 4699
#define NOTE_DS8 4978