The (almost) Firefly¶
Introduction¶
Art imitates nature, and so can wearable electronics. I’ve designed an outfit inspired by my fascination towards firflies. The (almost) Firefly is a copying of what makes fireflies special, their light. Thus, the skirt is designed to respond to motion by sparkling light.
A Closer Look¶
So… how does it work? After all the trials and error I had, I can finally say, it’s fairly simple! The microcontroller is programmed to calculate the acceleration vector every 600 milliseconds, if the latest vector is larger than a set variable, motion is recognized and is responded with light.
An Even Closer Look¶
The Design¶
The top is plain and basic green tank that was laser-cut and then laser-engraved with a firefly to live up to the project’s name.
The skirt has two layers (disregarding the pouch that pockets the battery). The first layer holds the neopixels and is a dark blue to emphasize the light and resemble the ponds where fireflies live. The layer above is a sheer dark blue organza to add texture and hide the scars of the electronics sewn on the first layer.
The Electronics¶
The layout of the electronics is pretty simple. The battery is attached to a booster to acheive the optimum 5V, which is then connected to VCC and GND pins on seperate small boards I like to call “The Common”, which are soldered to the microcontroller’s (ATtiny85) VCC and GND pins, that is connected to the MPU-6050, and the neopixels use the MISO on the ATtiny and the VCC and GND from The Common.
The Code¶
The code is combination of Ashish Choudary’s “Build a Portable Step Counter using ATtiny85 and MPU6050” code, and the color wipe function from the AdaFruit Neopixel Library examples + some of my changes.
#include "TinyWireM.h"
#include <Adafruit_NeoPixel.h>
#ifdef __AVR__
#include <avr/power.h> // Required for 16 MHz Adafruit Trinket
#endif
#define LED_PIN 6
#define LED_COUNT 11
Adafruit_NeoPixel strip(LED_COUNT, LED_PIN, NEO_GRB + NEO_KHZ800);
int accelX, accelY, accelZ;
char mpu = 0x68;
float vectorprevious;
float vector;
float totalvector;
void setup() {
#if defined(__AVR_ATtiny85__) && (F_CPU == 16000000)
clock_prescale_set(clock_div_1);
#endif
strip.begin(); // INITIALIZE NeoPixel strip object (REQUIRED)
strip.show(); // Turn OFF all pixels ASAP
strip.setBrightness(50); // Set BRIGHTNESS to about 1/5 (max = 255)
TinyWireM.begin();
TinyWireM.beginTransmission(mpu);
TinyWireM.write(0x6B); // Power setting address
TinyWireM.write(0b00000000); // Disable sleep mode (just in case)
TinyWireM.endTransmission();
TinyWireM.beginTransmission(mpu);
TinyWireM.write(0x1B); // Config register for Gyro
TinyWireM.write(0x00000000); // 250° per second range (default)
TinyWireM.endTransmission();
TinyWireM.beginTransmission(mpu); //I2C address of the MPU
TinyWireM.write(0x1C); // Accelerometer config register
TinyWireM.write(0b00000000); // 2g range +/- (default)
TinyWireM.endTransmission();
}
void loop() {
getAccel();
vector = sqrt( (accelX * accelX) + (accelY * accelY) + (accelZ * accelZ) );
totalvector = vector - vectorprevious;
if (totalvector > 6){
colorWipe(strip.Color(255, 255, 51), 50); // yellow
colorWipe(strip.Color( 255, 255, 255), 50); // white
colorWipe(strip.Color( 153, 255, 255), 50); // Blue
}
strip.show(); // Turn OFF all pixels ASAP
vectorprevious = vector;
delay(600);
}
void getAccel() {
TinyWireM.beginTransmission(mpu); //I2C address of the MPU
TinyWireM.write(0x3B); // Acceleration data register
TinyWireM.endTransmission();
TinyWireM.requestFrom(mpu, 6); // Get 6 bytes, 2 for each DoF
accelX = TinyWireM.read() << 8|TinyWireM.read();
accelY = TinyWireM.read() << 8|TinyWireM.read();
accelZ = TinyWireM.read() << 8|TinyWireM.read();
}
void colorWipe(uint32_t color, int wait) {
for(int i=0; i<strip.numPixels(); i++) { // For each pixel in strip...
strip.setPixelColor(i, color); // Set pixel's color (in RAM)
strip.show(); // Update strip to match
delay(wait); // Pause for a moment
}
}