! [exclamation mark]

So this is my big exclamation mark for Halloween.

It started from soldering the sound board, which was, well, quite painful.

(this is how it looks like after two days of soldering – unsoldering – soldering again ūüė¶

This it is time for testing how the sensor works. It turns out it works without any driver, just plug in TWO power cables and TWO ground cables and one data cable, the result can be viewed immediately in the monitor.

Then to combine the different parts and let it work. The basic idea is, let the distance sensor detect the distance and when it reaches a value (here it is actually the value of 1000/d, since the noise is plentiful and it has an exponential growth), it turns the light on and sound board starts playing the music preset in the sd card.

The 3d printed exclamation marks has 0.8 mm walls so in dark environment it can be easily seen when the led is on.

The problem here is that the sound board cannot work simultaneously with other components, so when it starts to work, the light will stay on after the music is off.

Here is the code.

#include <Adafruit_NeoPixel.h>

#ifdef __AVR__

  #include <avr/power.h>

#endif

#define PIN            6

#define NUMPIXELS      16

Adafruit_NeoPixel pixels = Adafruit_NeoPixel(NUMPIXELS, PIN, NEO_GRBW + NEO_KHZ800);

int delayval = 1;

#include <WaveHC.h>

#include <WaveUtil.h>

SdReader card;

FatVolume vol;

FatReader root;

WaveHC wave;

uint8_t dirLevel;

dir_t dirBuf;

#define error(msg) error_P(PSTR(msg))

void play(FatReader &dir);

void setup() {

#if defined (__AVR_ATtiny85__)

  if (F_CPU == 16000000) clock_prescale_set(clock_div_1);

#endif

  pixels.begin();

  Serial.begin(9600);

¬† putstring_nl(“\nWave test!”);

¬† putstring(“Free RAM: “);

  Serial.println(FreeRam());

  //  if (!card.init(true)) {

  if (!card.init()) {

¬† ¬† error(“Card init. failed!”);

  }

  card.partialBlockRead(true);

  uint8_t part;

  for (part = 0; part < 5; part++) {

    if (vol.init(card, part))

      break;

  }

  if (part == 5) {

¬† ¬† error(“No valid FAT partition!”);

  }

¬† putstring(“Using partition “);

  Serial.print(part, DEC);

¬† putstring(, type is FAT”);

  Serial.println(vol.fatType(), DEC);

  if (!root.openRoot(vol)) {

¬† ¬† error(“Can’t open root dir!”);

  }

¬† putstring_nl(“Files found (* = fragmented):”);

  root.ls(LS_R | LS_FLAG_FRAGMENTED);

}

void loop() {

  int sensorValue = analogRead(A5);

  if (1000/sensorValue < 2){

    for(int i=0;i<NUMPIXELS;i++){

      pixels.setPixelColor(i, pixels.Color(255,0,0));

      pixels.show();

      delay(delayval);

     }

    root.rewind();

    play(root);

  }

    else {

       for(int i=0;i<NUMPIXELS;i++){

      pixels.setPixelColor(i, pixels.Color(0,0,0));

      pixels.show();

      delay(delayval);

   }

 }

}

void error_P(const char *str) {

¬† PgmPrint(“Error: “);

  SerialPrint_P(str);

  sdErrorCheck();

  while(1);

}

void sdErrorCheck(void) {

  if (!card.errorCode()) return;

¬† PgmPrint(“\r\nSD I/O error: “);

  Serial.print(card.errorCode(), HEX);

  PgmPrint(,);

  Serial.println(card.errorData(), HEX);

  while(1);

}

void play(FatReader &dir) {

  FatReader file;

  while (dir.readDir(dirBuf) > 0) {

    if (!DIR_IS_SUBDIR(dirBuf)

¬† ¬† ¬† ¬† ¬†&& strncmp_P((char *)&dirBuf.name[8], PSTR(“WAV”), 3)) {

      continue;

    }

    Serial.println();

    for (uint8_t i = 0; i < dirLevel; i++) {

¬† ¬† ¬† ¬†Serial.write(‘ ‘);

    }

    if (!file.open(vol, dirBuf)) {

¬† ¬† ¬† error(“file.open failed”);

    }

    if (file.isDir()) {

¬† ¬† ¬† putstring(“Subdir: “);

      printEntryName(dirBuf);

      Serial.println();

      dirLevel += 2;

      play(file);

      dirLevel -= 2;

    }

    else {

¬† ¬† ¬† putstring(“Playing “);

      printEntryName(dirBuf);

      if (!wave.create(file)) {

¬† ¬† ¬† ¬† putstring(” Not a valid WAV”);

      } else {

        Serial.println();

        wave.play();

        uint8_t n = 0;

        while (wave.isplaying) {

¬† ¬† ¬† ¬† ¬† putstring(“.”);

          if (!(++n % 32))Serial.println();

          delay(100);

        }

        sdErrorCheck();

      }

    }

  }

}

LED Vest in action.

Here is the starting sketch of the concept.

Color-Stealing-Suspenders.jpg

It quickly evolved into a vest format to ease up the complication of trying to fit everything in the suspender format.

I went a little overboard on the construction process by making a silicone sleeved , heat-shrink sealed, 10 LED unit that joined together with a connector. While this left me with a lot of versatility, it took way to long to construct.

You can see the overly involved construction process in these videos.

The final assembly ended up super durable, as it traveled well to Vegas stuffed in a carry-on (the TSA was very curious about it),  was stepped on, and had beer spilled on it during a concert.

The original intent of making it sample colors and add this into the animations was scrapped, as I was having some difficulty in figuring out how to integrate a sampled color into the LED animations that I was using within the time constraints I had. This is definitely something I am interested in figuring out in the future.

The final direction I went in was a series of animations that drove through 4 sets of parallel neopixel strips, with a push button cycling through the different animations.

The biggest leaning I found from the field was the brightness. It was WAY too bright to use during a concert. This was adjusted down to 40% following night one, but found that was still not enough. I made a scrambled attempt to integrate a potentiometer into the circuit to control the brightness, but may have been too intoxicated to pull this off.

F-wings, an Optical Show

P2290643

Hey y’all!

For my Halloween Costume, I made light-up fairy wings using the following ingredients:

  1. 12 and 24 gauge wires for the frame
  2. White stockings/tights to cover the frame
  3. .75 mm fiber optic cables to provide light patterns on the wings
  4. Neopixel RGB LED strips
  5. 3D printed couplings to make sure the fiber optic cable ends were flush with the LED strip
  6. Flora micro-controller to control the light animations
  7. 330 ő© resistors and wires to connect LED strips to Flora
  8. Foam board as a base and cover for the electronics on the middle
  9. Ample amounts of hot glue to connect the fiber optic cables and LED strips to the couplings
  10. Arduino code for the light animations
  11. Nylon thread to sew the fiber optic cables in place on the wings
  12. External battery pack to power wings

 

Some new skills I learned doing this project:

  • How to use a 3D printer.
  • How to work with end-glow fiber optic cables and what the different types of fiber optic cables are.

My biggest challenges with the project were:

  • 3D printing the couplings. It took a fair amount of time to measure everything and build the shape in Tinkercad.
  • Soldering wires in my circuit and to the Neopixels. Either the wire was popping off, or the “input ” copper pad kept melting, or the wire would break where the wire insulation ended. I ended up having to redo parts of the circuit several times.
  • The battery pack I used kept shutting down power after about 1.5-2 min because my circuit didn’t draw enough power.

 

Special thanks to Ted, Helen, and Pantea for helping me finish my costume. Thank you to Becky and Rhea as well for helping me put my costume on. I wouldn’t have made it to the parade without all of you!

 

Process Photos:

Halloween Wings Circuit-2.png

#include 

#define PIN 6

// use define instead of integer because PIN not changing, so treat as a constant.
// variables change, but constants don't. Constants take up less space.
// if doing a variable need an equal sign and a semicolon at end

#define NUM_LEDS 8

#define BRIGHTNESS 80

// Parameter 1 = number of pixels in strip
// Parameter 2 = pin number (most are valid)
// Parameter 3 = pixel type flags, add together as needed:
// NEO_RGB Pixels are wired for RGB bitstream
// NEO_GRB Pixels are wired for GRB bitstream, correct if colors are swapped upon testing
// NEO_RGBW Pixels are wired for RGBW bitstream
// NEO_KHZ400 400 KHz bitstream (e.g. FLORA pixels)
// NEO_KHZ800 800 KHz bitstream (e.g. High Density LED strip), correct for neopixel stick
Adafruit_NeoPixel strip = Adafruit_NeoPixel(NUM_LEDS, PIN, NEO_GRB + NEO_KHZ800);

// Adafruit_NeoPixel strip is like the "int" on regular arduino

void setup() {

// Always have to use strip.begin and strip.show when coding neopixels

strip.setBrightness(BRIGHTNESS);
strip.begin(); // Intitialize the pixels
strip.show(); // Initialize all pixels to 'off'
//use strip.show(); every time want to change the strip color

//for setup, "strip" is the name of the object we named above "Adafruit_Neopixel strip = [...]"
}

void loop() {
// Some example procedures showing how to display to the pixels:
colorWipe(strip.Color(255, 0, 0), 50); // Red
// 50 at end is the wait time
colorWipe(strip.Color(0, 255, 0), 50); // Green
colorWipe(strip.Color(0, 0, 255), 50); // Blue
colorWipe(strip.Color(0, 0, 0, 255), 50); // White

rainbowFade2White(3,3,1);
}

// Fill the dots one after the other with a color
void colorWipe(uint32_t c, uint8_t wait) {
//uint32_t is a special type of data but essentially just a fancy integer
//c is the name of the integer, and turns colorwipes in code earlier into a local function call
for(uint16_t i=0; i<strip.numPixels(); i++) {
//for loop starts at 0 and counts up by 1 until reaches until it reaches strip.numPixels
// which is the max number of pixels set at beginning
strip.setPixelColor(i, c);
strip.show();
//update all the pixels
//if put strip.show outside for loop, all the colors will show at once
delay(wait);
//wait
}
}

void rainbowFade2White(uint8_t wait, int rainbowLoops, int whiteLoops) {
float fadeMax = 100.0;
int fadeVal = 0;
uint32_t wheelVal;
int redVal, greenVal, blueVal;

for(int k = 0 ; k < rainbowLoops ; k ++){

for(int j=0; j<256; j++) { // 5 cycles of all colors on wheel

for(int i=0; i< strip.numPixels(); i++) {

wheelVal = Wheel(((i * 256 / strip.numPixels()) + j) & 255);

redVal = red(wheelVal) * float(fadeVal/fadeMax);
greenVal = green(wheelVal) * float(fadeVal/fadeMax);
blueVal = blue(wheelVal) * float(fadeVal/fadeMax);

strip.setPixelColor( i, strip.Color( redVal, greenVal, blueVal ) );

}

//First loop, fade in!
if(k == 0 && fadeVal < fadeMax-1) { fadeVal++; } //Last loop, fade out! else if(k == rainbowLoops - 1 && j > 255 - fadeMax ){
fadeVal--;
}

strip.show();
delay(wait);
}

}

delay(500);
for(int k = 0 ; k < whiteLoops ; k ++){

for(int j = 0; j < 256 ; j++){

for(uint16_t i=0; i < strip.numPixels(); i++) { strip.setPixelColor(i, strip.Color(0,0,0, j ) ); } strip.show(); } delay(2000); for(int j = 255; j >= 0 ; j--){

for(uint16_t i=0; i < strip.numPixels(); i++) { strip.setPixelColor(i, strip.Color(0,0,0, j ) ); } strip.show(); } } delay(500); } void whiteOverRainbow(uint8_t wait, uint8_t whiteSpeed, uint8_t whiteLength ) { if(whiteLength >= strip.numPixels()) whiteLength = strip.numPixels() - 1;

int head = whiteLength - 1;
int tail = 0;

int loops = 3;
int loopNum = 0;

static unsigned long lastTime = 0;
while(true){
for(int j=0; j<256; j++) {
for(uint16_t i=0; i<strip.numPixels(); i++) { if((i >= tail && i <= head) || (tail > head && i >= tail) || (tail > head && i <= head) ){ strip.setPixelColor(i, strip.Color(0,0,0, 255 ) ); } else{ strip.setPixelColor(i, Wheel(((i * 256 / strip.numPixels()) + j) & 255)); } } if(millis() - lastTime > whiteSpeed) {
head++;
tail++;
if(head == strip.numPixels()){
loopNum++;
}
lastTime = millis();
}

if(loopNum == loops) return;

head%=strip.numPixels();
tail%=strip.numPixels();
strip.show();
delay(wait);
}
}

}
void fullWhite() {

for(uint16_t i=0; i<strip.numPixels(); i++) {
strip.setPixelColor(i, strip.Color(0,0,0, 255 ) );
}
strip.show();
}
// Slightly different, this makes the rainbow equally distributed throughout
void rainbowCycle(uint8_t wait) {
uint16_t i, j;

for(j=0; j<256 * 5; j++) { // 5 cycles of all colors on wheel
for(i=0; i< strip.numPixels(); i++) {
strip.setPixelColor(i, Wheel(((i * 256 / strip.numPixels()) + j) & 255));
}
strip.show();
delay(wait);
}
}

