Group 7 : LED Performance Trousers
Dance Your Cares Away…
By Group 7 Teodora Toma, Nora Kennech
Project Brief: Dance Your Cares Away…
When you finish this project you will be the envy of the dance floor. Create an e-textile (t-shirt, bag, skirt, etc) with interactive leds that can be set to either flash to the beats of the music or the movement of the wearer. There is lots of example code out there, so you will need to think of how to make yours stand out.. Could you detect and come up with appropriate lighting schemes (a jump, a twirl?) for certain movements or sounds (the slow dance, the fast one, a surprising sound??). Remember to be creative but get started on programming the reactions even before you finish the garment (just use the sensors and LEDs with a normal Arduino to get started.
Purpose:
Our intent is to create an easy-to-use wearable that reacts to users’ movements and environments with specific sounds, lights, brightnesses.
Target Audience: Performers, Dancers
This project is intended to be used by scenic arts performers. Thus, the whole design of the wearables needed to suit the user’s profile and requirements. A wide range of movements are being carried out on stages by performers. Stepping and moving to the beat/rhythm of the music are the basics of any performance. Wearable must be able to resist this.
Market Research:
Components:
- 1 Arduino UNO
- 4 Individually Addressable LED Strip
- 1 Force Sensitive Resistor
- 1 Sound Sensor
- 1 Breadboard
- 4 100K OHM Resistors
- 1 10K OHM Resistor
- 1 9V Battery
- Male, Female, Male-Female Cables
- Carpet Strong Tape
- Trousers
Goals:
- Create an interactive wearable that responds to performers’ movements and environments
- Make it as easy to use as possible by not adding hidden features
- Analyse both sound levels and stepping pressure
- Give distinguished and clear feedback on both analysed inputs
Task List:
- Brainstorming and Research: Nora & Teodora
- Low-fidelity Prototypes and Storyboards : Nora & Teodora
- Components Order : Nora
- Test Components : Nora & Teodora
- Project Code : Nora & Teodora
- Testing and Debugging : Nora & Teodora
- Components Assembly : Nora & Teodora
- Images/Videos : Nora
- Circuit Layout : Nora
- Blog Documentation : Nora
- Blog Design : Teodora
- Presentation : Teodora
Meeting 1/ 16th November
Brainstorming: Project Ideas
- Music Gloves: Gloves activated with friction and pressure that would make different sounds. Play melodies with these with the bare motion of the fingers.
- LED Performance Trousers: Microphone sensor detects the different beats and tonalities of the music, input which will control a pair of led strips located on the sides of the trousers. A force sensor which the dancer will attach to their shoe will control another pair of led strip lights located on the front of the trousers.
- DC Motor Controlled Bow Tie: The tie will spin around a certain number of degrees depending on the pushbutton the performer presses.
Conclusion: LED Performance Trousers
After comparing these three ideas, efficiency, safety, utility, understandability and usability we got to the conclusion that the LED performance trousers were the ideal match to our requirements:
- No need of usage instructions: automatic feedback from the music playing and the natural stepping in the choreography
- Large area for providing feedback on both sounds and movements.
- Basic clothing item
Meeting 2/ 20th November
Components Research
Our first design decision was having two main sensors, to map the analog input of the sounds and the movements of the dancer: a force sensitive resistor, and a microphone sensor. Then we analysed what to use to display output/feedback.
Our main first idea was to place two different colours of led bulbs for the two different inputs over the trouser’s legs, which brightnesses’s would vary according to the analog values. However, after taking into consideration how unpractical and complicated the installation of the bulbs would be; and also their fragility and safety issues for the desired purpose, we decided to look into alternatives.
Determined to map movements and sounds into lights, we conducted research on available light sources that would match our requirements, and we found the perfect candidate: LED Strips.
Interaction Design
These LED Strips would have two main functionalities depending on what sensor they are connected to:
- A pair of LED strips attached to the outer-side of the trousers, of which output would vary depending on the music playing.
- A pair of LED strips attached to the inner-side of the trousers, controlled by the stepping pressure input captured by the force sensitive resistor.
Meeting 3/ 23rd November
Implementation of Design Principles: Feedback Visibility, Safety Constraints
After the progress made in the previous meeting, the next task was to take into consideration visibility and usability of our design.
Firstly we focused on the placement of the LEDs on the trousers. These needed to be attached using some very strong adhesive, as sewing might damage both the LEDs Strips and the trousers. Therefore we did some research and came across some ultra strong carpet tape.
To minimise both detachment and breakage risks, we decided we would stick the LEDs strips on the inside of the trousers. Moreover, in this way, we would achieve a ‘surprise’ factor for the audience, as the LEDs would not be visible for weak input values. However, with this came our new design decision, to place tape strips between the LEDs of the LED Strips, as to not obstruct their brightnesses.
Next we had to decide the location of the sensors.These would have to be placed in strategic locations to provide maximum efficiency and functionality. Therefore, we decided that the force resistor should be attached to the performer’s shoe, where it would capture the fluctuation of pressure of the stepping. The microphone would be placed on the top part of the trousers to capture the sound as neatly as possible, avoiding background noises.
Meeting 4/ 26th November
Low-fi Prototyping: Sketches, Storyboards
Meeting 5/ 30th November
Components Trial Processes
- Learn how to connect components to Arduino UNO
- Create mock sketches analysing the analog inputs from the sensors for adjusting sensitivity
- Assembly LEDs’ and sensors’ code in one sketch to try functionality
Force Sensitive Resistor with LEDs
Sound Sensor with LEDs: Tutorial
Meeting 6/ 2nd December
Once we had a first outline of how our components looked like inside our sketch it was time for us to tailor the mapping of the components’ input into our code.
Force Sensitive Resistor Mapping: So far we had only tried using the force sensitive resistor applying pressure with our hands. Therefore we had to try it using our feet. Using the serial monitor as a reference we mapped our ideal max and min pressure values.
Sound Mapping: The same process was followed with the microphone, but this time using different music genres, and adjusting its sensitivity using a screwdriver to rotate its sensitivity-meter.
LEDs Strips’ Feedback: For the lights the execution was different. We had to decide which pattern these would follow and what colours they would have. About colours, we decided that for the strips controlled by the force resistor, all LEDs would share the same colour, which would change at each step all together; and for the sound-controlled ones, we decided to give a random colour to each LED, making it more ‘fun’ and unpredictable. Meanwhile, for the functionality, we decided that for the strips controlled by the force resistor, these would light up one after the other once triggered, and would turn off the same way after a small delay time. The amount of LEDs turned on would depend on the intensity of the stepping, the higher the more LEDs torn on. The sound-controlled ones follow the same pattern, but stores an average value of the few last input values on which is based the number of LEDs to turn on.
Meeting 7/ 3rd December
Final Components Assembly: Sticking the LEDs Strips to the trousers
We realised that the front LEDs would not look good if we kept them in their original length, therefore we cut them from 60 led to 33 led. This also meant we had to change the values of the LEDs number in our code. To attach the LED strips to the trousers we flip them over, as they were going to be stuck on the inside. We used small squares of the carpet tape in between each individual LED to achieve maximum sticking surface. Once these were nicely secured, It was time to wire up the pants. Cables were also stuck with the same carpet tape to the trousers.
The force sensitive resistance was connected to two long cables that would be attached to the trouser’s insides. The same process was followed when attaching the rest of the components, achieving a neat and minimal look of the exterior or the trousers.
All cable ends and connectors were conducted to the left pocket of the trousers where the arduino and the breadboard would be stored. Everything was carefully connected together, making sure no errors were made or no cables were missed.
Meeting 8/ 4rd December
The trousers were working as we wanted them to, but most next risky step or the production was yet to come. As an electronic wearable, the fragility, and possible breakage of components were one of our main concerns. Very carefully, we tried them on, and connected the arduino to a 9V battery, which would be the main source of power.
Once on we first tried them on, our performance wearable accomplished its goals, and achieved optimal functionality.
Meeting 9/ 5rd December
While getting the trousers off, some of the cables broke inside the pins. We had to very carefully use some tweezers to remove one by one the metal parts stuck on the board, and to try bringing the project back to optimal functionality.
Maker’s Manual: How is it done?
Technology is being used more and more in the dance and interpretation world, since it is a great tool to accompany and give a whole new meaning to the artist’s performances. This project consists of a dance performance wearable, specifically trousers, with 2 types of LED controls incorporated, which are controlled both by the music playing, and also by the user.
A microphone sensor detects the different beats and tonalities of the music input which will control a pair of led strips located on the sides of the trousers. A force sensor which the dancer will attach to their shoe will control another pair of led strip lights located on the front of the trousers. These will light up controlled by the stepping of the performer.
Build Section
- Connect ground and 5V to breadboard.
- Connect 5V to the IN of the LED, ground to the OUT, and connect a cable with a 100K OHM resistance to the middle(W) and that to your digital pin of choice (for us is pin 13, 11,6,3). Do it for all the LEDs.
- Connect your force resistor to two long female cables. Then connect the right cable to the breadboard, and connect the same column to 5V. Then connect the left cable to the breadboard and connect a cable in the same column to your desired Analog pin (A0 for us). Don’t forget to put a 10K OHM resistance in between the cable of the sensor and the cable that goes to the analog pin.
- Connect your microphone having the in pin to 5v and out pin to ground, and power(w) to Analog pin 1.
- Put the pants inside out and stick the LEDs into the side and the middle of the leg using the carpet tape. Make sure to have all cable connections facing to the left pocket where the Arduino goes.
- Connect long cables across the pants, from the components to the arduino, sticking them to the inside with the tape.
- Tape all connections together so they don’t disconnect with the motion.
- Upload the code.
- Insert Arduino into pocket.
- Connect 9V battery to power the device.
Breadboard Layout
SHORTCOMINGS:
- Since it’s a wearable, and the wires are not welded together, they die-attach with ease, ruining their functionality. Thus to improve our approach we would have to weld the wires together.
- The lack of case or protector for the arduino is also a major shortcoming, due to the high risk of breakage.
- The reaction functionality of the lights to the music is not ideal, and could be improved in relation to the volume of the sound playing.
- The force sensitive resistor on the foot could be improved, with the building of a “shoe attacher” to get the best response possible, rather than just sticking it.
#include <FastLED.h>
#include <Adafruit_NeoPixel.h>
/** BASIC CONFIGURATION FOR SOUND LEDs **/
//The amount of LEDs in the setup
#define NUM_LEDS 60 // for side sound LEDs
//The pin that controls the LEDs
#define LED_PIN 13
#define LED_PIN2 11
//The pin that we read sound sensor values form
#define ANALOG_READ 2
//Confirmed microphone low value, and max value
#define MIC_LOW 500.0
#define MIC_HIGH 1000.0
/** Other macros */
//How many previous sensor values effects the operating average
#define AVGLEN 4
//How many previous sensor values decides if we are on a peak/HIGH (e.g. in a song)
#define LONG_SECTOR 50
//How many previous sensor values decides if we are on a peak/HIGH (e.g. in a song)
#define LONG_SECTOR 50
//Mneumonics
#define HIGH 3
#define NORMAL 2
//How long do we keep the “current average” sound, before restarting the measuring
#define MSECS 20 * 1000
#define CYCLES MSECS / DELAY
/* How much is a reading allowed to deviate from the average. **/
#define DEV_THRESH 0.8
//Arduino loop delay
#define DELAY 1
//Average sound measurement the last CYCLES
unsigned long song_avg;
//The amount of iterations since the song_avg was reset
int iter = 0;
//How many LEDs to we display
int curshow = NUM_LEDS;
//The speed the LEDs fade
float fade_scale = 1.2;
//Led array
CRGB leds[NUM_LEDS];
// Short sound avg used to “normalize” the input values.
int avgs[AVGLEN] = {-1};
//Longer sound avg
int long_avg[LONG_SECTOR] = {-1};
//Showing different colors based on the mode for future implementation
int songmode = NORMAL;
//Keeping track how often, and how long times we hit a certain mode for future implementation
struct time_keeping {
unsigned long times_start;
short times;
};
struct time_keeping high;
//Colour every cycle
struct color {
int r;
int g;
int b;
};
struct color Color;
float fscale( float originalMin, float originalMax, float newBegin, float newEnd, float inputValue, float curve);
void insert(int val, int *avgs, int len);
int compute_average(int *avgs, int len);
void visualize_music();
/** BASIC CONFIGURATION FOR FORCE SENSOR LEDs **/
//The amount of LEDs in the setup
#define LED_COUNT 33 // for middle force sensor
//The pin that controls the LEDs
#define LED_PIN3 6
#define LED_PIN4 4
Adafruit_NeoPixel strip(LED_COUNT, LED_PIN3, NEO_GRB + NEO_KHZ800);
Adafruit_NeoPixel strip2(LED_COUNT, LED_PIN4, NEO_GRB + NEO_KHZ800);
//The pin that we read force sensor values form
int pressureAnalogPin = 0;
//Force measurement
int pressureReading;
void setup() {
//Set all lights
FastLED.addLeds<NEOPIXEL, LED_PIN>(leds, NUM_LEDS);
FastLED.addLeds<NEOPIXEL, LED_PIN2>(leds, NUM_LEDS);
FastLED.show();
strip.begin();
strip.show();
strip2.begin();
strip2.show();
delay(1000);
//bootstrap average sound with some low values
for (int i = 0; i < AVGLEN; i++) {
insert(250, avgs, AVGLEN);
}
//Initial values
Color.r = 0;
Color.g = 0;
Color.b = 0;
}
void loop() {
visualize_steps();
visualize_music();
delay(DELAY);
}
// Function to configure the number of force LEDs to turn on and LEDs’ brightnesses
void visualize_steps(){
pressureReading = analogRead(pressureAnalogPin);
//Decides how many of the LEDs will be lit
int val = map(pressureReading, 900, 1023, 0, 33);
int rColour = random(0,255);
int gColour = random(0,255);
int bColour = random(0,255);
strip.setBrightness(val);
strip2.setBrightness(val);
colorWipe(strip.Color(rColour, gColour, bColour), 5, val);
}
// Function to turn On the input number of force LEDs
void colorWipe(uint32_t color, int wait, int numLEDS) {
for(int i=0; i<numLEDS; i++) {
strip.setPixelColor(i, color);
strip2.setPixelColor(i, color);
strip.show();
strip2.show();
delay(wait);
}
for(int i=numLEDS; i>0; i–) {
strip.setPixelColor(i, 0, 0, 0);
strip2.setPixelColor(i, 0, 0, 0);
strip.show();
strip2.show();
delay(wait);
}
}
void visualize_music() {
int sensor_value, mapped, avg, longavg;
sensor_value = analogRead(ANALOG_READ);
//If 0, likely not right and save CPU.
if (sensor_value == 0)
return;
//Discard readings that deviates too much from the past avg.
mapped = (float)fscale(MIC_LOW, MIC_HIGH, MIC_LOW, (float)MIC_HIGH, (float)sensor_value, 2.0);
avg = compute_average(avgs, AVGLEN);
if (((avg – mapped) > avg*DEV_THRESH)) //|| ((avg – mapped) < -avg*DEV_THRESH))
return;
//Insert new avg. values
insert(mapped, avgs, AVGLEN);
insert(avg, long_avg, LONG_SECTOR);
//Compute the “song average” sensor value
song_avg += avg;
iter++;
if (iter > CYCLES) {
song_avg = song_avg / iter;
iter = 1;
}
//Preset initial start values
if (songmode == NORMAL) {
fade_scale = 2;
Color.r = 1;
Color.b = 1;
Color.g = 1;
}
//Decides how many of the LEDs will be lit
curshow = fscale(MIC_LOW, MIC_HIGH, 0.0, (float)NUM_LEDS, (float)avg, -1);
// Set colour of sound LEDs
for (int i = 0; i < NUM_LEDS; i++)
//Turns LEDs On
if (i < curshow) {
//First 15LEds inside the pockets
if(i<15){
leds[i].r = 0;
leds[i].g = 0;
leds[i].b = 0;
}
else{
leds[i].r = random(0,255);
leds[i].g = random(0,255);
leds[i].b = random(0,255);
}
//All the other LEDs’ fading journey
} else {
leds[i] = CRGB(leds[i].r/fade_scale, leds[i].g/fade_scale, leds[i].b/fade_scale);
}
FastLED.show();
}
//Function to compute average of a int array, given the starting pointer and the length
int compute_average(int *avgs, int len) {
int sum = 0;
for (int i = 0; i < len; i++)
sum += avgs[i];
return (int)(sum / len);
}
//Function to insert a value into an array, and shift it down removing
//the first value if array already full
void insert(int val, int *avgs, int len) {
for (int i = 0; i < len; i++) {
if (avgs[i] == -1) {
avgs[i] = val;
return;
}
}
for (int i = 1; i < len; i++) {
avgs[i – 1] = avgs[i];
}
avgs[len – 1] = val;
}
//Function imported from the arduino website: map with a curve on the scale
float fscale( float originalMin, float originalMax, float newBegin, float
newEnd, float inputValue, float curve){
float OriginalRange = 0;
float NewRange = 0;
float zeroRefCurVal = 0;
float normalizedCurVal = 0;
float rangedValue = 0;
boolean invFlag = 0;
if (curve > 10) curve = 10;
if (curve < -10) curve = -10;
curve = (curve * -.1) ;
curve = pow(10, curve);
// Check for out of range inputValues
if (inputValue < originalMin){
inputValue = originalMin;
}
if (inputValue > originalMax){
inputValue = originalMax;
}
// Zero Refference the values
OriginalRange = originalMax – originalMin;
if (newEnd > newBegin){
NewRange = newEnd – newBegin;
} else {
NewRange = newBegin – newEnd;
invFlag = 1;
}
zeroRefCurVal = inputValue – originalMin;
normalizedCurVal = zeroRefCurVal / OriginalRange;
// Check for originalMin > originalMax
if (originalMin > originalMax ) {
return 0;
}
if (invFlag == 0){
rangedValue = (pow(normalizedCurVal, curve) * NewRange) + newBegin;
} else {// invert the ranges
rangedValue = newBegin – (pow(normalizedCurVal, curve) * NewRange);
}
return rangedValue;
}