The Power Bracelet

This wearable housing for the Adafruit Flora incorporates light, sound and a unique capacitive touch sensing interface to allow a range of potential low-fi functions. This prototype functions as a light-up musical keyboard on your wrist for spontaneous musical interludes to your daily life.

lucy brandon

Kahler_W_bracelet 2 (1024x768)

Kahler_W_bracelet1 (1024x768)

A 3D printed enclosure is capped with a translucent lid of laser-cut and laminated acrylic. The wristband is of muslin, with a Velcro clasp.

Kahler_W_bracelet 4 (1024x768)

These capacitive buttons are very low-cost can be incorporated into a flexible medium, such as the fabric of the wristband, without adding bulk or rigidity. The consist of conductive fabric, with a machine-embroidered border and are connected to the micro-controller via conductive thread.

piezo2

The Flora board is outfitted with two neopixels soldered directly to the board, a small rechargeable battery, and a piezo buzzer (shown unsoldered).

The computer models of the housing:

body lid

The bracelet is programmed to play four different arpeggiated chords in the key of G and flash a different color for each colors for each.

Watch the Video: http://www.youtube.com/watch?v=ey87flPV0ts&feature=youtu.be

Here’s the code:

#include <CapPin.h>

/* CapPin
* Capacitive Library CapPin Demo Sketch
* Paul Badger 2011
* This class uses the bullt-in pullup resistors read the capacitance on a pin
* The pin is set to input and then the pullup is set,
* A loop times how long the pin takes to go HIGH.
* The readPin method is fast and can be read 1000 times in under 10 mS.
* By reading the pin repeated you can sense “hand pressure”
* at close range with a small sensor. A larger sensor (piece of foil/metal) will yield
* larger return values and be able to sense at more distance. For
* a more senstive method of sensing pins see CapTouch
* Hook up a wire with or without a piece of foil attached to the pin.
* I suggest covering the sensor with mylar, packing tape, paper or other insulator
* to avoid having users directly touch the pin.
*/

CapPin cPin_2 = CapPin(2); // read pin 5
CapPin cPin_3 = CapPin(3);
CapPin cPin_4 = CapPin(9);
CapPin cPin_5 = CapPin(10);

#include <Adafruit_NeoPixel.h>

#define PIN 12

// Parameter 1 = number of pixels in strip
// Parameter 2 = pin number (most are valid)
// Parameter 3 = pixel type flags, add together as needed:
// NEO_KHZ800 800 KHz bitstream (most NeoPixel products w/WS2812 LEDs)
// NEO_KHZ400 400 KHz (classic ‘v1’ (not v2) FLORA pixels, WS2811 drivers)
// NEO_GRB Pixels are wired for GRB bitstream (most NeoPixel products)
// NEO_RGB Pixels are wired for RGB bitstream (v1 FLORA pixels, not v2)
Adafruit_NeoPixel strip = Adafruit_NeoPixel(2, PIN, NEO_GRB + NEO_KHZ800);

float smoothed;
float smoothed2;
float smoothed3;
float smoothed4;
#define NOTE_B0 31
#define NOTE_C1 33
#define NOTE_CS1 35
#define NOTE_D1 37
#define NOTE_DS1 39
#define NOTE_E1 41
#define NOTE_F1 44
#define NOTE_FS1 46
#define NOTE_G1 49
#define NOTE_GS1 52
#define NOTE_A1 55
#define NOTE_AS1 58
#define NOTE_B1 62
#define NOTE_C2 65
#define NOTE_CS2 69
#define NOTE_D2 73
#define NOTE_DS2 78
#define NOTE_E2 82
#define NOTE_F2 87
#define NOTE_FS2 93
#define NOTE_G2 98
#define NOTE_GS2 104
#define NOTE_A2 110
#define NOTE_AS2 117
#define NOTE_B2 123
#define NOTE_C3 131
#define NOTE_CS3 139
#define NOTE_D3 147
#define NOTE_DS3 156
#define NOTE_E3 165
#define NOTE_F3 175
#define NOTE_FS3 185
#define NOTE_G3 196
#define NOTE_GS3 208
#define NOTE_A3 220
#define NOTE_AS3 233
#define NOTE_B3 247
#define NOTE_C4 262
#define NOTE_CS4 277
#define NOTE_D4 294
#define NOTE_DS4 311
#define NOTE_E4 330
#define NOTE_F4 349
#define NOTE_FS4 370
#define NOTE_G4 392
#define NOTE_GS4 415
#define NOTE_A4 440
#define NOTE_AS4 466
#define NOTE_B4 494
#define NOTE_C5 523
#define NOTE_CS5 554
#define NOTE_D5 587
#define NOTE_DS5 622
#define NOTE_E5 659
#define NOTE_F5 698
#define NOTE_FS5 740
#define NOTE_G5 784
#define NOTE_GS5 831
#define NOTE_A5 880
#define NOTE_AS5 932
#define NOTE_B5 988
#define NOTE_C6 1047
#define NOTE_CS6 1109
#define NOTE_D6 1175
#define NOTE_DS6 1245
#define NOTE_E6 1319
#define NOTE_F6 1397
#define NOTE_FS6 1480
#define NOTE_G6 1568
#define NOTE_GS6 1661
#define NOTE_A6 1760
#define NOTE_AS6 1865
#define NOTE_B6 1976
#define NOTE_C7 2093
#define NOTE_CS7 2217
#define NOTE_D7 2349
#define NOTE_DS7 2489
#define NOTE_E7 2637
#define NOTE_F7 2794
#define NOTE_FS7 2960
#define NOTE_G7 3136
#define NOTE_GS7 3322
#define NOTE_A7 3520
#define NOTE_AS7 3729
#define NOTE_B7 3951
#define NOTE_C8 4186
#define NOTE_CS8 4435
#define NOTE_D8 4699
#define NOTE_DS8 4978

