Wenn es in der Musik um gegeneinander (oder miteinander) laufende Rhythmen geht (Polyrhythmik), dann tuen sich etlichen Menschen hart, den einzelnen Rhythmen zu folgen. Die folgende Schaltung und Programmierung soll eine kleine Hilfestellung sein für zwei oder mehrere gleichzeitig laufende Rhythmen ein Gefühl zu bekommen.
Im folgenden Schaltplan ist ein sog. Rhythmus-Modul verbaut, welches aus einem Mikrotaster mit
Pulldown-Widerstand, einer LED mit Vorwiderstand und einem Piezo-Buzzer
besteht. Für Polyrhythmik werden mindestens zwei dieser Rhythmus-Module benötigt. Hierbei ist nur darauf
zu achten, dass die Piezo-Buzzer an einem Pin mit PWM anzuschließen sind.
Zusätzlich ist noch ein Potentiometer verbaut, welches die Gesamtgeschwindigkeit regelt.
Für das praktische Beispiel im Folgenden habe ich drei Rhythmus-Module verwendet mit jeweils unterschiedlich farbigen LEDs.
Im folgenden Arduino-Sketch werden die (hier: drei) Rhythmus-Module an verschiedenen Pins angeschlossen und
mit unterschiedlichen Rhythmen programmiert. Das baseDelay
gibt die Pausenzeit in Millisekunden
zwischen den Schlägen des Rhythmus an. Will man also eine 2-zu-3-Rhythmik einstellen, so wählt man 20ms und 30ms.
Natürlich können auch Vielfache dieser Werte gewählt werden. Durch das Drehen am Potentiometer werden diese
Delays multipliziert (1× bis 30×).
Durch das Drücken der jeweiligen Mikrotaster wird der entsprechende Rhythmus an- bzw. ausgeschaltet. So kann
man auch selbst kombinieren.
#define NUM_MODULES 3
#define POTENTIOMETER_PIN A5
#define lmillis() ((long)millis())
#define DEBOUNCE_TIME 100 // in milliseconds
struct RhythmModule {
byte isEnabled;
byte pinLed;
byte pinPiezo;
byte pinButton;
long lastAction;
unsigned int baseDelay; // in milliseconds
unsigned int pauseDelay; // in milliseconds
};
RhythmModule modules[] = {
{true, A0, 9, 5, 0, 20, 0},
{true, A1, 10, 6, 0, 30, 0},
{true, A2, 11, 7, 0, 50, 0}
};
void setup()
{
for (byte i = 0; i < NUM_MODULES; i++) {
pinMode(modules[i].pinLed, OUTPUT);
digitalWrite(modules[i].pinLed, LOW);
pinMode(modules[i].pinPiezo, OUTPUT);
}
}
void loop()
{
for (byte i = 0; i < NUM_MODULES; i++) {
byte multiplier = map(analogRead(POTENTIOMETER_PIN), 0, 1024, 1, 30);
modules[i].pauseDelay = modules[i].baseDelay * multiplier;
if (buttonPressed(modules[i].pinButton)) {
modules[i].isEnabled = !modules[i].isEnabled;
}
if (lmillis() - modules[i].lastAction >= 0) {
if (modules[i].isEnabled) {
digitalWrite(modules[i].pinLed, !digitalRead(modules[i].pinLed));
tone(modules[i].pinPiezo, 440);
delay(1);
noTone(modules[i].pinPiezo);
} else {
digitalWrite(modules[i].pinLed, LOW);
noTone(modules[i].pinPiezo);
}
modules[i].lastAction += modules[i].pauseDelay;
}
}
}
byte buttonPressed(byte pin)
{
static long lastButtonClick = 0;
if ((lmillis() - lastButtonClick) < DEBOUNCE_TIME) {
return false;
}
lastButtonClick = lmillis();
return (digitalRead(pin) == HIGH);
}