HMI - Hallway Music Interface: Einführung

Das Hallway Music Interface ist eine interaktive Installation, die den Benutzer ohne sein bewusstes Zutun zum Dirigenten von Musik macht. Die Art, wie man damit interagiert ist eine sehr einfache: Man bewegt sich ganz einfach gehend einen Flur entlang, der über Lautsprecher mit Musik beschallt wird. Dadurch werden beim Passieren fünf festgelegter Punkte bestimmte Grundparameter der Musik in Echtzeit verändert. Diese fünf Parameter sind das Tempo, die Tonhöhe, das Panorama, die Lautstärke und das Delay. Kommt man also als Benutzer oder gegebenfalls als einfacher Fußgänger, je nachdem ob das HMI in musealem Kontext oder im öffentlichen Raum gezeigt wird, am ersten Punkt vorbei, wird das Tempo verändert. Je weiter man links im Flur die Stelle passiert desto langsamer, je weiter rechts, desto schneller wird die Musik danach abgespielt. Beim zweiten dieser Passierpunkte verändert sich nach dem gleichen Prinzip die Lautstärke. Links bedeutet leiser, rechts lauter. Das Panorama wird ebenfalls in ähnlicher Weise beeinflusst. Die Tonhöhe bei Punkt Vier wird von einem basslastigen Gesamteindruck (links) zu einem höhenlastigen (rechts) hin verändert, in gleicher Weise wird das Delay beim Passieren von Punkt Fünf von links nach rechts erhöht. Das HMI ist somit in der Lage einzelnen, wie mehreren Personen die Möglichkeit zu geben, nur mit simplem Gehen in gewisser Weise Musik zu machen, bzw. ein fertiges Stück damit zu arrangieren. Ebenso kann das HMI auch als „Fluktuationsmesser“ angesehen werden, denn wenn sich viele Leute in kurzen Abständen oder gar gleichzeitig den Gang entlang bewegen wird das Musikstück für das Ohr sehr unwillkürlich und wirr, da es aufgrund der schnellen Veränderungen für den Menschen kaum mehr Möglichkeiten gibt, sich auf ein Tempo, auf eine Tonhöhe oder einen der anderen genannten Grundparameter einzustellen. Dies spiegelt die gewisse Aufregung, die unter größeren Menschenmassen aufkommt akustisch wieder.

Grafische Darstellung des physikalischen Aufbaus:

Technische Umsetzung: verwendete Hard- und Software

Hardware

Nach längerer Suche nach der geeigneten Hardware und Sensorik haben sich am Ende folgende Komponenten durchgesetzt:

  • Arduino Duemilanove
  • Devantech SRF05 Ultraschallsensor
  • natürlich ein halbwegs brauchbares Notebook auf dem die Daten verarbeitet werden
  • Lautsprecher und Mischpult

Arduino Duemilanove:

Das Arduino-Board war die erste Komponente, die feststand. Die Sensoren werden hierüber mit Spannung versorgt. Der wichtigere Teil der Aufgabe den das Arduino-Board hat, ist aber die Verarbeitung der Sensorwerte. Diese werden in der Open-Source-Arduino-Software ausgelesen und anschließend, da ja die Entfernung zur Wand, wo die Sensoren angebracht sind, gemessen werden soll, in cm umgerechnet und so an MAX/MSP weitergegeben. (siehe Kapitel Arduino).

SRF05 Ultraschallsensor:

Den anfänglichen Überlegungen nach, sollte das HMI mit Infrarotsensoren umgesetzt werden. Der Grund, warum schließlich doch Ultraschallsensoren verwendet wurden, ist zum einen das sehr gute Preis-/Leistungsverhältnis und zum anderen die Reichweite, die die SRF05 aufweisen. Diese wird von den meisten Infrarotsensoren nicht erreicht und beträgt bis zu 4 Metern bei einer Genauigkeit von 1 cm, was für diesen Zweck mehr als ausreichend ist.Ausserdem hat der SRF05-Sensor den Vorteil, im 1 Pin-Mode betrieben werden zu können, was die Hälfte an Leitermaterial für die Signalleitungen erspart.

1 Pin-Modus und 2 Pin-Modus:

Entfernungsmessung via Ultraschall funktioniert in der Regel so, dass ein Ultraschallsignal ausgesendet wird, an einem Objekt reflektiert und das reflektierte Signal wieder empfangen wird. Die Zeit, die zwischen Senden und Empfangen des Signals vergangen ist wird gemessen und aufgrund der Tatsache, dass die Schallgeschwindigkeit bekannt ist (343 m/s), kann auf einfache Art und Weise die Entfernung errechnet werden.

Nun wird aber in aller Regel bei Ultraschallsensoren ein Pin für das Senden und einer für das Empfangen verwendet. Dies ist zwar beim SRF05 auch möglich, aber nicht unbedingt notwendig. Er kann also mit nur einem Pin als Signalpin betrieben werden. Dieser wird sozusagen nach jedem Sendevorgang auf Empfang umgestellt und umgekehrt. Dies soll in den folgenden Abbildungen veranschaulicht werden.

2 Pin-Modus 1 Pin-Modus

Natürlich braucht es für die Funktion auch eine Verbindung der Sensoren und des Arduino-Boards. Wie das funktioniert, zeigt die folgende Abbildung. Es wurden hierfür die digitalen Pins 3 bis 7 verwendet.

 

