Ribbon Instrument

Lumi

12.06.2017

Abstract

The goal of the Ribbon Instrument was to create a space that children and adults alike could interact with, and through the physicality of the ribbons themselves, and the sounds they triggered, evoke a sense of wonder, discovery, and play through the audio, visual, and tactile environment. The colors and tactility of the ribbons themselves created an inviting piece that allowed for different types of interaction. The audio lent itself to the element of discovery and another level of interaction. These interactions ranged from the intended walk-through and pulling of the ribbons, to children wrapping themselves in the ribbons, not seemingly caring about the sound elements. The final piece integrated into the museum environment as a space that was beautifully described as “an environment where other things can happen”.

Objectives

The goal of the ribbon instrument was to create a space that invited children to interact with, and physically be within, while they triggered sounds to create an ambient audio-scape through the motion of the ribbons. The final piece consisted of 18 ribbons hung on a 6 by 3.5 foot wooden structure suspended in the Maker Space room. The piece used two types of triggers: 12 roller switches, and 6 IR sensors to sense movement of the ribbons themselves to play sound. The entire system was powered by an Arduino attached to my laptop (Velcroed to a beam on the hanging structure).

Implementation

The critical design elements of this project related to the color, scale, and planned interaction with the piece. The final piece consisted of 18 ribbons multicolored ribbons hung about 6 feet above the ground on a 6 by 3.5 foot grid suspended in the Maker Space room. Two different types of ribbon were used to indicate different types of interaction (pull or wave) however the differences were very subtle (smooth versus ribbed) that in this case this difference did not add anything to the piece. Each of the ribbons was about 11 inches from the next creating space between the to walk in, but close enough to catch on to people as they did. The colors themselves served as a huge draw, one young boy saying, “so pretty” as he ran around the space. The use of the thick, slightly textured ribbons, invited people to pull on them, but not to hang on then as ropes would have done. The large scale of the piece lent itself to creating a space of ribbons that people could enter into and travel through. The sounds that were triggered were a range of single notes to short melodies, mostly from marimbas and kalimbas. These created sounds with a softer texture that worked as individual moments, as well as in combination with each other to create a dynamic soundscape.

Outcomes

There were multiple different types of interaction with the piece itself, particularly when it came to the engagement with the sound elements. Some children would walk though the space, pulling ribbons as they went along triggering the sound-scape, in some cases the pulling of the ribbons was prompted by the parents. Often, once a ribbon was pulled and a sound was triggered, a child would continue holding on to that ribbon for a while.

The physicality of the ribbons themselves played a critical role in the interaction with the piece, not only in the tactile click that occurred when the ribbons were pulled down and triggered, but even more so in just the hanging ribbons themselves. Often children would be seen, spinning around in the center of the structure, wrapping themselves in the ribbons, or running through the space, trailing the long strings around them. For them, it didn’t matter that sounds were being triggered, that wasn’t an important part of the experience, but it was the delight in the physicality of it that drew them.

The implementation of the soundscape itself provided a layer of discovery to the piece. Adults and children alike pulled the outer ribbons without being prompted to do so, and were then rewarded with an audio response. This then led to people to walk into the hanging structure itself to pull the other ribbons, triggering new sounds with each one. In some cases, especially with younger children, their parents would discover the sound element first, then prompt their children to pull on the ribbons as well.

It shows that the choice of the colorful ribbons and pull down triggers was a successful one in inviting people into, and to interact with the space created by the instrument.

I also had motion triggers to set off sound using IR sensors on six of the ribbons. While the few that did ultimately work provided a nice addition of sound to those running around in the space who didn’t tug on the ribbons, they also created a discontinuity with the type of interaction with the piece. This became evident when those who were navigating the instrument by tugging on the ribbons came across the IR sensor ribbons and were unable to pull them down in the same way and did not receive an audio response. In this sense, picking on time of intended trigger action would have been more successful. There is room to explore both the direct and ambient motion further.

 

Rhino Model for switches:

 

Max Patch:

LINK

Arduino:

