Powerpuff Girls with LED Light-Up Oversized Eye glasses👓✨
Hi! We’re the Powerpuff Girls! Batu❤️(Blossom), Jisu💚(Buttercup), Yennie💙(Bubbles)
Batu❤️, Jisu💚, and Yennie💙
Descriptions:
Throughout the process, we faced several challenges, especially when soldering the two LED rings without causing errors. We all participated in soldering, helping each other and working together to solve the issues. We also encountered coding errors during the setup. In the final assembly, we faced a problem where the red light appeared green—possibly due to a soldering issue. We adjusted parts of the code to fix this color error.
Making Process
Yennie_Mainly focused on creating the glasses and coding.
Yennie : I’m really glad to have worked with Jisu and Batu, who are both spontaneous and very supportive. We never felt disappointed when our soldering failed, the lights didn’t turn on, or coding errors occurred — instead, we just laughed it off and kept trying to figure things out together.
Jisu : I was so happy to be one of the Powerpuff Girls with Yennie and Batu. We cheered each other up even when our soldering or coding didn’t work, and those moments turned into such fun and meaningful memories. It wasn’t just about finishing the project, we genuinely enjoyed the process, laughed a lot during our late-night problem-solving, and supported each other every step of the way.
Batu : I was really excited to collaborate with two creatives whose work I admire. It was so much fun working with Yennie and Jisu — printing shirts with Jisu and soldering and coding with Yennie were definitely the highlights. If we were to make a second version of this project, we’d probably focus more on improving the cabling and soldering, since the red glasses sometimes worked and sometimes glitched. We shared so many laughs in the studio — such a great experience overall.
Making my Edward Scissorhands costume was really fun! I feel like I was finally able to bring all my goth dreams to life. I’ve always been interested in incorporating technology into clothing and this was my first project doing so and I’m pretty proud of how it turned out.
Starting out, I ordered my gloves and Becky recommend 3d printing the Scissorhands (I was considering chipboard or foil initially). I slowly realized though that pushing myself beyond that which I already knew and collaborating with my peers was way better than sticking to what I already knew. I started out by printing one scissorhand out to test it then printed the rest. Jimmy helped me with 3d printing and ofcourse the VFL staff!
I then moved on to soldering. Based on my tinkercad, I knew soldering was a big part of my project and it did end up taking a lot of time. I had to measure out how long the wires had to be for each scissorhands and use black wiring only to add to the goth look which made the whole thing confusing at times. Using the gemma was also very new to me and thanks to Kyle and Becky, I was able to understand it better. I started out with trying out one neopixel on the arduino uno and breadboard (known territory) to test it out – and it went well and then moved on to the gemma ( unknown territory).
The back is maybe not the prettiest 🤣maybe in the future I will try to 3d print in a way to insert the wires through the Scissorhands. I did use some black canvas cloth though to cover up all the wiring.
The final step on my journey was the code. I have to admit this was the hardest step even though I initially assumed it would take the least amount of time. Becky initially taught me how to use the serial monitor to test the bend for the flex sensor. I then worked with Kyle to convert this into code. We were able to get the sensor to work but it only went from white to multicolor not white to red like I hoped. I looked up why this might have been happening and chat gpt told me perhaps the gemma couldn’t handle 40 leds and I doubted this was true.
Thanks to Becky though, on the day of Halloween, she told me I just had to change my code from RGB to RGBW and although it worked for like a second, it ending up leading to a short circuit and I wasn’t able to take any pictures ☹️. Super bummed about that because I worked really hard on this but this program has taught me to expect the unexpected. I came back in on Monday and realized the sodder was touching two pins on a neopixel so once I fixed that and rebooted the gemma, IT WORKED 🥳. It felt amazing to see my hard work come into fruition.
DESCRIPTION: I started out aiming to recreate the Flux Capacitor from Back to the Future, as part of my Marty McFly costume. I wanted to recreate a prop as I’m interested in prop design, and design for entertainment. However, I wanted to put my own spin on it, and decided that I would make a Luxe Capacitor, and I would wear it be wearable.
I came away with quite a few learnings from this process. Overall, I struggled to figure out the order in which to complete steps. For example, I spray painted individual components and then realized that it prevented adhesion when I started to glue everything together. Upon completion, I think I have a better (not perfect) sense in how I would order my to do list if repeating this process. I created my own dielines for the box (which I then laser cut), and I made the mistake of not leaving extra room for the insert to fit into the box. Lastly, I didn’t test my circuit while soldering. It worked out, but if I encountered errors then I wouldn’t have had any idea which connection was causing the issue.
// Simple demonstration on using an input device to trigger changes on your
// NeoPixels. Wire a momentary push button to connect from ground to a
// digital IO pin. When the button is pressed it will change to a new pixel
// animation. Initial state has all pixels off -- press the button once to
// start the first animation. As written, the button does not interrupt an
// animation in-progress, it works only when idle.
#include <Adafruit_NeoPixel.h>
#ifdef __AVR__
#include <avr/power.h> // Required for 16 MHz Adafruit Trinket
#endif
// Digital IO pin connected to the button. This will be driven with a
// pull-up resistor so the switch pulls the pin to ground momentarily.
// On a high -> low transition the button press logic will execute.
#define BUTTON_PIN 0 // Gemma M0 D0 for button input
#define PIXEL_PIN 1 // Digital IO pin connected to the NeoPixels (Gemma M0 default)
#define PIXEL_COUNT 8 // Number of NeoPixels
// Declare our NeoPixel strip object:
Adafruit_NeoPixel strip(PIXEL_COUNT, PIXEL_PIN, NEO_GRBW + NEO_KHZ800);
// Argument 1 = Number of pixels in NeoPixel strip
// Argument 2 = Arduino pin number (most are valid)
// Argument 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)
// NEO_RGBW Pixels are wired for RGBW bitstream (NeoPixel RGBW products)
boolean oldState = HIGH;
int mode = 0; // Currently-active animation mode, 0-9
voidsetup() {
pinMode(BUTTON_PIN, INPUT_PULLUP);
strip.begin(); // Initialize NeoPixel strip object (REQUIRED)
strip.show(); // Initialize all pixels to 'off'
}
voidloop() {
// Get current button state.
boolean newState = digitalRead(BUTTON_PIN);
// Check if state changed from high to low (button press).
if ((newState == LOW) && (oldState == HIGH)) {
// Short delay to debounce button.
delay(20);
// Check if button is still low after debounce.
newState = digitalRead(BUTTON_PIN);
if (newState == LOW) { // Yes, still low
if (++mode > 3) mode = 0; // Advance to next mode, wrap around after #3
switch (mode) { // Start the new animation...
case0:
fluxChase(0, 0, 0, 0, 0); // off
break;
case1:
fluxChase(255, 180, 0, 20, 100); // light chase, 100ms delay per frame
break;
case2:
fadeEffect(255, 180, 0, 20, 5); // slow fade
break;
case3:
fadeEffect(255, 180, 0, 20, 2); // fast fade
break;
}
}
}
// Set the last-read button state to the old state.
oldState = newState;
}
// Animated chasing glow
voidfluxChase(uint8_t r, uint8_t g, uint8_t b, uint8_t w, int delayTime) {
for (int loop = 0; loop < 6; loop++) { // looping - renamed from 'i' to avoid shadowing
for (int step = 0; step < PIXEL_COUNT * 1; step++) {
strip.clear();
for (int i = 0; i < PIXEL_COUNT; i++) {
int offset = (step + i) % PIXEL_COUNT;
float fade = 1.0 - (float)i / PIXEL_COUNT; // trailing dimmer effect
strip.setPixelColor(offset, strip.Color(r * fade, g * fade, b * fade, w * fade));
}
strip.show();
delay(delayTime);
}
}
}
// Smooth fade in/out
voidfadeEffect(uint8_t r, uint8_t g, uint8_t b, uint8_t w, int speed) {
for (int loop = 0; loop < 4; loop++) { // looping - renamed from 'i' for clarity
// Fade in
for (int brightness = 0; brightness <= 255; brightness++) {
setAllBrightness(r, g, b, w, brightness);
delay(speed);
}
// Fade out
for (int brightness = 255; brightness >= 0; brightness--) {
setAllBrightness(r, g, b, w, brightness);
delay(speed);
}
}
}
// Helper for setting all pixels to same brightness
voidsetAllBrightness(uint8_t r, uint8_t g, uint8_t b, uint8_t w, uint8_t brightness) {
for (int i = 0; i < PIXEL_COUNT; i++) {
strip.setPixelColor(i, strip.Color(
(r * brightness) / 255,
(g * brightness) / 255,
(b * brightness) / 255,
(w * brightness) / 255
));
}
strip.show();
}
Five Nights At Freddy’s Bonnie The Animatronic Bunny
WHY:
I wanted to do something niche, but recognizable to only the fan base. Five Nights fans are CRAZYY and I was immediately recognized many times throughout the night! I also love horror and this concept always stood out to me, as a kid.
WHAT (I USED): Foam, Acrylic Paint, Adhesive Spray, Solder, Gemma, Adafruit Jewels, Battery Pack, Medium Gauge Wire
WHAT (I DID):
The first thing I worked on was the ear headpiece. I cut foam with the band saw into 4 pieces and spent hours sanding them down to the correct shapes. Then, I sprayed them with adhesive spray before painting them.
I separately soldered wire to a metal headband (& later added supports + a second metal headband)
Finally I tackled the part I was most nervous about. I started on tinkered, with a tutorial of a blinking light sequence on the jewels that I was working with.
I played around with the code and used a bit of help from chat gbt to apply a fade between the yellow and red color switch.
Next, I soldered the Gemma to the 2 jewels, measuring them up against the glasses that they would be attached to.
HOW (I FEEL):
I am happy with the accuracy of this costume! And its wearability throughout the night.
Running out of time, during my laptop disaster, I thought I would not be able to pull it all together in the end. But after a last minute re-solder and borrowing Lauren’s laptop on October 31st at 4:45pm, I loaded the light animation onto my Gemma and was ready for the fashion show and parade!
HOW (I CAN DO BETTER):
I should have decreased the brightness significantly. Maybe also take into account my own eye protection. I want to be more fluent in coding language so I can pinpoint issues and troubleshoot with more confidence.
Photos of your completed project (video optional):
This Halloween, I built a “Stray Robot” costume as a special tribute to our family. With my husband and I expecting our “second” son at the end of this year, we wanted to make this Halloween all about our “first son,” our orange tabby cat, Apu, putting him in the main spotlight. The costume is inspired by the video game Stray, which was a perfect theme since the main character is an orange tabby cat in a world populated only by robots. Our costume symbolized our deep love for Apu—we would even turn into robots to make him the star. The construction was a learning process; the head was built with an internal support and a waist belt for stability, and I taught myself how to program Arduino for the LED lights. Although it was a success, if I were to make it again, I would definitely design the head to be a bit smaller.
List (with links) of materials and parts used:
BTF-LIGHTING WS2812B RGB 5050SMD Individually Addressable Digital 16×16 256 Pixels 6.3in x 6.3in LED Matrix Flexible FPCB Dream Full Color Works with SP802E Controller Image Video Text Display DC5V
BTF-LIGHTING WS2812B IC RGB 5050SMD Pure Gold Individual Addressable LED Strip 16.4FT 300LED 60Pixel/m Flexible Full Color IP30 DC5V for DIY Chasing Color Project(No Adapter or Controller)
Cardboard
Acrylic board
Spray paints
Glass paints
Hot glue
Circuit diagram
Arduino code
// Simple demonstration on using an input device to trigger changes on your
// NeoPixels. Wire a momentary push button to connect from ground to a
// digital IO pin. When the button is pressed it will change to a new pixel
// animation. Initial state has all pixels off -- press the button once to
// start the first animation. As written, the button does not interrupt an
// animation in-progress, it works only when idle.
#include <Adafruit_NeoPixel.h>
#ifdef __AVR__
#include <avr/power.h> // Required for 16 MHz Adafruit Trinket
#endif
// Digital IO pin connected to the button. This will be driven with a
// pull-up resistor so the switch pulls the pin to ground momentarily.
// On a high -> low transition the button press logic will execute.
#define BUTTON_PIN 2
#define PIXEL_PIN 1 // Digital IO pin connected to the NeoPixels.
//#define PIXEL_COUNT 256 // Number of NeoPixels
#define MATRIX_WIDTH 14
#define MATRIX_HEIGHT 16
#define PIXEL_COUNT (MATRIX_WIDTH * MATRIX_HEIGHT)
//#define BRIGHTNESS 10
// Define the brightness values requested
const uint8_t BACKGROUND_BRIGHTNESS = 100; // For the RGB rainbow part
const uint8_t FACE_BRIGHTNESS = 150; // For the RGB components of the white face
// // Get current button state.
// const uint8_t BACKGROUND_BRIGHTNESS = 20; // For the RGB rainbow part
// const uint8_t FACE_BRIGHTNESS = 35; // For the RGB components of the white face
const byte On_HOLDMap[MATRIX_HEIGHT][MATRIX_WIDTH] = {
{0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,1,1,0,0,0,0,0,0,0},
{0,0,0,0,1,1,1,1,0,0,0,0,0,0},
{0,0,0,0,1,1,1,1,0,0,0,0,0,0}, // Eye
{0,0,0,0,1,1,1,1,0,0,1,0,0,0}, // Eye
{0,0,0,0,0,1,1,0,0,0,1,0,0,0}, // Eye
{0,0,0,0,0,0,0,0,0,0,1,0,0,0},
{0,0,0,0,0,0,0,0,0,0,1,0,0,0},
{0,0,0,0,0,0,0,0,0,0,1,0,0,0},
{0,0,0,0,0,0,0,0,0,0,1,0,0,0},
{0,0,0,0,0,1,1,0,0,0,1,0,0,0}, // Mouth
{0,0,0,0,1,1,1,1,0,0,1,0,0,0}, // Mouth
{0,0,0,0,1,1,1,1,0,0,0,0,0,0},
{0,0,0,0,1,1,1,1,0,0,0,0,0,0},
{0,0,0,0,0,1,1,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0}
};
const byte Wink_Map[MATRIX_HEIGHT][MATRIX_WIDTH] = {
{0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,1,1,0,0,0,0,0,0,0},
{0,0,0,0,0,1,1,0,0,0,0,0,0,0},
{0,0,0,0,0,1,1,0,0,0,0,0,0,0}, // Eye
{0,0,0,0,0,1,1,0,0,0,1,0,0,0}, // Eye
{0,0,0,0,0,1,1,0,0,0,1,0,0,0}, // Eye
{0,0,0,0,0,0,0,0,0,0,1,0,0,0},
{0,0,0,0,0,0,0,0,0,0,1,0,0,0},
{0,0,0,0,0,0,0,0,0,0,1,0,0,0},
{0,0,0,0,0,0,0,0,0,0,1,0,0,0},
{0,0,0,0,0,1,1,0,0,0,1,0,0,0}, // Mouth
{0,0,0,0,1,1,1,1,0,0,1,0,0,0}, // Mouth
{0,0,0,0,1,1,1,1,0,0,0,0,0,0},
{0,0,0,0,1,1,1,1,0,0,0,0,0,0},
{0,0,0,0,0,1,1,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0}
};
const byte no_words_Map[MATRIX_HEIGHT][MATRIX_WIDTH] = {
{0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,1,1,0,0,0,0,0,0,0},
{0,0,0,0,0,1,1,0,0,0,0,0,0,0},
{0,0,0,0,0,1,1,0,0,0,0,0,0,0}, // Eye
{0,0,0,0,0,1,1,0,0,0,1,0,0,0}, // Eye
{0,0,0,0,0,1,1,0,0,0,1,0,0,0}, // Eye
{0,0,0,0,0,0,0,0,0,0,1,0,0,0},
{0,0,0,0,0,0,0,0,0,0,1,0,0,0},
{0,0,0,0,0,0,0,0,0,0,1,0,0,0},
{0,0,0,0,0,0,0,0,0,0,1,0,0,0},
{0,0,0,0,0,1,1,0,0,0,1,0,0,0}, // Mouth
{0,0,0,0,0,1,1,0,0,0,1,0,0,0}, // Mouth
{0,0,0,0,0,1,1,0,0,0,0,0,0,0},
{0,0,0,0,0,1,1,0,0,0,0,0,0,0},
{0,0,0,0,0,1,1,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0}
};
const byte heartMap[MATRIX_HEIGHT][MATRIX_WIDTH] = {
{0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0},
{0,0,0,0,1,1,0,0,0,0,0,0,0,0},
{0,0,0,1,1,1,1,0,0,0,0,0,0,0}, // Bigger Heart Top
{0,0,1,1,1,1,1,1,0,0,0,0,0,0},
{0,0,1,1,1,1,1,1,1,0,0,0,0,0},
{0,0,1,1,1,1,1,1,1,1,0,0,0,0},
{0,0,0,1,1,1,1,1,1,1,1,0,0,0},
{0,0,0,0,1,1,1,1,1,1,1,1,0,0},
{0,0,0,1,1,1,1,1,1,1,1,0,0,0},
{0,0,1,1,1,1,1,1,1,1,0,0,0,0},
{0,0,1,1,1,1,1,1,1,0,0,0,0,0},
{0,0,1,1,1,1,1,1,0,0,0,0,0,0}, // Bigger Heart Tip
{0,0,0,1,1,1,1,0,0,0,0,0,0,0},
{0,0,0,0,1,1,0,0,0,0,0,0,0,0},
{0,0,0,0,0,0,0,0,0,0,0,0,0,0}
};
// Declare our NeoPixel strip object:
Adafruit_NeoPixel strip(PIXEL_COUNT, PIXEL_PIN, NEO_GRB + NEO_KHZ800);
// Argument 1 = Number of pixels in NeoPixel strip
// Argument 2 = Arduino pin number (most are valid)
// Argument 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)
// NEO_RGBW Pixels are wired for RGBW bitstream (NeoPixel RGBW products)
boolean oldState = HIGH;
int mode = 0; // Currently-active animation mode, 0-9
int brightness = 25;
void setup() {
strip.setBrightness(brightness);
pinMode(BUTTON_PIN, INPUT_PULLUP);
strip.begin(); // Initialize NeoPixel strip object (REQUIRED)
strip.show(); // Initialize all pixels to 'off'
}
void loop() {
boolean newState = digitalRead(BUTTON_PIN);
// Check if state changed from high to low (button press).
if((newState == LOW) && (oldState == HIGH)) {
// Short delay to debounce button.
delay(20);
// Check if button is still low after debounce.
newState = digitalRead(BUTTON_PIN);
if(newState == LOW) { // Yes, still low
if(++mode > 9) mode = 0; // Advance to next mode, wrap around after #8
switch(mode) { // Start the new animation...
case 0:
colorWipe(strip.Color( 0, 0, 0), 50); // Black/off
break;
case 1:
drawPattern_on_hold_face();
break;
case 2:
drawPattern_wink_face();
//
break;
case 3:
//colorWipe(strip.Color( 0, 0, 255), 50); // Blue
drawPattern_on_hold_face();
break;
case 4:
//theaterChase(strip.Color(127, 127, 127), 50); // White
//drawCirclePattern();
drawPattern_rainbow_heart_face();
break;
case 5:
drawPattern_on_hold_face();
//theaterChase(strip.Color(127, 0, 0), 50); // Red
break;
case 6:
drawPattern_no_words_face();
//theaterChase(strip.Color( 0, 0, 127), 50); // Blue
break;
case 7:
//rainbow(10);
//drawCirclePattern();
drawPattern_heart_face();
break;
case 8:
theaterChaseRainbow(50);
break;
}
}
}
// Set the last-read button state to the old state.
oldState = newState;
}
void drawPattern_on_hold_face() {
// Iterate over every pixel in the matrix.
for (int y = 0; y < MATRIX_HEIGHT; y++) {
for (int x = 0; x < MATRIX_WIDTH; x++) {
// Get the 1D index for the pixel at (x,y) coordinates.
int pixelIndex = getPixelIndex(x, y);
// Check the bitmap to see if this pixel is part of the smiley.
if (On_HOLDMap[y][x] == 1) {
// This pixel is part of the face.
uint8_t current_brightness = FACE_BRIGHTNESS;
// Add vertical stripe effect by brightening odd-numbered columns.
if (x % 2 != 0) {
// Add brightness for the stripe, ensuring it doesn't exceed 255.
current_brightness = min(255, current_brightness + 15);
}
// Set an RGB white color by setting R, G, and B to the same value.
strip.setPixelColor(pixelIndex, strip.Color(current_brightness, current_brightness, current_brightness));
} else {
// This pixel is part of the background.
// To reverse the rainbow direction (green->yellow->red...), we start
// at the green hue (21845) and SUBTRACT a value that increases
// across the diagonal. This makes the hue decrease.
uint16_t hue = 21845 - (((uint32_t)((x - y) + (MATRIX_HEIGHT - 1)) * 65535) / (MATRIX_WIDTH + MATRIX_HEIGHT - 2));
uint8_t current_brightness = BACKGROUND_BRIGHTNESS;
// Add vertical stripe effect by brightening odd-numbered columns.
if (x % 2 != 0) {
current_brightness += 8; // Make stripes on background brighter
}
// Get the 32-bit color value from HSV (Hue, Saturation, Value/Brightness).
uint32_t color_background = strip.ColorHSV(hue, 255, current_brightness);
strip.setPixelColor(pixelIndex, color_background);
}
}
}
// After setting all the pixel colors, push the data to the strip.
strip.show();
}
void drawPattern_no_words_face() {
// Iterate over every pixel in the matrix.
for (int y = 0; y < MATRIX_HEIGHT; y++) {
for (int x = 0; x < MATRIX_WIDTH; x++) {
// Get the 1D index for the pixel at (x,y) coordinates.
int pixelIndex = getPixelIndex(x, y);
// Check the bitmap to see if this pixel is part of the smiley.
if (no_words_Map[y][x] == 1) {
// This pixel is part of the face.
uint8_t current_brightness = FACE_BRIGHTNESS;
// Add vertical stripe effect by brightening odd-numbered columns.
if (x % 2 != 0) {
// Add brightness for the stripe, ensuring it doesn't exceed 255.
current_brightness = min(255, current_brightness + 15);
}
// Set an RGB white color by setting R, G, and B to the same value.
strip.setPixelColor(pixelIndex, strip.Color(current_brightness, current_brightness, current_brightness));
} else {
// This pixel is part of the background.
// To reverse the rainbow direction (green->yellow->red...), we start
// at the green hue (21845) and SUBTRACT a value that increases
// across the diagonal. This makes the hue decrease.
uint16_t hue = 21845 - (((uint32_t)((x - y) + (MATRIX_HEIGHT - 1)) * 65535) / (MATRIX_WIDTH + MATRIX_HEIGHT - 2));
uint8_t current_brightness = BACKGROUND_BRIGHTNESS;
// Add vertical stripe effect by brightening odd-numbered columns.
if (x % 2 != 0) {
current_brightness += 8; // Make stripes on background brighter
}
// Get the 32-bit color value from HSV (Hue, Saturation, Value/Brightness).
uint32_t color_background = strip.ColorHSV(hue, 255, current_brightness);
strip.setPixelColor(pixelIndex, color_background);
}
}
}
// After setting all the pixel colors, push the data to the strip.
strip.show();
}
void drawPattern_wink_face() {
// Iterate over every pixel in the matrix.
for (int y = 0; y < MATRIX_HEIGHT; y++) {
for (int x = 0; x < MATRIX_WIDTH; x++) {
// Get the 1D index for the pixel at (x,y) coordinates.
int pixelIndex = getPixelIndex(x, y);
// Check the bitmap to see if this pixel is part of the smiley.
if (Wink_Map[y][x] == 1) {
// This pixel is part of the face.
uint8_t current_brightness = FACE_BRIGHTNESS;
// Add vertical stripe effect by brightening odd-numbered columns.
if (x % 2 != 0) {
// Add brightness for the stripe, ensuring it doesn't exceed 255.
current_brightness = min(255, current_brightness + 15);
}
// Set an RGB white color by setting R, G, and B to the same value.
strip.setPixelColor(pixelIndex, strip.Color(current_brightness, current_brightness, current_brightness));
} else {
// This pixel is part of the background.
// To reverse the rainbow direction (green->yellow->red...), we start
// at the green hue (21845) and SUBTRACT a value that increases
// across the diagonal. This makes the hue decrease.
uint16_t hue = 21845 - (((uint32_t)((x - y) + (MATRIX_HEIGHT - 1)) * 65535) / (MATRIX_WIDTH + MATRIX_HEIGHT - 2));
uint8_t current_brightness = BACKGROUND_BRIGHTNESS;
// Add vertical stripe effect by brightening odd-numbered columns.
if (x % 2 != 0) {
current_brightness += 8; // Make stripes on background brighter
}
// Get the 32-bit color value from HSV (Hue, Saturation, Value/Brightness).
uint32_t color_background = strip.ColorHSV(hue, 255, current_brightness);
strip.setPixelColor(pixelIndex, color_background);
}
}
}
// After setting all the pixel colors, push the data to the strip.
strip.show();
}
void drawPattern_heart_face() {
// Iterate over every pixel in the matrix.
for (int y = 0; y < MATRIX_HEIGHT; y++) {
for (int x = 0; x < MATRIX_WIDTH; x++) {
// Get the 1D index for the pixel at (x,y) coordinates.
int pixelIndex = getPixelIndex(x, y);
// Check the bitmap to see if this pixel is part of the heart.
if (heartMap[y][x] == 1) {
// This pixel is part of the heart.
uint8_t current_brightness = FACE_BRIGHTNESS;
// Add vertical stripe effect by brightening odd-numbered columns.
if (x % 2 != 0) {
// Add brightness for the stripe, ensuring it doesn't exceed 255.
current_brightness = min(255, current_brightness + 15);
}
// Set an RGB red color.
strip.setPixelColor(pixelIndex, strip.Color(current_brightness, 0, 0));
} else {
// This pixel is part of the background.
// Set a static sky blue color.
uint16_t sky_blue_hue = 36000; // A nice cyan/sky blue hue.
uint8_t current_brightness = BACKGROUND_BRIGHTNESS;
// Add vertical stripe effect by brightening odd-numbered columns.
if(x == 0 && y == 0){
Serial.print("before: ");
Serial.println(current_brightness);
}
// if (x % 2 == 0) {
// current_brightness += 8; // Make stripes on background brighter
// }
if(x == 0 && y == 0){
Serial.print("after: ");
Serial.println(current_brightness);
}
// Get the 32-bit color value from HSV (Hue, Saturation, Value/Brightness).
uint32_t color_background = strip.ColorHSV(sky_blue_hue, 255, 255);
strip.setPixelColor(pixelIndex, color_background);
}
}
}
// After setting all the pixel colors, push the data to the strip.
strip.show();
}
void drawPattern_rainbow_heart_face() {
// Iterate over every pixel in the matrix.
for (int y = 0; y < MATRIX_HEIGHT; y++) {
for (int x = 0; x < MATRIX_WIDTH; x++) {
// Get the 1D index for the pixel at (x,y) coordinates.
int pixelIndex = getPixelIndex(x, y);
// Check the bitmap to see if this pixel is part of the smiley.
if (heartMap[y][x] == 1) {
// This pixel is part of the face.
uint8_t current_brightness = FACE_BRIGHTNESS;
// Add vertical stripe effect by brightening odd-numbered columns.
if (x % 2 != 0) {
// Add brightness for the stripe, ensuring it doesn't exceed 255.
current_brightness = min(255, current_brightness + 15);
}
// Set an RGB white color by setting R, G, and B to the same value.
strip.setPixelColor(pixelIndex, strip.Color(current_brightness, current_brightness, current_brightness));
} else {
// This pixel is part of the background.
// To reverse the rainbow direction (green->yellow->red...), we start
// at the green hue (21845) and SUBTRACT a value that increases
// across the diagonal. This makes the hue decrease.
uint16_t hue = 21845 - (((uint32_t)((x - y) + (MATRIX_HEIGHT - 1)) * 65535) / (MATRIX_WIDTH + MATRIX_HEIGHT - 2));
uint8_t current_brightness = BACKGROUND_BRIGHTNESS;
// Add vertical stripe effect by brightening odd-numbered columns.
if (x % 2 != 0) {
current_brightness += 8; // Make stripes on background brighter
}
// Get the 32-bit color value from HSV (Hue, Saturation, Value/Brightness).
uint32_t color_background = strip.ColorHSV(hue, 255, current_brightness);
strip.setPixelColor(pixelIndex, color_background);
}
}
}
// After setting all the pixel colors, push the data to the strip.
strip.show();
}
void drawCirclePattern() {
// Define the colors we will use.
uint32_t color_circle = strip.Color(255, 255, 255); // White
uint32_t color_background = strip.Color(255, 0, 0); // Green
// Define the center of the matrix (using float for accuracy).
float centerX = (MATRIX_WIDTH - 1) / 2.0f;
float centerY = (MATRIX_HEIGHT - 1) / 2.0f;
// Define the radius of the circle.
float radius = 1.0f;
// This value controls the thickness of the circle's line.
float thickness = 1.0f;
// Iterate over every pixel in the matrix.
for (int y = 0; y < MATRIX_HEIGHT; y++) {
for (int x = 0; x < MATRIX_WIDTH; x++) {
// Calculate the distance of the current pixel (x, y) from the center.
float distance = sqrt(pow(y - centerY, 2) + pow(x - centerX, 2));
// Get the 1D index for the pixel at (x,y) coordinates.
int pixelIndex = getPixelIndex(x, y);
// Check if the distance is within the circle's line.
if (fabs(distance - radius) < thickness) {
// This pixel is part of the circle, set it to white.
strip.setPixelColor(pixelIndex, color_circle);
} else {
// This pixel is part of the background, set it to green.
strip.setPixelColor(pixelIndex, color_background);
}
}
}
// After setting all the pixel colors in memory, push the data to the strip.
strip.show();
}
int getPixelIndex(int x, int y) {
if (y % 2 == 0) {
// Even row: 0, 2, 4,...
return y * MATRIX_WIDTH + x;
} else {
// Odd row: 1, 3, 5,...
return y * MATRIX_WIDTH + (MATRIX_WIDTH - 1 - x);
}
}
// Fill strip pixels one after another with a color. Strip is NOT cleared
// first; anything there will be covered pixel by pixel. Pass in color
// (as a single 'packed' 32-bit value, which you can get by calling
// strip.Color(red, green, blue) as shown in the loop() function above),
// and a delay time (in milliseconds) between pixels.
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
}
}
// Theater-marquee-style chasing lights. Pass in a color (32-bit value,
// a la strip.Color(r,g,b) as mentioned above), and a delay time (in ms)
// between frames.
void theaterChase(uint32_t color, int wait) {
for(int a=0; a<10; a++) { // Repeat 10 times...
for(int b=0; b<3; b++) { // 'b' counts from 0 to 2...
strip.clear(); // Set all pixels in RAM to 0 (off)
// 'c' counts up from 'b' to end of strip in steps of 3...
for(int c=b; c<strip.numPixels(); c += 3) {
strip.setPixelColor(c, color); // Set pixel 'c' to value 'color'
}
strip.show(); // Update strip with new contents
delay(wait); // Pause for a moment
}
}
}
// Rainbow cycle along whole strip. Pass delay time (in ms) between frames.
void rainbow(int wait) {
// Hue of first pixel runs 3 complete loops through the color wheel.
// Color wheel has a range of 65536 but it's OK if we roll over, so
// just count from 0 to 3*65536. Adding 256 to firstPixelHue each time
// means we'll make 3*65536/256 = 768 passes through this outer loop:
for(long firstPixelHue = 0; firstPixelHue < 3*65536; firstPixelHue += 256) {
for(int i=0; i<strip.numPixels(); i++) { // For each pixel in strip...
// Offset pixel hue by an amount to make one full revolution of the
// color wheel (range of 65536) along the length of the strip
// (strip.numPixels() steps):
int pixelHue = firstPixelHue + (i * 65536L / strip.numPixels());
// strip.ColorHSV() can take 1 or 3 arguments: a hue (0 to 65535) or
// optionally add saturation and value (brightness) (each 0 to 255).
// Here we're using just the single-argument hue variant. The result
// is passed through strip.gamma32() to provide 'truer' colors
// before assigning to each pixel:
strip.setPixelColor(i, strip.gamma32(strip.ColorHSV(pixelHue)));
}
strip.show(); // Update strip with new contents
delay(wait); // Pause for a moment
}
}
// Rainbow-enhanced theater marquee. Pass delay time (in ms) between frames.
void theaterChaseRainbow(int wait) {
int firstPixelHue = 0; // First pixel starts at red (hue 0)
for(int a=0; a<30; a++) { // Repeat 30 times...
for(int b=0; b<3; b++) { // 'b' counts from 0 to 2...
strip.clear(); // Set all pixels in RAM to 0 (off)
// 'c' counts up from 'b' to end of strip in increments of 3...
for(int c=b; c<strip.numPixels(); c += 3) {
// hue of pixel 'c' is offset by an amount to make one full
// revolution of the color wheel (range 65536) along the length
// of the strip (strip.numPixels() steps):
int hue = firstPixelHue + c * 65536L / strip.numPixels();
uint32_t color = strip.gamma32(strip.ColorHSV(hue)); // hue -> RGB
strip.setPixelColor(c, color); // Set pixel 'c' to value 'color'
}
strip.setBrightness(10);
strip.show(); // Update strip with new contents
delay(wait); // Pause for a moment
firstPixelHue += 65536 / 90; // One cycle of color wheel over 90 frames
}
}
}
My costume, “Ghost Doll Cat,” represents both comfort and invisibility — it’s a little spooky but also silly and cute. I wanted to be like a real plush cat doll: quietly sitting in the corner, sometimes calm, sometimes playful, always just being myself.
I designed this costume as a kind of soft shield — something that hides me, yet lets me join everyone at the same time. The glowing fishbone pillow adds a bit of humor and life to the ghostly form. I chose a cat because cats always do whatever they want — even as ghosts, they remain mysterious and independent.
How to wear
To wear the costume, locate it through the red eyes first and adjust the ear positions. Each time it fits slightly differently, and the feeling varies depending on the person’s body shape under the cover, which I find very interesting.
What I learn
I learned how to use an electric embroidery machine — it was so much fun (though a bit expensive), and it made me more thoughtful about my design patterns. I also learned how to set up the Gemma board and connected the NeoPixel light strips.
What I would do differently
If I could remake it, I’d probably make the eye area smaller and use a more transparent fabric. Although I can still see people through the cloth, it’s not very convenient to move around. Next time, I’d also add an elastic band around the neck to create a Sunnyday Doll “teru teru bozu” style doll shape — to make it look even creepier and more doll-like.
materials
White fabric (photography backdrop) – main ghost part (https://a.co/d/fiu8FMx) Black fabric (thick curtain) – fishbone cushion (https://a.co/d/iN3wOLF) Red fabric (translucent) – eyes White embroidery thread and white ribbon – fishbone pattern (https://a.co/d/jlelgSO) Black embroidery thread and black marker – eyes Neo pixel x 99, one Gemma, soldering wire (https://a.co/d/a3CFcol)
I still prefer my first idea — cosplaying as Plankton’s electronic wife, Karen, from SpongeBob SquarePants. Although my second idea, the angel wings, is visually beautiful, it doesn’t feel as conceptually interesting. However, wearing a large “computer” on my head during the Halloween parade would not be safe. So I’m thinking about transforming the computer into a handheld screen or a portable box, while dressing myself in a mechanical or cyber-inspired outfit.
This way, I can ensure safety during the parade, and when taking photos, I can lift the screen up to my face to recreate Karen’s look — it would still be visually striking and conceptually playful.
1.Structure & Function
The device functions as a portable electronic screen that displays animated graphics and patterns. A button allows the user to switch between multiple display modes (heartbeat line, smile, or flat signal), recreating the reactive visual behavior of Karen from SpongeBob SquarePants.
2.Materials
Main Board:Use an Arduino UNO as the main control board to manage lighting and button interactions.
Display Module:BTF-LIGHTING WS2812B IC RGB 5050SMD Pure Gold Individual Addressable LED Strip 16.4FT 300LED 60Pixel/m Flexible Full Color IP30 DC5V for DIY Chasing Color Project
Light Source:Apply green LEDs or RGB lights (green channel only) to recreate Karen’s iconic electronic green glow.
Button:Add a small push button to switch between different facial expressions or animation modes.
I’ve decided to move ahead with my halloween costume resembling Eve from Pixar’s Wall-E. I’m particularly interested in Eve’s vocabulary of moods as demonstrated through her different eye-states. This is an important part of her character building in Wall-E as we see her character go from a mindless mission driven robot to the considerate and caring character that audiences love.
To tackle these different mood-states I’ve decided to use an LED matrix for each of Eve’s eyes and glue them to the inside of a full-face sunglass visor. Below are a few examples of different mood states I could express via the LED matrix. It’s particularly useful in this case that I may be able to use different colors through the RGB matrix to express enhanced states like anger.
I think I will mostly have a loop of alert with a ‘blinking’ animation loop to give the eyes effect. I will include a button on the visor or battery pack to toggle between mood states.
Shopping List
2x 8×8 RGB LED Matrix (Reminder to ask Becky which is best) 1x Sunglasses Visor 1x Rubber Gasket (to create distance between the visor + matrix and the face) 1x White Headcover 1x Adafruit Gemma 1x Battery Pack 1x Tactile Switch Button __x Jumper Wire __x Heat Seal Gasket __x Glue (Reminder to ask Becky which is best)
To-do list: 3D Print the Gem – option 1 – option 2 Solder the Led Strip – Attach to inside of pole? Attach Gem to Pole Wrap pole with fur to create handle Tie ribbons on to the pole
Arduino: I want to use a button to maybe toggle between two settings, both will be a fade through some gradient of pink light. I want to confirm, the best way to go about this.
This project recreates the iconic “?” Question Box from the Super Mario video game series as an interactive prop. When someone punches or taps the bottom of the box, it lights up brightly and plays a Mario coin sound, just like in the game when Mario collects a coin or power-up.
The intention behind this costume prop is to bring nostalgia and fun to Halloween. It’s not designed to scare people — it’s designed to make people smile and feel like they’re inside the Mario world. When friends see the glowing box and hear the coin sound, they immediately recognize it and often want to “hit” it themselves! It’s both interactive and playful, perfect for a group or gaming-themed costume.
Concept: Inspired by the iconic Question Block from the Super Mario games, this interactive box lights up and changes color whenever it’s “hit” from below — just like in the game when Mario punches it to release a coin or power-up. The project uses NeoPixel LEDs for vivid lighting effects and an impact sensor (or push button) at the bottom to detect the punch or tap.
Objective: To recreate a nostalgic video game interaction using Arduino and NeoPixel LEDs, demonstrating how sensors can trigger real-time lighting animations.
Step-by-Step Build Process
1️⃣ Prototype on Breadboard
Connect Arduino, DFPlayer, button, and LED strip on breadboard.
Upload code to test light + sound reaction.
2️⃣ Prepare the Box
Build or purchase a yellow box (15–20 cm cube).
Cut question marks (white “?”) from paper or vinyl.
Mount LED strip inside the box edges (with the arrows following data flow).
3️⃣ Install Components
Fix Arduino + DFPlayer inside the bottom compartment.
Mount the button under the bottom panel (acts as the “hit detector”).
Place the speaker facing downward through a small hole for louder sound.
Secure all wiring with hot glue or Velcro.
4️⃣ Power and Testing
Connect USB power bank → Arduino’s USB port.
Press the bottom to test:
LEDs flash and shift colors ✨
Coin sound plays 🔊
5️⃣ Adjust Brightness & Volume
🧠 Physical Construction
Box Design
Construct a cube (around 15–20 cm) using yellow cardboard, acrylic, or foam board.
Add white “?” symbols on all sides for the authentic Mario look.
Install NeoPixel LEDs inside the box so the light diffuses softly through the walls.
The bottom panel will house the button or impact sensor — users can punch or tap it to activate the light show.
Electronics Placement
Place the Arduino Nano inside or beneath the box.
Wires from the impact sensor and LEDs feed into the Arduino through small holes.
The power supply (battery pack) can sit outside or be hidden beneath the display stand.