void rainbow(uint8_t wait) {
uint16_t i, j;

for(j=0; j<256; j++) {
for(i=0; i<strip.numPixels(); i++) {
strip.setPixelColor(i, Wheel((i+j) & 255));
}
strip.show();
delay(wait);
}
}

// Input a value 0 to 255 to get a color value.
// The colours are a transition r - g - b - back to r.
uint32_t Wheel(byte WheelPos) {
WheelPos = 255 - WheelPos;
if(WheelPos < 85) {
return strip.Color(255 - WheelPos * 3, 0, WheelPos * 3,0);
}
if(WheelPos < 170) { WheelPos -= 85; return strip.Color(0, WheelPos * 3, 255 - WheelPos * 3,0); } WheelPos -= 170; return strip.Color(WheelPos * 3, 255 - WheelPos * 3, 0,0); } uint8_t red(uint32_t c) { return (c >> 8);
}
uint8_t green(uint32_t c) {
return (c >> 16);
}
uint8_t blue(uint32_t c) {
return (c);
}

 

led-fiber optic couplings.png

P2290654

Flasher Costume

 

Last week for Halloween, I dressed up as a flasher.

This is sadly the only video I have of it in action since Victoria and I got separated from the group early on in the parade, but here are some additional pictures of the interior and exterior

