In seiner Funktionalität auf die Lehre in gestalterischen Studiengängen zugeschnitten... Schnittstelle für die moderne Lehre
In seiner Funktionalität auf die Lehre in gestalterischen Studiengängen zugeschnitten... Schnittstelle für die moderne Lehre
Die DrumBowl ist ein Midi-Controller für die Steuerung von Digital Audio Workstation Softwares. Es verfügt über sechs drucksensitive Drum-Pads, bei denen in Kombination mit zwei Tastern die Oktaven verändert werden können. Des Weiteren ist es möglich zwischen drei verschieden Instrumenten zu wählen und durch einen integrierten Abstandssensor können zwei verschiedene Effekte gesteuert werden. Die Session kann man selbstverständlich auch aufnehmen.
Der Musical Interface Kurs orientiert sich am Physical Interaction Design. Das Ziel dieses Kurses ist es, neue Musical Interfaces zu entwickeln. Neben theoretischen Grundlagen werden eigene In- und Output-Module gebaut, programmiert und Interaktionskonzepte realisiert. Dabei richtet sich der Fokus auf Music-Controller.
Ich habe mich bewusst für einen Controller entschieden, für den ich persönlich Potential gesehen habe, ihn auch künftig selbst nutzen zu können. Meine bisherige Erfahrung habe ich genutzt um diesen Controller zu realisieren. Dabei beschränkte ich mich auf wenige aber wesentliche Funktionen. Den weiteren Fokus legte ich auf die Form des Controllers und die Anordnung der einzelnen Steuerungselemente um eine einfache Usability zu gewährleisten.
Nachdem die Idee feststand machte ich mir Gedanken über die Hardware die ich benötigte.
Das Herzstück ist ein Mikrocontroller, welches die ankommenden Informationen verarbeitet und als Midi-Signale weiterleitet. Für die Drum-Pads verwende ich sechs Drucksensoren, diese ermöglichen es einzelne Töne in ihrer Lautstärke zu steuern. Um die Effektparameter steuern zu können, entschied ich mich für einen Infrarotsensor. Zu dem fanden insgesamt acht Taster mit integrierten LEDs ihren Platz.
Verwendete Bauteile:
Bevor es mit dem Programmieren losging, galt es im nächsten Schritt die Schaltung auf einem Breadboard zu bauen.
Hinweis: In meinem Fall werden für die LEDs keine Widerstände benötigt. Ich verwende Taster mit integrierter LED, welche bei einer Nutzung zwischen 3V und 6V keinen Widerstand benötigen.
Da ich bisher keine umfangreiche Erfahrung mit der verwendeten Programmiersprache hatte, habe ich die Komplexität der einzelnen Codefragmente zu Beginn geringfügig unterschätzt. So sind beispielsweise während dem Bau des Controllers Fehler bei den Drucksensoren aufgetaucht, welche durch einen weiterführenden Code behoben werden mussten.
[Arduino Datei herunterladen](http://www.chrisklement.com/fhp/drumbowl/drumbowl.zip „Arduino Code“)
#include <Bounce2.h>
int channel = 1;
// Variablen Drums
int Schalter[] = { A0, A1, A2, A3, A4, A5 };
int SchalterReading[6];
int value[6];
boolean SchalterActive[6];
// Midi-Notes send
int alleOktaven[4][6]={
{24,25,26,27,28,29},
{30,31,32,33,34,35},
{36,37,38,39,40,41},
{42,43,44,45,46,47}
};
int thresholdValues[6];
int aktiveOktave=0; // speichert aktuelle Töne
int minOktave=0; // kleinste Oktave
int maxOktave=3; // höchste Oktave
boolean octavePlusPressed = false;
boolean octaveMinusPressed = false;
// Infarotsensor
int effectControlPin = 22;
// Buttons
#define Record_PIN 0
#define Record_LED_PIN 1
#define Effekt1_PIN 8
#define Effekt1_LED_PIN 9
#define Effekt2_PIN 10
#define Effekt2_LED_PIN 11
#define OktavePlus_PIN 12
#define OktavePlus_LED_PIN 13
#define OktaveMinus_PIN 21
#define OktaveMinus_LED_PIN 20
#define Sound1_PIN 2
#define Sound1_LED_PIN 3
#define Sound2_PIN 4
#define Sound2_LED_PIN 5
#define Sound3_PIN 6
#define Sound3_LED_PIN 7
int RecordState = LOW;
int Effekt1State = LOW;
int Effekt2State = LOW;
int Sound1State = LOW;
int Sound2State = LOW;
int Sound3State = LOW;
// Instantiate a Bounce object :
Bounce Recorddebouncer = Bounce();
Bounce Effekt1debouncer = Bounce();
Bounce Effekt2debouncer = Bounce();
Bounce OktavePlusdebouncer = Bounce();
Bounce OktaveMinusdebouncer = Bounce();
Bounce Sound1debouncer = Bounce();
Bounce Sound2debouncer = Bounce();
Bounce Sound3debouncer = Bounce();
void setup() {
// Setup buttons
Serial.begin(9600); // Für evt. Serial.print() Ausgabe
pinMode(Record_PIN,INPUT_PULLUP);
pinMode(Effekt1_PIN,INPUT_PULLUP);
pinMode(Effekt2_PIN,INPUT_PULLUP);
pinMode(OktavePlus_PIN,INPUT_PULLUP);
pinMode(OktaveMinus_PIN,INPUT_PULLUP);
pinMode(Sound1_PIN,INPUT_PULLUP);
pinMode(Sound2_PIN,INPUT_PULLUP);
pinMode(Sound3_PIN,INPUT_PULLUP);
// After setting up the button, setup the Bounce instance:
Recorddebouncer.attach(Record_PIN);
Recorddebouncer.interval(50);
Effekt1debouncer.attach(Effekt1_PIN);
Effekt1debouncer.interval(50);
Effekt2debouncer.attach(Effekt2_PIN);
Effekt2debouncer.interval(50);
OktavePlusdebouncer.attach(OktavePlus_PIN);
OktavePlusdebouncer.interval(5);
OktaveMinusdebouncer.attach(OktaveMinus_PIN);
OktaveMinusdebouncer.interval(5);
Sound1debouncer.attach(Sound1_PIN);
Sound1debouncer.interval(50);
Sound2debouncer.attach(Sound2_PIN);
Sound2debouncer.interval(50);
Sound3debouncer.attach(Sound3_PIN);
Sound3debouncer.interval(50);
// Setup LEDs
pinMode(Record_LED_PIN,OUTPUT);
digitalWrite(Record_LED_PIN,RecordState);
pinMode(Effekt1_LED_PIN,OUTPUT);
digitalWrite(Effekt1_LED_PIN,Effekt1State);
pinMode(Effekt2_LED_PIN,OUTPUT);
digitalWrite(Effekt2_LED_PIN,Effekt2State);
pinMode(OktavePlus_LED_PIN,OUTPUT);
pinMode(OktaveMinus_LED_PIN,OUTPUT);
pinMode(Sound1_LED_PIN,OUTPUT);
digitalWrite(Sound1_LED_PIN,Sound1State);
pinMode(Sound2_LED_PIN,OUTPUT);
digitalWrite(Sound2_LED_PIN,Sound2State);
pinMode(Sound3_LED_PIN,OUTPUT);
digitalWrite(Sound3_LED_PIN,Sound3State);
for(int i = 0; i < 6; i++) {
thresholdValues[i] = analogRead(Schalter[i]);
}
}
void loop() {
// Update the Bounce instance
Recorddebouncer.update();
Effekt1debouncer.update();
Effekt2debouncer.update();
OktavePlusdebouncer.update();
OktaveMinusdebouncer.update();
Sound1debouncer.update();
Sound2debouncer.update();
Sound3debouncer.update();
// Call code if Bounce fell:
// Control Record
if ( Recorddebouncer.fell() ) {
// Toggle LED state :
RecordState = !RecordState;
digitalWrite(Record_LED_PIN,RecordState);
usbMIDI.sendNoteOn(1, 99, channel);
} else {
usbMIDI.sendNoteOff(1, 99, channel);
}
// Control Effekt 1
if ( Effekt1debouncer.fell() ) {
// Toggle LED state :
Effekt1State = !Effekt1State;
digitalWrite(Effekt1_LED_PIN,Effekt1State);
usbMIDI.sendNoteOn(2, 99, channel);
} else {
usbMIDI.sendNoteOff(2, 99, channel);
}
// Control Effekt 2
if ( Effekt2debouncer.fell() ) {
// Toggle LED state :
Effekt2State = !Effekt2State;
digitalWrite(Effekt2_LED_PIN,Effekt2State);
usbMIDI.sendNoteOn(3, 99, channel);
} else {
usbMIDI.sendNoteOff(3, 99, channel);
}
// Control Sound 1
if ( Sound1debouncer.fell() ) {
// Toggle LED state :
Sound1State = !Sound1State;
digitalWrite(Sound1_LED_PIN,Sound1State);
usbMIDI.sendControlChange(4, 99, channel);
}
// Control Sound 2
if ( Sound2debouncer.fell() ) {
// Toggle LED state :
Sound2State = !Sound2State;
digitalWrite(Sound2_LED_PIN,Sound2State);
usbMIDI.sendControlChange(5, 99, channel);
}
// Control Sound 3
if ( Sound3debouncer.fell() ) {
// Toggle LED state :
Sound3State = !Sound3State;
digitalWrite(Sound3_LED_PIN,Sound3State);
usbMIDI.sendControlChange(6, 99, channel);
}
// Control Effektsensor
int valueeffectControl = analogRead(effectControlPin);
valueeffectControl = constrain(valueeffectControl, 200, 900);
valueeffectControl = map(valueeffectControl, 200, 900, 0, 127);
usbMIDI.sendControlChange(20, valueeffectControl, channel);
// Soundpads Konfiguration
if (aktiveOktave>maxOktave) {
aktiveOktave=maxOktave;
}
if (aktiveOktave<minOktave) {
aktiveOktave=minOktave;
}
// Control Oktave Plus
int OktavePlus_value = OktavePlusdebouncer.read();
if (( OktavePlus_value == LOW )&&(octavePlusPressed == false)) {
digitalWrite(OktavePlus_LED_PIN, HIGH );
delay(600);
aktiveOktave++;
octavePlusPressed = true;
} else {
digitalWrite(OktavePlus_LED_PIN, LOW );
octavePlusPressed = false;
}
// Control Oktave Minus
int OktaveMinus_value = OktaveMinusdebouncer.read();
if (( OktaveMinus_value == LOW )&&(octaveMinusPressed == false)) {
digitalWrite(OktaveMinus_LED_PIN, HIGH );
delay(600);
aktiveOktave--;
octaveMinusPressed = true;
} else {
digitalWrite(OktaveMinus_LED_PIN, LOW );
octaveMinusPressed = false;
}
for(int i = 0; i < 6; i++) {
SchalterReading[i] = analogRead(Schalter[i]);
Serial.print("Sensor");Serial.print(i);Serial.print("\t");
Serial.print(value[i]);Serial.print("\t");
value[i] = constrain(value[i], 20 , 200);
value[i] = map(SchalterReading[i], 20, 200, 0, 127);
Serial.print(value[i]);Serial.print("\t");
if(value[i] > thresholdValues[i]+20) {
if(!SchalterActive[i]) {
Serial.print("Note send \t");
usbMIDI.sendNoteOn(alleOktaven[aktiveOktave][i],
value[i], channel);
SchalterActive[i] = true;
}
} else {
if(SchalterActive[i]) {
SchalterActive[i] = false;
usbMIDI.sendNoteOff(alleOktaven[aktiveOktave]
[i], value[i], channel);
}
}
Serial.println();
}
delay(20);
while (usbMIDI.read()){}
}
Ich dachte lange darüber nach, welche Materialien ich für den Controller verwendenden sollte um ein möglichst edles Design zu erreichen. Daraufhin entschied ich mich für eine Kombination aus Edelstahl und Holz. Für die Oberfläche der Drum-Pads bot sich Moosgummi an, welches ein angenehmes Gefühl beim Bedienen mit sich bringt. Folgend sieht man einen Teil des Bauprozesses und die Endpräsentation.
Ich bin mit meinem Ergebnis sehr zufrieden und der Kurs hat mir die Möglichkeit geben meine erste Begegnung mit Arduino und Co. zu machen. Es war für mich sehr interessant die einzelnen Phasen eines Prototypens zu durchlaufen. Für mich steht fest, in meinem weiteren Verlauf des Studiums meine bisher erlangten Fähigkeiten in Physical Interaction Design zu vertiefen, da ich für mich ein hohes Potential darin sehe.
Ich kann diesen Kurs auf jeden fall Studenten weiterempfehlen, die ihre ersten Erfahrungen in Physical Interaction Design suchen und sich ausprobieren möchten.
Mein Dank gilt Stefan Hermann für diesen lehrreichen und sehr interessanten Kurs.