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
BeatCircle ist ein Step Sequencer mit integriertem Effect Controller.
![Idee](http://www.Jonathan-Jonas.de/Studium/WS12/MI/idee.jpg „Idee“)
Mein Ziel war es ein Interface zu bauen, das wenig musikalische Begabung erfordert und als Stand-Alone ohne weitere Controller agieren kann.
Als Basis sollte ein Step Sequencer dienen, da man hierfür kein perfektes Taktgefühl braucht. Da Step Sequencer relativ begrenzt in der Variation der Rhythmen sind, sollten zusätzlich noch verschiedene Effekt-Parameter ansteuerbar sein. Diese sollte der Benutzer nicht über unzählige Schiebe- oder Drehregler einstellen müssen, damit das Interface oberflächlich nicht zu komplex wird. Zum anderen sollte der Benutzer physisch mehr gefordert werden und so entschied ich mich für einen Entfernungsmesser.
Bei der Form wollte ich von der typisch linearen Anordnung eines Step Sequencers weg, sie sollte eher an den wiederholenden Loop eines Beats angelehnt werden.
![Video Prototyp](http://www.Jonathan-Jonas.de/Studium/WS12/MI/videoprototyp.jpg „Video Prototyp“)
pw: beat
![Überschrift](http://www.Jonathan-Jonas.de/Studium/WS12/MI/umsetzung.jpg „Überschrift“)
Zuerst habe ich mir einen Breadboard-Prototypen gebaut und schnell gemerkt, dass die am Teensy vorhandenen Anschlüsse nicht für die von mir verwendeten Komponenten ausreichen. Deswegen habe ich zwei Multiplexer besorgt, um alle Komponenten anschließen zu können. Nachdem der Breadboard-Prototyp fertig war, bin ich zum Bau des Gehäuses übergegangen.
Aus einem Block Nussbaumholz habe ich an der Drehbank eine Außenschale gedreht. Für die Abdeckplatte habe ich Aluminiumblech und rotes Plexiglas verwendet. Hinter der Plexiglasscheibe befestigte ich ein Stück Kupferblech, um diese als kapazitiven Sensor verwenden zu können. Außerdem verbirgt sich dahinter auch der Entfernungsmesser.
Die Knöpfe habe ich aus einem Plexiglasstab gedreht, ausgehöhlt, eine LED eingelassen und dann auf einem Push-Button fixiert.
Am Ende habe ich alle Komponenten mit der Platine verkabelt, im Gehäuse fixiert und mit der Abdeckplatte verschlossen.
![Video](http://www.Jonathan-Jonas.de/Studium/WS12/MI/video.jpg „Video“)
![Funktionsweise](http://www.Jonathan-Jonas.de/Studium/WS12/MI/funktion.jpg „Funktionsweise“)
![Beschriftung](http://www.Jonathan-Jonas.de/Studium/WS12/MI/manual.jpg „Beschriftung“)
Steuerung
Der Benutzer hat die Möglichkeit auf acht verschieden Ebenen jeweils acht Anschläge zu setzen. Zu jedem Anschlag kann auf Wunsch noch ein Control Change gesendet werden. Auf jeder Ebene kann zusätzlich noch ein globaler Control Change gesendet werden.
Anzeige
Der BeatCirle verfügt über acht weiße und acht rote LEDs. Die weißen LEDs zeigen im normal Betrieb an, welche Anschläge aktiviert sind (schwach) und welcher der aktivierten gerade aktiv ist (stark). Während der ebenen Auswahl zeigen sie an, welche Ebene aktiviert ist. Die roten LEDs zeigen im normal Betrieb an, an welcher Position der Loop sich befindet. Bei der Control Change Änderung zeigen diese die Intensität an.
![Code](http://www.Jonathan-Jonas.de/Studium/WS12/MI/code.jpg „Code“)
#include <CapacitiveSensor.h>
#include <Bounce.h>
CapacitiveSensor touch = CapacitiveSensor(2,22);
int ledbin[8][3] = {{0,0,0},{1,0,0},{0,1,0},{1,1,0},{0,0,1},{1,0,1},{0,1,1},{1,1,1}};
int ledPins[] = {7, 8, 9, 10, 3, 4, 5, 6};
int butPins[] = {19, 18, 17, 16, 15, 14, 13, 12};
Bounce Bouncer[8] = {Bounce(19,5),Bounce(18,5),Bounce(17,5),Bounce(16,5),Bounce(15,5),Bounce(14,5),Bounce(13,5),Bounce(12,5)};
int butStat[8][8] = {};
int disStat[8][8] = {0};
int stepStat[8];
int chanswitch = 4;
int pinCount = 8;
int Step = 0;
byte counter;
int hold[8];
const int numReadings = 25;
int readings[numReadings];
int index = 0;
int total = 0;
int average = 0;
int count;
int holddown;
int stepcount[8];
int holdtouch;
void RealTimeSystem(byte realtimebyte) {
if(realtimebyte == 248) {
counter++;
if(counter >= 12) {
counter = 0;
if(Step < 7) {
Step = Step++;
} else {
Step = 0;
}
for (int thisPin = 0; thisPin < pinCount; thisPin++) {
if(butStat[thisPin][Step]==1){
usbMIDI.sendNoteOn(60, 127, thisPin+1);
usbMIDI.sendNoteOff(60, 127, thisPin+1);
usbMIDI.sendControlChange(70+thisPin, 0+disStat[thisPin][Step], thisPin+1);
}
}
}
}
if(realtimebyte == 250 || realtimebyte == 251) {
counter = 0;
}
if(realtimebyte == 252) {
Step = 0;
}
}
void setup() {
Serial.begin(9600);
pinMode(A1, INPUT);
for (int thisPin = 0; thisPin < pinCount; thisPin++) {
pinMode(ledPins[thisPin], OUTPUT);
pinMode(butPins[thisPin], INPUT_PULLUP);
}
usbMIDI.setHandleRealTimeSystem(RealTimeSystem);
for (int thisReading = 0; thisReading < numReadings; thisReading++) {
readings[thisReading] = 0;
}
}
void loop() {
total= total - readings[index];
readings[index] = touch.capacitiveSensorRaw(5);
total= total + readings[index];
index = index + 1;
if (index >= numReadings)
index = 0;
average = total / numReadings;
for (int thisPin = 0; thisPin < pinCount; thisPin++) {
int sum1 = 0;
for (int i = 0; i < 8; i++) {
sum1 += butStat[chanswitch][i];
}
if (sum1 > 0 || average>475) {
digitalWrite(ledPins[4], 1);
}
int sum2 = 0;
for (int i = 0; i < 8; i++) {
sum2 += stepStat[i];
}
if (sum2 > 0) {
digitalWrite(ledPins[0], 1);
}
Bouncer[thisPin].update();
if(average>480){
digitalWrite(ledPins[5], ledbin[chanswitch][0]);
digitalWrite(ledPins[6], ledbin[chanswitch][1]);
digitalWrite(ledPins[7], ledbin[chanswitch][2]);
count = count++;
if (count > 5000) {
usbMIDI.sendControlChange(chanswitch, map(analogRead(A1),0,620,0,127), chanswitch);
holdtouch=1;
}
if (Bouncer[thisPin].fallingEdge()){
chanswitch=thisPin;
}
} else {
count = 0;
holdtouch=0;
if (digitalRead(butPins[thisPin])==0){
if (Bouncer[thisPin].duration()>500){
disStat[chanswitch][thisPin] = map(analogRead(A1),0,620,0,127);
hold[thisPin]=2;
holddown = thisPin;
digitalWrite(ledPins[5], ledbin[thisPin][0]);
digitalWrite(ledPins[6], ledbin[thisPin][1]);
digitalWrite(ledPins[7], ledbin[thisPin][2]);
}
if (Bouncer[thisPin].fallingEdge()){
if (butStat[chanswitch][thisPin]==0) {
butStat[chanswitch][thisPin] = 1;
hold[thisPin] = 1;
}
}
}
if (Bouncer[thisPin].risingEdge()){
if (hold[thisPin]==0){
butStat[chanswitch][thisPin] = 0;
disStat[chanswitch][thisPin] = 0;
}
hold[thisPin] = 0;
}
if (butStat[chanswitch][thisPin]==1 && hold[0]<2 && hold[1]<2 && hold[2]<2 && hold[3]<2 && hold[4]<2 && hold[5]<2 && hold[6]<2 && hold[7]<2) {
digitalWrite(ledPins[5], ledbin[thisPin][0]);
digitalWrite(ledPins[6], ledbin[thisPin][1]);
digitalWrite(ledPins[7], ledbin[thisPin][2]);
}
}
if (hold[0]==2 || hold[1]==2 || hold[2]==2 || hold[3]==2 || hold[4]==2 || hold[5]==2 || hold[6]==2 || hold[7]==2 || holdtouch==1 ){
for (int i = 0; i < 8; i++) {
if (map(analogRead(A1),0,620,0,9)>i){
if (i+holddown>7){
stepStat[i+holddown-8]=1;
} else {
stepStat[i+holddown]=1;
}
} else if (i+holddown>7){
stepStat[i+holddown-8]=0;
} else {
stepStat[i+holddown]=0;
}
}
} else if (thisPin==Step) {
stepStat[thisPin]=1;
} else {
stepStat[thisPin]=0;
}
if (stepStat[thisPin]==1) {
digitalWrite(ledPins[1], ledbin[thisPin][0]);
digitalWrite(ledPins[2], ledbin[thisPin][1]);
digitalWrite(ledPins[3], ledbin[thisPin][2]);
}
digitalWrite(ledPins[0], 0);
if (butStat[chanswitch][thisPin]==1 && stepStat[thisPin]==1) {
delay(1);
} else {
digitalWrite(ledPins[4], 0);
}
}
usbMIDI.read();
}
![Fazit](http://www.Jonathan-Jonas.de/Studium/WS12/MI/fazit.jpg „Fazit“)
Ich hatte vorher noch keinen Kontakt zu Arduino oder Vergleichbarem, bin aber erstaunlich schnell damit klargekommen. Auch dank der guten Anleitung von [Stefan Hermann](http://incom.org/profil/1941 „Stefan Hermann“). Mit meinem Ergebnis bin ich sehr zufrieden. Denn ich hätte mir nicht vorstellen können, das ich meine Idee aus dem Video-Prototypen so gut, und noch besser umsetzten würde.
Ich bin von dem Kurs begeistert und freue mich jetzt schon auf den nächsten Physical Interaction Kurs.