IMG_5219.jpg

The exterior shell is a coat that I had designed, patterned, and made some time ago.

IMG_5215.jpg

I cut 6 segments of LED strips compatible with the neopixel library into 4 LED sections for a total of 24 LEDs, all connected in parallel.  The LED portion of the circuit was attached to the innermost layer of lining so that no stitching would be visible from the inside of the coat.  The second layer of lining was added to create light diffusion and to also hide the circuit.

IMG_5216.jpg

Through a small opening in the seam joining the right lining and facing, I pulled the rest of the circuit with the Gemma, lithium battery, and button through.  The Gemma and battery were inserted in a pouch I sewed into the lining, and the button was attached to the right front button hole for quick access.

Building the circuit was straightforward because I was able to preview it on TinkerCAD first.  The coding, however, was the trickiest part.  I had originally planned to use code from a library of LED strip effects that I had found on the web, but it was incompatible with the ButtonCycler example that I wanted to build on.  For this reason, I opted to use the sequences in the ButtonCycler, tweaking some of the delays and cycle times.

 

 

Lantern Fish – Halloween Costume

P2290595new

Here is my Halloween Costume. I was so excited after finishing it. It is really an unforgettable experience. Not only the challenging process of making the hood but also walking at the amazing parade wearing the hood.

Materials:

  • 1 RGB Neopixel LEDs
  • 1 HC-SR04 Ultrasonic Sonar Distance Sensor
  • 1 GEMMA¬† – Wearable Microcontroller
  • 1 Lithium Ion Polymer Battery

  • Fleece
  • Felt
  • Stuffing
  • Velcro
  • Iron wire