// _________switch set (2)__________
 const int buttonPin2 = 2; 
 
 int buttonState2 = 0;
 int lastButtonState2 = 0;
 int clickSwitchState2 = 0;



// _________switch (3)______________
const int buttonPin3 = 3; 
 
 int buttonState3 = 0;
 int lastButtonState3 = 0;
 int clickSwitchState3 = 0;
 
//_____Switch set input (4)__________
const int buttonPin4 = 4;

int buttonState4 = 0;
 int lastButtonState4 = 0;
 int clickSwitchState4 = 0;

//_____Switch set input (5)__________
const int buttonPin5 = 5;

int buttonState5 = 0;
 int lastButtonState5 = 0;
 int clickSwitchState5 = 0;

//_____Switch set input (6)__________
const int buttonPin6 = 6;

int buttonState6 = 0;
 int lastButtonState6 = 0;
 int clickSwitchState6 = 0;

//_____Switch set input (7)__________
const int buttonPin7 = 7;

int buttonState7 = 0;
 int lastButtonState7 = 0;
 int clickSwitchState7 = 0;

//_____Switch set input (8)__________
const int buttonPin8 = 8;

int buttonState8 = 0;
 int lastButtonState8 = 0;
 int clickSwitchState8 = 0;

//_____Switch set input (9)__________
const int buttonPin9 = 9;

int buttonState9 = 0;
 int lastButtonState9 = 0;
 int clickSwitchState9 = 0;

//_____Switch set input (10)__________
const int buttonPin10 = 10;

int buttonState10 = 0;
 int lastButtonState10 = 0;
 int clickSwitchState10 = 0;

//_____Switch set input (11)__________
const int buttonPin11 = 11;

int buttonState11 = 0;
 int lastButtonState11 = 0;
 int clickSwitchState11 = 0;

//_____Switch set input (12)__________
const int buttonPin12 = 12;

int buttonState12 = 0;
 int lastButtonState12 = 0;
 int clickSwitchState12 = 0;

//_____Switch set input (13)__________
const int buttonPin13 = 13;

int buttonState13 = 0;
 int lastButtonState13 = 0;
 int clickSwitchState13 = 0;







// IR SWITCHES:

const int irInput = A0; // IR
 
 int irClickSwitchState = 0;
 int irButtonState = 0;
 int irLastButtonState = 0;

int val;

//______________________________
 const int irInput1 = A1; // IR
 
 int irClickSwitchState1 = 0;
 int irButtonState1 = 0;
 int irLastButtonState1 = 0;

int val1;

//______________________________
 const int irInput2 = A2; // IR
 
 int irClickSwitchState2 = 0;
 int irButtonState2 = 0;
 int irLastButtonState2 = 0;

int val2;

//______________________________
 const int irInput3 = A3; // IR

int irClickSwitchState3 = 0;
 int irButtonState3 = 0;
 int irLastButtonState3 = 0;

int val3;
 //_______________________________
 const int irInput4 = A4; // IR
 
 int irClickSwitchState4 = 0;
 int irButtonState4 = 0;
 int irLastButtonState4 = 0;

int val4;
//_______________________________
 const int irInput5 = A5; // IR
 
 int irClickSwitchState5 = 0;
 int irButtonState5 = 0;
 int irLastButtonState5 = 0;

int val5;
//_______________________________



bool triggerA0 = false;
 bool triggerA1 = false;
 bool triggerA2 = false;
 bool triggerA3 = false;
 bool triggerA4 = false;
 bool triggerA5 = false;
 
bool trigger = false; 
bool triggerD1 = false;
bool triggerD2 = false;
bool triggerD3 = false;
bool triggerD4 = false;
bool triggerD5 = false;
bool triggerD6 = false;
bool triggerD7 = false;
bool triggerD8 = false;
bool triggerD9 = false;
bool triggerD10 = false;
bool triggerD11 = false;
bool triggerD12 = false;
bool triggerD13 = false;



