Incom ist die Kommunikations-Plattform der Fachhochschule Potsdam

In seiner Funktionalität auf die Lehre in gestalterischen Studiengängen zugeschnitten... Schnittstelle für die moderne Lehre

Incom ist die Kommunikations-Plattform der Fachhochschule Potsdam mehr erfahren

DrumBowl

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.

Funktionsdarstellung

Kursbeschreibung

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.

Mein Ziel

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.

Hardware

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:

  • Teensy 3.1 (Mikrocontroller)
  • FSR406 von Interlink (Drucksensoren)
  • GP2Y0AA41SK0F von Sharp (Infrarotsensor)
  • Waterproof Metal Pushbutton width LED Ring von Adafruit (Taster)

Schaltung

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.

Programmierung

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()){}
}

Eindrücke des Prozesses

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.

Fazit

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.

Ein Projekt von

Fachgruppe

Sonstige Veranstaltungen

Art des Projekts

Studienarbeit im Grundstudium

Betreuung

Stefan Hermann

Zugehöriger Workspace

Musical Interfaces 2014

Entstehungszeitraum

Wintersemester 2014 / 2015

zusätzliches Material