Initial proposal:

IMG_8503

I really like this hood initially. But the sewing was a very intricate task and harder then I had expected. I was trying to find what the other people did and learned how to make this hood. It is really tough and I tried to make the hood again and again. Finally, I made it even though it is not perfect. I also use the velcro to make this hood more suitable for the head. I added the detail to the fish like eyes, teeth, fins, and etc.

IMG_8895

Besides making the whole hood, another challenge is to connect the light with hood. I have tried different ways like tied it on the breadboard. But finally I used the iron wire to make it like a headband which is much more stable.

IMG_90391.jpg

For the circuit board. At first, I didn’t realize the distance sensor cannot be hidden in the hood. It must be at outside the hood without anything in front of it. Then I tried to tie it with the neopixel, making them like a little fish.

Below are more pictures and the code:

IMG_3744IMG_6679

#include <Adafruit_NeoPixel.h>

#define PIN 1

#define NUM_LEDS 1

#define BRIGHTNESS 200

#define Trig 0 
#define Echo 2 
 
float cm; 
float temp; // 
// Parameter 1 = number of pixels in strip
// Parameter 2 = pin number (most are valid)
// Parameter 3 = pixel type flags, add together as needed:
//   NEO_RGB     Pixels are wired for RGB bitstream
//   NEO_GRB     Pixels are wired for GRB bitstream, correct if colors are swapped upon testing
//   NEO_RGBW    Pixels are wired for RGBW bitstream
//   NEO_KHZ400  400 KHz bitstream (e.g. FLORA pixels)
//   NEO_KHZ800  800 KHz bitstream (e.g. High Density LED strip), correct for neopixel stick
Adafruit_NeoPixel strip = Adafruit_NeoPixel(NUM_LEDS, PIN, NEO_RGB + NEO_KHZ800);