void setup()
{

Serial.begin(115200);
Serial.println(“start”);
strip.begin();
strip.show(); // Initialize all pixels to ‘off’
// slider_2_7.calibrateSlider();

}

void loop()
{
delay(1);
long total1 = 0;
long start = millis();
long total = cPin_2.readPin(2000);
long total2 = cPin_3.readPin(2000);
long total3 = cPin_4.readPin(2000);
long total4 = cPin_5.readPin(2000);
// simple lowpass filter to take out some of the jitter
// change parameter (0 is min, .99 is max) or eliminate to suit
smoothed = smooth(total, .1, smoothed);
smoothed2 = smooth(total2, .1, smoothed2);
smoothed3 = smooth(total3, .1, smoothed3);
smoothed4 = smooth(total4, .1, smoothed4);

//Serial.print( millis() – start); // time to execute in mS
//Serial.print(“\t”);
//Serial.print(total); // raw total
//Serial.print(“\t”);
//Serial.println((int) smoothed); // smoothed
//delay(2);
//Serial.print(“\t”);
//Serial.println((int) smoothed2); // smoothed
//delay(2);
//Serial.print(“\t”);
//Serial.println((int) smoothed3); // smoothed
//delay(2);
//Serial.print(“\t”);
//Serial.println((int) smoothed4); // smoothed
//delay(2);

if (smoothed>100 and smoothed2<100 and smoothed3<100 and smoothed4<100){
G_5 ();
}
if (smoothed<100 and smoothed2>100 and smoothed3<100 and smoothed4<100){
D_6 ();
}
if (smoothed<100 and smoothed2<100 and smoothed3>100 and smoothed4<100){
G_5 ();
}
if (smoothed<100 and smoothed2<100 and smoothed3<100 and smoothed4>100){
C_5 ();
}
if (smoothed<100 and smoothed2<100 and smoothed3<100 and smoothed4<100){
noTone(1);
}
}
void C_5(){
colorWipe(strip.Color(50, 50, 0), 0);
tone(1, NOTE_C5);
delay(100);
colorWipe(strip.Color(150, 150, 0), 0);
tone (1, NOTE_E5);
delay(100);
colorWipe(strip.Color(250, 250, 0), 0);
tone(1, NOTE_G5);
delay(100);
//tone (1, NOTE_C4);
//delay(30);
colorWipe(strip.Color(0, 0, 0), 0);
}
void G_5(){
colorWipe(strip.Color(50, 50, 50), 0);
tone(1, NOTE_G5);
delay(100);
colorWipe(strip.Color(150, 150, 150), 0);
tone (1, NOTE_B5);
delay(100);
colorWipe(strip.Color(250, 250, 250), 0);
tone(1, NOTE_D6);
delay(100);
//tone (1, NOTE_C4);
//delay(30);
colorWipe(strip.Color(0, 0, 0), 0);
}
void D_6(){
colorWipe(strip.Color(50, 0, 50), 0);
tone(1, NOTE_D6);
delay(100);
colorWipe(strip.Color(150, 0, 150), 0);
tone (1, NOTE_A5);
delay(100);
colorWipe(strip.Color(250, 0, 250), 0);
tone(1, NOTE_FS5);
delay(100);
colorWipe(strip.Color(0, 0, 0), 0);
}
void colorWipe(uint32_t c, uint8_t wait) {
for(uint16_t i=0; i<strip.numPixels(); i++) {
strip.setPixelColor(i, c);
strip.show();
delay(wait);
}
}
// simple lowpass filter
// requires recycling the output in the “smoothedVal” param
int smooth(int data, float filterVal, float smoothedVal){

if (filterVal > 1){ // check to make sure param’s are within range
filterVal = .999999;
}
else if (filterVal <= 0){
filterVal = 0;
}

smoothedVal = (data * (1 – filterVal)) + (smoothedVal * filterVal);

return (int)smoothedVal;
}