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;
      }
    }
    0 0 votes
    Article Rating
    Abonnieren
    Benachrichtige mich bei

    Diese Seite verwendet Akismet, um Spam zu reduzieren. Erfahre, wie deine Kommentardaten verarbeitet werden..

    9 Comments
    Newest
    Oldest Most Voted
    Inline Feedbacks
    Alle Kommentare anzeigen
    2 Jahre zuvor

    Ich finde das sehr super ❤❤❤❤❤❤❤❤❤

    Simon
    9 Jahre zuvor

    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;
    }

    Karl
    Antworte an  Simon
    7 Jahre zuvor

    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!

    Andreas
    Antworte an  Karl
    3 Jahre zuvor

    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

    Philipp
    9 Jahre zuvor

    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.

    Recep S.
    10 Jahre zuvor

    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?

    9
    0
    Ich würde mich über deine Meinung freuen.x