Zum Inhalt springen
Ein Button Piano

Lektion 16 – Ein-Tasten-Piano

    Hast Du Lust, ein richtiges Musikinstrument mit Arduino zu bauen? Na dann geht’s los!

    Benötigte Bauteile

    Bauteile Piezo Button

    Benötigte Bauteile

    Bauplan Piezo Button

    Wir bauen jetzt ein Piano mit nur einer Taste. Ich würde sagen, das Piano soll einen Ton auslösen, wenn die Taste gedrückt wird. Wenn sie losgelassen wird, soll der Ton wieder ausgehen.

    int speakerPin = 9;
    int buttonPin = 11;
    
    void setup() {
      pinMode(buttonPin, INPUT);
    }
    
    void loop() {
      if (digitalRead(buttonPin)==HIGH){
        tone(speakerPin, 440);
      } else {
        noTone(speakerPin);
      }
    }

    Wie schaffen wir es jetzt, dass wir damit eine Melodie spielen können? In der vorherigen Lektion waren wir der Lösung schon sehr nah. Da haben wir die for-Schleife benutzt, um einen Ton des Arrays zu spielen. Wie wäre es, wenn der Button dieses Mal das Zählen übernehmen würde? Dazu brauchen wir aber noch einen kleinen Trick. Wir müssen nämlich dieses Mal genau wissen, wann der Button gedrückt wird und nicht, wann er einfach nur an ist. Wenn wir nur:

    if (digitalRead(buttonPin)==HIGH){
    	ton = ton + 1;
    }

    fragen, dann wird diese Abfrage so lange wahr sein, bis wir den Button loslassen. Wenn wir hierbei versuchen würden, eine Variable hoch zuzählen, wäre die bei einer Sekunde schon bei fast unendlich.


    Sieh dir jetzt meinen neuen Arduino-Videokurs an: Jetzt ansehen!


    Wir müssen also nicht nur wissen, ob der Button gedrückt ist, sondern auch, ob er direkt davor nicht gedrückt war. Das geht mit einer Boolean-Variable.

    Boolean

    Variablen vom Typ Boolean kennen zwei Zustände, nämlich true (wahr) und false (falsch). Wenn wir eine Variable haben, die buttonPressed, also Taster gedrückt heißt, dann könnte diese den aktuellen Zustand des Tasters speichern.

    1. Beim Programmstart ist der Taster ist nicht gedrückt, die Variable buttonPressed wird auf falsch gesetzt.
    2. Geprüft wird in der ersten if-Abfrage jetzt nicht nur nach digitalRead(buttonPin)==HIGH, sondern auch darauf, ob buttonPressed== false ist. Das kann man mit dem doppelten et-Zeichen machen (&&).
    3. Ist das der Fall, wird buttonPressed auf true gesetzt.
    4. Wenn der Button nicht gedrückt ist, wird buttonPressed auf false gesetzt.

    Im Programmtext sieht das so aus:

    boolean buttonPressed = false;
    
    int speakerPin = 9;
    int buttonPin = 11;
    
    void setup() {
      pinMode(buttonPin, INPUT);
    }
    
    void loop() {
      if ((digitalRead(buttonPin)==HIGH)&&(buttonPressed==false)){
        buttonPressed=true;
    
    
      } 
      if (digitalRead(buttonPin)==LOW){
        buttonPressed=false;
    
    
      }
    }

    Jetzt können wir eine Zählervariable mitlaufen lassen. Wenn diese zu groß wird, muss sie wieder auf 0 gesetzt werden. Das erledigt die dritte if-Abfrage:

    int tonAnzahl = 27;
    int ton = 0;
    
    boolean buttonPressed = false;
    
    int speakerPin = 9;
    int buttonPin = 11;
    
    void setup() {
      pinMode(buttonPin, INPUT);
    }
    
    void loop() {
      if ((digitalRead(buttonPin)==HIGH)&&(buttonPressed==false)){
        buttonPressed=true;
    
        ton=ton+1;
      } 
      if (digitalRead(buttonPin)==LOW){
        buttonPressed=false;
    
      }
      if (ton>=tonAnzahl){
        ton=0;
      }
    }

    Und nun brauchen wir nur noch die Tonausgabe hinzuzufügen:

    int frequenzen[] = {262, 294, 330, 349, 392, 392, 440, 440, 440, 440, 392, 440, 440, 440, 440, 392, 349, 349, 349, 349, 330, 330, 392, 392, 392, 392, 262};
    int tonDauer[]= {200, 200, 200, 200, 400, 400, 200, 200, 200, 200, 800, 200, 200, 200, 200, 800, 200, 200, 200, 200, 400, 400, 200, 200, 200, 200, 800};
    int tonAnzahl = 27;
    int ton = 0;
    
    boolean buttonPressed = false;
    
    int speakerPin = 9;
    int buttonPin = 11;
    
    void setup() {
      pinMode(buttonPin, INPUT);
    }
    
    void loop() {
      if ((digitalRead(buttonPin)==HIGH)&&(buttonPressed==false)){
        buttonPressed=true;
        tone(speakerPin, frequenzen[ton]);
        ton=ton+1;
      } 
      if (digitalRead(buttonPin)==LOW){
        buttonPressed=false;
        noTone(speakerPin);
      }
      if (ton>=tonAnzahl){
        ton=0;
      }
    }

    9 Gedanken zu „Lektion 16 – Ein-Tasten-Piano“

    1. Fehlt da nicht irgendwie die ‚tonDauer‘ im letzten Abbild ?

      konkret aus:
      void loop() {
      if ((digitalRead(buttonPin)==HIGH)&&(buttonPressed==false)){
      buttonPressed=true;
      tone(speakerPin, frequenzen[ton]);
      ton=ton+1;
      }

      ergänzt um ein ‚ delay(tonDauer[ton]); ‚ im if-Teil ergibt:

      void loop() {
      if ((digitalRead(buttonPin)==HIGH)&&(buttonPressed==false)){
      buttonPressed=true;
      tone(speakerPin, frequenzen[ton]);
      delay(tonDauer[ton]);
      ton=ton+1;
      }

      1. Hallo Simon,

        Du hast ein gutes Auge. Die Frage ist gut! Hier die Antwort: Den tone()-Befehl gibt es in zwei Ausführungen:

        • tone(Pin, Tonhöhe)
        • tone(Pin, Tonhöhe, Dauer)

        Wir benutzen hier die obere Variante, da der Ton so lange erklingen soll, wie die Taste gedrückt ist. Ich hoffe, das hilft Dir weiter.

        Liebe Grüße

        Stefan

      2. Ne ne, Simon hat da schon recht!!!
        Mal ausprobieren! Mit erster Variante bekommst du den Melodieablauf niemals hin!
        Der Ton bleibt aber mit der Eingabe von Simon auch, so lange die Taste gedrückt ist!

        1. Hallo,
          ich denke, der Punkt von Simon ist noch immer nicht korrigiert. Im obigen Script fehlt die Verwendung der Variable „tonDauer“. Damit ertönt der Ton immer in der Länge des Tastendrucks.
          Schöner klingt es mit der in „tonDauer“ hinterlegten Dauer. Ich habe mein Script wie folgt angepasst:

          if ((digitalRead(buttonPin) == HIGH) && (buttonPressed == false)) {
          buttonPressed = true;
          tone(speakerPin, frequenzen[ton]);
          delay(tonDauer[ton]);
          noTone(speakerPin);
          ton = ton + 1;
          }
          Viele Grüße an alle Bastler ;)
          Andreas

    2. Guten Tag,
      hat sich in dem ersten Abbild des Codes bei der if-Abfrage ein Fehler eingeschlichen?
      Dort steht „tone(9, 440)“
      Dieser Pin wurde ja am Anfang als Variable festgelegt.
      „Müsste“ es konsequenter Weise dann nicht „tone(speakerPin, 440)“ heißen?

      Übrigens eine sehr tolle und anschauliche Tutorial-Website. Großes Lob von meiner Seite.

      1. Hallo Philipp,

        vielen Dank für das nette Lob. Du hast recht. Das sollte wirklich speakerPin heißen. Danke für den Hinweis. Ich ändere das sofort :-)

        Liebe Grüße

        Stefan

    3. Guten Tag,

      Warum wurde den in der setup Funktion per pinMode() nicht mitgeteilt, dass man speakerPin als output verwenden möchte? Hat sich da ein Fehler geschlichen oder wird das durch die tone-funktion erledigt?

      1. Hallo Recep,

        danke für Deinen Hinweis. Die tone() Funktion benötigt keine vorherige Deklaration des Pins als OUTPUT. Das hatte ich bisher noch nicht betont, es nun aber in Lektion 14 eingefügt.

        Liebe Grüße

        Stefan“

    Schreibe einen Kommentar

    Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert

     

    Diese Website verwendet Akismet, um Spam zu reduzieren. Erfahre mehr darüber, wie deine Kommentardaten verarbeitet werden.