Lektion 16 – Ein-Tasten-Piano

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

Schaltplan

Benötigte Bauteile

Bauteile Piezo Button

1

Bauplan Piezo Button

2

Bauplan Piezo Button

3

Bauplan Piezo Button

4

Bauplan Piezo Button

5

Bauplan Piezo Button

6

Bauplan Piezo Button

7

Bauplan Piezo Button

8

Bauplan Piezo Button

9

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 hochzuzählen, wäre die bei einer Sekunde schon bei fast unendlich.

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