int inches = 0;

long readUltrasonicDistance(int pin)
{
  pinMode(pin, OUTPUT);  // Clear the trigger
  digitalWrite(pin, LOW);
  delayMicroseconds(2);
  // Sets the pin on HIGH state for 10 micro seconds
  digitalWrite(pin, HIGH);
  delayMicroseconds(10);
  digitalWrite(pin, LOW);
  pinMode(pin, INPUT);
  // Reads the pin, and returns the sound wave travel time in microseconds
  return pulseIn(pin, HIGH);
}

void setup()
{
//  Serial.begin(9600);
  pinMode(Trig, OUTPUT);
  pinMode(Echo, INPUT);
  pinMode(1, INPUT);
  strip.setBrightness(BRIGHTNESS);
  strip.begin();
  strip.show(); // Initialize all pixels to 'off'

}

void loop()
{
  digitalWrite(Trig, LOW); 
  delayMicroseconds(2); 
  digitalWrite(Trig,HIGH); 
  delayMicroseconds(10); 
  digitalWrite(Trig, LOW); 
  
  temp = float(pulseIn(Echo, HIGH)); 
  cm = (temp * 17 )/1000; 


if (cm < 30){
    colorWipe(strip.Color(0, 255, 0), 50); // Red
  } else if (cm >=30 && cm < 500){
  colorWipe(strip.Color(100, 100, 100), 50); 
  }
}

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);
  }
}

Infinity Mirror: “the Dad Joke of Halloween Costumes”

 

Whoa! It’s like you have a hole in your chest!! Nice!!!