Software

Nachdem die Hardware funktioniert werde ich mich jetzt der Software zuwenden. Zur Verarbeitung der Messdaten wurde, wie bereits erwähnt, Arduino verwendet. Für die Realtime-Soundbearbeitung standen Processing und MAX/MSP zur Auswahl, wobei ich mich nach längerem hin und her für letztere entschloss.  

Arduino

Hier der Arduino-Code, der für die Umsetzung verwendet wurde: 

// Setzen der Pin-Nummern für die 5 Sensoren
const int pingPin7 = 7;
const int pingPin6 = 6;
const int pingPin5 = 5;
const int pingPin4 = 4;
const int pingPin3 = 3;

void setup() {
  // initialisieren der baud rate
  Serial.begin(9600);
}

void loop()
{
  // deklarieren der Variablen für die Zeitdauer und für die Entfernung in cm  
  // für jeden Sensor (Nummerierung nach Arduino-Pins)
  long duration7, duration6, duration5, duration4, duration3, cm7, cm6, cm5, cm4, cm3;

  // Der SRF 05 wird durch einen HIGH-Impuls getriggert, hierfür ist der jeweilige Pin auf OUTPUT gesetzt.
  // Anschließend wird der Pin auf INPUT geswitcht, um die Werte auslesen zu können.
  // Die Zeitdauer wird gemessen und danach in cm umgewandelt. Es folgt ein Delay um in keine 
  // Konflikte zwischen den Sensoren zu geraten.
  pinMode(pingPin7, OUTPUT);
  digitalWrite(pingPin7, LOW);
  delayMicroseconds(2);
  digitalWrite(pingPin7, HIGH);
  delayMicroseconds(5);
  digitalWrite(pingPin7, LOW);
  pinMode(pingPin7, INPUT);
  duration7 = pulseIn(pingPin7, HIGH);
  cm7 = microsecondsToCentimeters7(duration7);
  delayMicroseconds(20); 
  
  pinMode(pingPin6, OUTPUT);
  digitalWrite(pingPin6, LOW);
  delayMicroseconds(2);
  digitalWrite(pingPin6, HIGH);
  delayMicroseconds(5);
  digitalWrite(pingPin6, LOW);
  pinMode(pingPin6, INPUT);
  duration6 = pulseIn(pingPin6, HIGH);  
  cm6 = microsecondsToCentimeters6(duration6);
  delayMicroseconds(20); 
  
  pinMode(pingPin5, OUTPUT);
  digitalWrite(pingPin5, LOW);
  delayMicroseconds(2);
  digitalWrite(pingPin5, HIGH);
  delayMicroseconds(5);
  digitalWrite(pingPin5, LOW);
  pinMode(pingPin5, INPUT);
  duration5 = pulseIn(pingPin5, HIGH);
  cm5 = microsecondsToCentimeters5(duration5);  
  delayMicroseconds(20);
   
  pinMode(pingPin4, OUTPUT);
  digitalWrite(pingPin4, LOW);
  delayMicroseconds(2);
  digitalWrite(pingPin4, HIGH);
  delayMicroseconds(5);
  digitalWrite(pingPin4, LOW);
  pinMode(pingPin4, INPUT);
  duration4 = pulseIn(pingPin4, HIGH);
  cm4 = microsecondsToCentimeters4(duration4);  
  delayMicroseconds(20);
 
  pinMode(pingPin3, OUTPUT);
  digitalWrite(pingPin3, LOW);
  delayMicroseconds(2);
  digitalWrite(pingPin3, HIGH);
  delayMicroseconds(5);
  digitalWrite(pingPin3, LOW);  
  pinMode(pingPin3, INPUT);
  duration3 = pulseIn(pingPin3, HIGH);
  cm3 = microsecondsToCentimeters3(duration3);
  delayMicroseconds(20);

  // Printen der Entfernungswerte in den Serialmonitor. 
  // -> 5 Werte pro Zeile, diese werden von dort von MAX/MSP ausgelesen.
  Serial.print(cm7);
  Serial.print(" ");
  Serial.print(cm6);
  Serial.print(" ");
  Serial.print(cm5);
  Serial.print(" ");
  Serial.print(cm4);
  Serial.print(" ");
  Serial.print(cm3);
  Serial.print(" ");
  Serial.println();
  
  delay(100);
}

// Definieren der Funktionen zur Umrechnung der Zeitdauer in Entfernung
// Schallgeschwindigkeit: 343m/s oder 29 cm/ms
long microsecondsToCentimeters7(long microseconds7)
{
  return microseconds7 / 29 / 2;
}
long microsecondsToCentimeters6(long microseconds6)
{
  return microseconds6 / 29 / 2;
}
long microsecondsToCentimeters5(long microseconds5)
{
  return microseconds5 / 29 / 2;
}
long microsecondsToCentimeters4(long microseconds4)
{
  return microseconds4 / 29 / 2;
}
long microsecondsToCentimeters3(long microseconds3)
{
  return microseconds3 / 29 / 2;

}


Der Code basiert auf folgendem Tutorial, das von www.arduino.cc zur Verfügung gestellt wird:

Tutorial Arduino + Ultraschallsensor 

MAX/MSP

Ich möchte hier lediglich auf die pdf-Datei unter den Materialien zum Download verweisen. Diese enthält die komplette Software-Dokumentation zum MAX/MSP-Teil der Realisierung.