void setup() {

// pinMode(ledPin, OUTPUT);

pinMode(irInput, INPUT);
 pinMode(irInput1, INPUT);
// pinMode(irInput2, INPUT);
// pinMode(irInput3, INPUT);
// pinMode(irInput4, INPUT);
// pinMode(irInput5, INPUT);
//

pinMode(buttonPin2, INPUT);
 pinMode(buttonPin3, INPUT);
 pinMode(buttonPin4, INPUT);
 pinMode(buttonPin5, INPUT);
 pinMode(buttonPin6, INPUT);
 pinMode(buttonPin7, INPUT);
 pinMode(buttonPin8, INPUT);
 pinMode(buttonPin9, INPUT);
 pinMode(buttonPin10, INPUT);
 pinMode(buttonPin11, INPUT);
 pinMode(buttonPin12, INPUT); 
 pinMode(buttonPin13, INPUT); 
 
 
 Serial.begin(9600);
 
}
void loop() { 
 // DIGITAL INPUTS:______________________________________________________________DIGITAL iNPUTS

//___________button (2):

buttonState2=digitalRead(buttonPin2);

//compare button state aginst previous
 if (buttonState2 != lastButtonState2){
 
 triggerD2 = true;
 
 if (buttonState2 == HIGH) {
 
 clickSwitchState2 = 1;
 }
 else {
 
 clickSwitchState2 = 0;
 }
 }
 lastButtonState2 = buttonState2;

//______________button (3):

buttonState3=digitalRead(buttonPin3);

//compare button state aginst previous
 if (buttonState3 != lastButtonState3){
 
 triggerD3 = true;
 
 if (buttonState3 == HIGH) {
 
 clickSwitchState3 = 1;
 }
 else {
 
 clickSwitchState3 = 0;
 }
 }
 lastButtonState3 = buttonState3;
 
//___________button (4):

buttonState4=digitalRead(buttonPin4);

//compare button state aginst previous
 if (buttonState4 != lastButtonState4){
 
 triggerD4 = true;
 
 if (buttonState4 == HIGH) {
 
 clickSwitchState4 = 1;
 }
 else {
 
 clickSwitchState4 = 0;
 }
 }
 lastButtonState4 = buttonState4;

//___________button (5):

buttonState5=digitalRead(buttonPin5);

//compare button state aginst previous
 if (buttonState5 != lastButtonState5){
 
 triggerD5 = true;
 
 if (buttonState5 == HIGH) {
 
 clickSwitchState5 = 1;
 }
 else {
 
 clickSwitchState5 = 0;
 }
 }
 lastButtonState5 = buttonState5; 
 
//___________button (6):

buttonState6=digitalRead(buttonPin6);

//compare button state aginst previous
 if (buttonState6 != lastButtonState6){
 
 triggerD6 = true;
 
 if (buttonState6 == HIGH) {
 
 clickSwitchState6 = 1;
 }
 else {
 
 clickSwitchState6 = 0;
 }
 }
 lastButtonState6 = buttonState6;

//___________button (7):

buttonState7=digitalRead(buttonPin7);

//compare button state aginst previous
 if (buttonState7 != lastButtonState7){
 
 triggerD7 = true;
 
 if (buttonState7 == HIGH) {
 
 clickSwitchState7 = 1;
 }
 else {
 
 clickSwitchState7 = 0;
 }
 }
 lastButtonState7 = buttonState7;

//___________button (8):

buttonState8=digitalRead(buttonPin8);

//compare button state aginst previous
 if (buttonState8 != lastButtonState8){
 
 triggerD8 = true;
 
 if (buttonState8 == HIGH) {
 
 clickSwitchState8 = 1;
 }
 else {
 
 clickSwitchState8 = 0;
 }
 }
 lastButtonState8 = buttonState8;

//___________button (9):

buttonState9=digitalRead(buttonPin9);

//compare button state aginst previous
 if (buttonState9 != lastButtonState9){
 
 triggerD9 = true;
 
 if (buttonState9 == HIGH) {
 
 clickSwitchState9 = 1;
 }
 else {
 
 clickSwitchState9 = 0;
 }
 }
 lastButtonState9 = buttonState9;

//___________button (10):

buttonState10=digitalRead(buttonPin10);

//compare button state aginst previous
 if (buttonState10 != lastButtonState10){
 
 triggerD10 = true;
 
 if (buttonState10 == HIGH) {
 
 clickSwitchState10 = 1;
 }
 else {
 
 clickSwitchState10 = 0;
 }
 }
 lastButtonState10 = buttonState10;


 //___________button (11):

buttonState11=digitalRead(buttonPin11);

//compare button state aginst previous
 if (buttonState11 != lastButtonState11){
 
 triggerD11 = true;
 
 if (buttonState11 == HIGH) {
 
 clickSwitchState11 = 1;
 }
 else {
 
 clickSwitchState11 = 0;
 }
 }
 lastButtonState11 = buttonState11;


 //___________button (12):

buttonState12=digitalRead(buttonPin12);

//compare button state aginst previous
 if (buttonState12 != lastButtonState12){
 
 triggerD12 = true;
 
 if (buttonState12 == HIGH) {
 
 clickSwitchState12 = 1;
 }
 else {
 
 clickSwitchState12 = 0;
 }
 }
 lastButtonState12 = buttonState12;


 //___________button (13):

buttonState13=digitalRead(buttonPin13);

//compare button state aginst previous
 if (buttonState13 != lastButtonState13){
 
 triggerD13 = true;
 
 if (buttonState13 == HIGH) {
 
 clickSwitchState13 = 1;
 }
 else {
 
 clickSwitchState13 = 0;
 }
 }
 lastButtonState13 = buttonState13;

// ANALOG READ_IR SENSORS: _________________________________________________________________ANALOG 
// ____________(A0)______________:

val = analogRead(A0);
//Serial.println(val);
float avg = avg + 0.1*(val-avg);

if (abs(val-avg)>12){
 irButtonState = HIGH;
 }
 else if (abs(val-avg)>5){
 irButtonState = LOW;
 }
 else if (abs(val-avg)>1){
 irButtonState = HIGH;
 }

if (irButtonState != irLastButtonState){
 triggerA0 = true;
 
 // trigger = true;
 if (irButtonState == HIGH) {
 
 irClickSwitchState = 1;
 }
 else {
 
 irClickSwitchState = 0;
 }
 }
 irLastButtonState = irButtonState;
 
 ____________A1______________:
val1 = analogRead(A1);
float avg1 = avg1 + 0.1*(val1-avg1);

if (abs(val1-avg1)>12){
 irButtonState1 = HIGH;
 }
 else if (abs(val1-avg1)>5){
 irButtonState1 = LOW;
 }
 else if (abs(val1-avg1)>1){
 irButtonState1 = HIGH;
 }

if (irButtonState1 != irLastButtonState1){
 
 triggerA1 = true;
 if (irButtonState1 == HIGH) {
 
 irClickSwitchState1 = 1;
 }
 else {
 
 irClickSwitchState1 = 0;
 }
 //incase of bounce
 // delay(50);
 }
 irLastButtonState1 = irButtonState1;
 ____________A2______________:
val2 = analogRead(A2);
float avg2 = avg2 + 0.1*(val2-avg2);

if (abs(val2-avg2)>12){
 irButtonState2 = HIGH;
 }
 else if (abs(val2-avg2)>5){
 irButtonState2 = LOW;
 }
 else if (abs(val2-avg2)>1){
 irButtonState2 = HIGH;
 }

if (irButtonState2 != irLastButtonState2){
 
 triggerA2 = true;
 if (irButtonState2 == HIGH) {
 
 irClickSwitchState2 = 1;
 }
 else {
 
 irClickSwitchState2 = 0;
 }
 //incase of bounce
 // delay(50);
 }
 irLastButtonState2 = irButtonState2;

____________A3______________:
val3 = analogRead(A3);
float avg3 = avg3 + 0.1*(val3-avg3);

if (abs(val3-avg3)>12){
 irButtonState3 = HIGH;
 }
 else if (abs(val3-avg3)>5){
 irButtonState3 = LOW;
 }
 else if (abs(val3-avg3)>1){
 irButtonState3 = HIGH;
 }

if (irButtonState3 != irLastButtonState3){
 
 triggerA3 = true;
 if (irButtonState3 == HIGH) {
 
 irClickSwitchState3 = 1;
 }
 else {
 
 irClickSwitchState3 = 0;
 }
 //incase of bounce
 // delay(50);
 }
 irLastButtonState3 = irButtonState3;

____________A4______________:
val4 = analogRead(A4);
float avg4 = avg4 + 0.1*(val4-avg4);

if (abs(val4-avg4)>12){
 irButtonState4 = HIGH;
 }
 else if (abs(val4-avg4)>5){
 irButtonState4 = LOW;
 }
 else if (abs(val4-avg4)>1){
 irButtonState4 = HIGH;
 }

if (irButtonState4 != irLastButtonState4){
 
 triggerA4 = true;
 if (irButtonState4 == HIGH) {
 
 irClickSwitchState4 = 1;
 }
 else {
 
 irClickSwitchState4 = 0;
 }
 //incase of bounce
 // delay(50);
 }
 irLastButtonState4 = irButtonState4;



____________A5_____________:
val5 = analogRead(A5);
float avg5 = avg5 + 0.1*(val5-avg5);

if (abs(val5-avg5)>12){
 irButtonState5 = HIGH;
 }
 else if (abs(val5-avg5)>5){
 irButtonState5 = LOW;
 }
 else if (abs(val5-avg5)>1){
 irButtonState5 = HIGH;
 }

if (irButtonState5 != irLastButtonState5){
 
 triggerA5 = true;
 if (irButtonState5 == HIGH) {
 
 irClickSwitchState5 = 1;
 }
 else {
 
 irClickSwitchState5 = 0;
 }
 //incase of bounce
 // delay(50);
 }
 irLastButtonState5 = irButtonState5;



//___________sPrint_______

if (
(triggerA0 == true) ||
(triggerA1 == true) || 
(triggerA2 == true) ||
(triggerA3 == true) ||
(triggerA4 == true) ||
(triggerA5 == true) ||

(triggerD2 == true) || 
(triggerD3 == true) ||
(triggerD4 == true) ||
(triggerD5 == true) ||
(triggerD6 == true) ||
(triggerD7 == true) ||
(triggerD8 == true) ||
(triggerD9 == true) ||
(triggerD10 == true)||
(triggerD11== true) ||
(triggerD12== true) ||
(triggerD13 == true))

{

//row1
 Serial.print(buttonState2);
 Serial.print(" ");

Serial.print(buttonState3);
 Serial.print(" ");

Serial.print(buttonState4);
 Serial.print(" ");
 
 //row2

Serial.print(buttonState5);
 Serial.print(" ");
 
 Serial.print(buttonState6);
 Serial.print(" ");
 
 Serial.print(buttonState7);
 Serial.print(" ");
 //row3
 
 
 Serial.print(buttonState8);
 Serial.print(" ");
 Serial.print(buttonState9);
 Serial.print(" ");
 Serial.print(buttonState10);
 
 //row 4
 
 Serial.print(" ");
 Serial.print(buttonState11);
 Serial.print(" ");
 Serial.print(buttonState12);
 Serial.print(" ");
 Serial.print(buttonState13);
 Serial.print(" ");
 //IR

Serial.print(irClickSwitchState);
 Serial.print(" ");
 Serial.print(irClickSwitchState1);
 Serial.print(" ");
 Serial.print(irClickSwitchState2);
 Serial.print(" ");
 Serial.print(irClickSwitchState3);
 Serial.print(" ");
 Serial.print(irClickSwitchState4);
 Serial.print(" ");
 Serial.println(irClickSwitchState5);

triggerA0 = false;
 triggerA1 = false;
 triggerA2 = false;
 triggerA3 = false;
 triggerA4 = false;
 triggerA5 = false;


triggerD2 = false;
 triggerD3 = false;
 triggerD4 = false;
 triggerD5 = false;
 triggerD6 = false;
 triggerD7 = false;
 triggerD8 = false;
 triggerD9 = false;
 triggerD10 = false;
 triggerD11 = false;
 triggerD12 = false;
 triggerD13 = false;
// Serial.println(val);



}
 delay(50);
}