‚ÄĒRandom Parade-Go’er

 

 

P2290611

 

Materials:

  • Shortbread cookie tin with cookies
  • 2x acrylic one sided glass same diameter as cookie tin
  • Electroluminescent tape
  • 4xAAA battery inverter
  • Suspenders
  • Black hoodie
  • Rivets

Process:

  1. Eat the shortbread cookies
  2. Laser cut the one sided glass into circles
  3. Stick EL tape to inside of the walls of the tin
  4. Rivet the tin to the suspenders
  5. Glue the mirrors into place
  6. Cut hole slightly smaller than the tin into the chest of the sweatshirt
  7. Punch holes every 1/2″ into the lid of the tin
  8. Sew lid to sweatshirt.
  9. Don the infinity mirror and blow everyone’s mind and induce barely-audible chuckles

In the future:

  • Use more robust housing than the tin such as ply wood.
  • Make a second one on the back

 

Much fun during the parade!

IMG_5952

Firebroom

First, I want to thank Becky for taking us to the Halloween parade! Since the country I came from does not really celebrate Halloween(we do give out candies to children but that’s all), it was interesting to experience new culture. I especially loved watching other people’s costumes.

I made the ‘Firebroom’ for this project. This is for the witch who gets really excited when surrounded by people or hear loud noises. The broomstick changes its color of bristles from white to red according to the noise level.

broomstick from Shin Young Park on Vimeo.

20181106_202238 (1).jpg

For the circuit, I used micro-amlpifier, Arduino Uno, RGBW Neopixels and 3xAAA battery pack. At first I was using Arduino Gemma but I noticed that my computer cannot recognize the Gemma. So I switched to Arduino Uno and that was my saddest moment in this project.

I made the broomstick before making the circuit, but I had to re-make the broomstick in order to fit in my Uno. Hopefully it worked out well.

I used a fabric that is not so dense in other to let the lights out. I wrapped the Arduino board with the fabric and attached it to the stick. After that I tied bristles to the stick and wrapped the fabric again.

20181031_005738.jpg

Below is the code for this project. I kept making adjustment to the code to figure out how sensitive the sound sensor has to be. Serial monitor was very helpful in the process. Starting from n, I made adjustments and finally decided to use 5n.

#include 
int SAMPLE_WINDOW = 33; // Sample window width in mS (33 mS = ~30 Hz)
int LED_PIN =      6; // DIGITAL pin # where LEDs are connected
int  MIC_PIN =      1; // ANALOG pin # where microphone "OUT" is connected
int  NUM_LEDS =     8;
#define BRIGHTNESS 50
Adafruit_NeoPixel strip = Adafruit_NeoPixel(8, 6, NEO_GRBW + NEO_KHZ800);


void setup() {

  Serial.begin(9600);
  

  pinMode(MIC_PIN, INPUT);
  pinMode(LED_PIN, OUTPUT);

  strip.setBrightness(BRIGHTNESS);
  strip.begin();
  strip.show(); // Initialize all pixels to 'off'
}

void loop() {
  // Listen to mic for short interval, recording min & max signal
  unsigned int signalMin = 1023, signalMax = 0;
  unsigned long startTime = millis();
  while ((millis() - startTime) < SAMPLE_WINDOW) {
    int sample = analogRead(MIC_PIN);
    if (sample  signalMax) signalMax = sample;
  }
  
  int peakToPeak = signalMax - signalMin; // Max - min = peak-peak amplitude
  int n = (peakToPeak - 10) / 4;          // Remove low-level noise, lower gain
  if (n > 51)    n = 51;                // Limit to valid PWM range
  else if (n < 0) n = 0;
  
  Serial.println(n);

  ColorWipe(strip.Color(255, 255 -5*n, 255 -5*n), n);        // And send to LEDs as PWM level
}
// Fill the dots one after the other with a color
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);
  }
}


It was exciting to learn more about coding and making circuit. After finishing this project, I felt much more confident about coding and circuits!