Skip to content

Latest commit

 

History

History
322 lines (238 loc) · 25.1 KB

README.md

File metadata and controls

322 lines (238 loc) · 25.1 KB

laser-stranger

framed_one_light_on

Introduction

For this project, I wanted to build a miniature replica of the Christmas lights wall from Stranger Things. If you haven't seen the first season of Stranger Things yet, do yourself a favor and add it to your watch queue ASAP! It's pretty great.

Check out this video clip for a reference to the wall. Winona Ryder's character essentially uses black paint and a strand of Christmas lights to create an alphabet Ouija board on her living room wall—in order to communicate with her son who is trapped in another dimension. Her son is able to spell out messages by illuminating the corresponding light bulbs, letter-by-letter.

wall_from_show_poster

Many other makers have already built versions of this Stranger Things wall with some neat and creative features (e.g. SparkFun's live Twitter wall), but none of them really looked very accurate to the show... I wanted my replica to mimic the creepy aesthetic and be used as a "wall" art piece, so I incorporated a laser to engrave the exact paint strokes.

The finished product was given as a gift to my friend, Regina. It featured addressable LEDs, a battery-powered Bluetooth microcontroller, and a companion mobile application that could be used to display messages remotely.

Supplies

supplies

Materials

Tools

  • Epilog Mini 24 60W Laser (courtesy of Harris County Public Library)
  • Soldering iron with hot air rework station; electric skillet
  • Solder wire and solder paste
  • Fine point tweezers
  • Wire stripper/cutter
  • Hot glue gun
  • Glue stick
  • Super glue
  • Black paint and brush
  • Black ink pen
  • Measuring tape

Build Process

This project mainly consists of three separate parts: laser engraving the alphabet, constructing a custom Christmas lights strand, and writing the control software. The most tedious part was definitely the lights strand because it was all done manually by hand... and there are 26 letters in the English alphabet. But I'm pretty proud with how it all turned out.

Laser Alphabet

Step 1: Create Binary Image

In order to do the laser engraving, we need to provide a black/white image to the Epilog laser software. Since I only want to engrave the alphabet paint strokes, they must be segmented from the rest of the wall (remove the Christmas lights, wallpaper, etc.) in the source image. I used Gimp and Adobe Illustrator image editing tools to adjust the threshold levels and erase any unwanted artifacts. Then I resized the binary image to fit my 12" x 24" canvas.

wall_from_show

stranger_things_wall_12x24

*Note: the 'Z' character was originally omitted in my source image, which is why it doesn't quite match up...

Step 2: Prepare Canvas

Next, prepare the canvas by glueing wallpaper to the plywood. I used a glue stick and wallpaper samples that had a similar floral design as the one from the show.

wallpaper_plywoodwallpaper_plywood_glued

Step 3: Laser Engraving

Make sure to test your laser engraving settings on a piece of scrap plywood first! You'll want to dial in the speed/power settings to etch through the paper and a layer of plywood, but not burn it! I did not do this and got burn marks on my expensive wallpaper... so I had to start over using two sheets of 12"x12" decorative paper. Also, make sure the canvas is properly aligned on the bed. Then, just let the laser do the work!

Unfortunately, I did not have the foresight to record a video of the laser engraving. But here is an image of the laser I used and the finished engraving job. I think it took about 45 minutes to finish.

laserwallpaper_engrave

Step 4: Paint the Letters

Fill in the engraved letters with black paint. Be careful not to drip any extra paint marks. I also found it helpful to use a black ink pen to touch up the narrow regions in the wood.

wallpaper_paintwallpaper_paint_fill

Christmas Lights

Step 1: Select LEDs and Design Breakout Boards

In order to illuminate one light bulb at a time, the light strand needs to use addressable LEDs. I found small C3-sized Christmas lights on Amazon, but they were not addressable... so I decided to retrofit the bulbs with small NeoPixel RGB LEDs. These LEDs are addressable and very popular among electronics hobbyists. Each LED would need to be daisy-chained with three wires to provide 3V, ground, and a data signal. Knowing this, I designed small breakout printed circuit boards that could support the C3 bulb and connect each LED to the daisy-chain with wires. The breakout board PCB was designed in Altium and fabricated by OSH Park for ~$0.10/board.

oshpark_toposhpark_bottom breakout_boards

Step 2: Assemble Breakout Boards

These LEDs and breakout boards are quite small at ~7x7 mm. Instead of soldering the heat-sensitive parts by hand, I decided to use solder paste and an electric skillet (the poor man's reflow oven). I found it helpful to use a microscope and stencil to apply the paste to the pads, then use tweezers to carefully place the LED. I didn't bother with soldering the decoupling capacitor in order to allow more space for mounting the light bulb.

breakout_boardbreakout_stencil breakout_solder_pastebreakout_led_placement

Repeat this process at least 26 times...

breakout_solder_paste_repeat

After all the boards are populated, place them on the electric skillet. Cover and turn up the heat. Try to follow the reflow profile for the LEDs, but ultimately keep an eye on the solder paste and watch when it gets hot enough to make a solid joint. I like using low-temp solder paste for this.

breakout_skilletbreakout_assembled

Step 3: Wire Up

The next step is to add wires to connect each LED breakout board together. These addressable LEDs work in a daisy-chain configuration with 3 input signals (VDD, GND, DIN) and 3 output signals (VDD, GND, DOUT). To keep track of the signals, I color-coded the wires using a standard convention of VDD=red, GND=black, DATA=white. I selected solid core 22 AWG gauge wire because it is easy to solder to through-hole pads and the wire itself holds its shape when bent.

wire_measure

Careful planning must be done to measure the wires between each LED. You must account for the space between the letters, but also leave room for wire stripping and soldering. It was helpful to use a measuring tape and a wire stripper/cutter for this task. To make it easier to mount the Christmas lights to the plywood, I decided to split the lights into three separate strands, one for each row of letters. This makes it look cleaner from the front, while the daisy-chain connection is managed in the back behind the frame. For this, I used 0.1" male and female header pins to effectively make extension cables.

wire_led_top_wire_led_bottom_ wire_header

I also added heat shrink tubing between each LED to make it look like a single black cable, matching how Christmas lights normally look. Cut to size and make sure to add these measured strips of heat shrink before soldering the next breakout board in the chain. After soldering the neighboring wires, use hot air or a lighter flame to activate the heat shrink tubing.

wire_heat_shrink

Step 4: Mount Christmas Light Bulbs

As you are adding new LEDs to the daisy-chain, it is good practice to test that the LEDs are functional and in the correct position. An easy way to check this is by connecting the strand to an Arduino and using Adafruit's NeoPixel library strandtest example to illuminate the LEDs. Once all of the LEDs have been verified to work, you are ready to mount the Christmas light bulbs to the breakout boards.

wire_measure_lightswire_test_lights

The C3 Christmas lights that I bought didn't have easily removable plastic bulbs. I needed to pry them off and use a cutter to carefully expose a large enough hole at the bulb base for the LED to shine through. Without cutting the plastic base, the LED would not properly diffuse light inside of the bulb; it needed to be flush to maximize light throw. Once 26 bulbs were removed, I arranged them in a color order to avoid any same-color neighbors. Using a hot glue gun, add a dab of hot glue on top of the LED and quickly apply the plastic bulb to the breakout board. Hold together for a few seconds for the surfaces to bond. The hot glue acts as an adhesive, but also works to diffuse light inside the bulb. Repeat this glueing process for all remaining LEDs, also using super glue if a stronger bond is needed. Pay attention to the orientation of each bulb, as some need to point at different angles.

bulb_removebulb_extract wire_glue_bulbswire_measure_bulbs

After mounting the bulbs, test the light strand again to see how the bulbs look when illuminated.

wire_test_bulbs

Software

The control software consists of microcontroller firmware to drive the LEDs and respond to Bluetooth commands from a companion mobile application. I used custom-built electronics from a previous project because it already contained the necessary components to power several LEDs with a Lithium-polymer battery. This custom board used a Nordic nRF52832 BLE System-on-Chip, which could easily connect to any Android or Apple smartphone device. The software is fairly straightforward... so any dev board like Arduino, Raspberry Pi, ESP32, or XIAO should also work fine. Just make sure it can adequately drive and control 26 LEDs.

Step 1: Alphabet-LED Protocol

Once you are able to turn on/off a specific LED in the daisy-chain, you just need to translate the text characters into light commands. To do this, I leveraged the ASCII standard, which already represents each character with a unique number (shown below in decimal and hex). Note that a space character is represented by 0x20, and upper- and lowercase A-z letters use different values. The leftmost column represents the LED index value in the Christmas lights daisy-chain.

# Character ASCII Dec ASCII Hex ASCII Dec ASCII Hex
- Space 32 0x20 -- --
0 A, a 65 0x41 97 0x61
1 B, b 66 0x42 98 0x62
2 C, c 67 0x43 99 0x63
3 D, d 68 0x44 100 0x64
4 E, e 69 0x45 101 0x65
5 F, f 70 0x46 102 0x66
6 G, g 71 0x47 103 0x67
7 H, h 72 0x48 104 0x68
8 I, i 73 0x49 105 0x69
9 J, j 74 0x4A 106 0x6A
10 K, k 75 0x4B 107 0x6B
11 L, l 76 0x4C 108 0x6C
12 M, m 77 0x4D 109 0x6D
13 N, n 78 0x4E 110 0x6E
14 O, o 79 0x4F 111 0x6F
15 P, p 80 0x50 112 0x70
16 Q, q 81 0x51 113 0x71
17 R, r 82 0x52 114 0x72
18 S, s 83 0x53 115 0x73
19 T, t 84 0x54 116 0x74
20 U, u 85 0x55 117 0x75
21 V, v 86 0x56 118 0x76
22 W, w 87 0x57 119 0x77
23 X, x 88 0x58 120 0x78
24 Y, y 89 0x59 121 0x79
25 Z, z 90 0x5A 122 0x80

When the firmware receives a message command on the NUS Bluetooth service, it will call the abc_display_char() function to display that character's LED. The abc_display_char() function takes an input character, calculates the corresponding LED index, and turns that LED on for a certain duration (g_char_duration_ms)—then turns the LED off in preparation for displaying the next LED/letter (g_inter_char_duration_ms).

// In Nordic UART Service Handler...
// Display message received
if (p_data[0]==HEAD_MESSAGE_0 && p_data[1]==HEAD_MESSAGE_1) {
  for (uint8_t ii=0; ii < length-2; ii++) {
    char cc = p_data[ii+2];
    if (abc_validate(cc) == true) {
      // NRF_LOG_INFO("%c", cc);
      abc_display_char(cc);
    }
  }
  eg_leds_off();
}

...

void abc_display_char(char c) {
  // If character is a space, turn off LEDs for g_space_duration
  if (c == ' ') {
    clear_leds();
    nrf_delay_ms(g_space_duration_ms);
  }

  // If character is ABC, display character LED for g_char_duration and inter-character delay with LEDs off
  else {
    uint8_t led_idx;
    if (c >= 'A' && c <= 'Z') {
      led_idx = c - 'A';
      eg_set_single_led(led_idx, g_led_r, g_led_g, g_led_b, LED_DIN_PIN);
      nrf_delay_ms(g_char_duration_ms);
      clear_leds();
      nrf_delay_ms(g_inter_char_duration_ms);
    } else if (c >= 'a' && c <= 'z') {
      led_idx = c - 'a';
      eg_set_single_led(led_idx, g_led_r, g_led_g, g_led_b, LED_DIN_PIN);
      nrf_delay_ms(g_char_duration_ms);
      clear_leds();
      nrf_delay_ms(g_inter_char_duration_ms);
    }
  }
}

Parameters

The firmware sets the following default LED color/brightness values and on/off durations in milliseconds. These parameters can be easily changed to reduce the brightness, change colors, or slow down the message display.

#define DEFAULT_LED_R                               255
#define DEFAULT_LED_G                               255
#define DEFAULT_LED_B                               255
#define DEFAULT_CHAR_DURATION_MS                    1000
#define DEFAULT_INTER_CHAR_DURATION_MS              250
#define DEFAULT_SPACE_DURATION_MS                   1000

uint8_t led_idx;              // LED index number (range 0-25)
uint8_t led_r, led_g, led_b;  // LED RGB color (range 0-255)
uint16_t char_duration;       // Sequence LED on duration (ms)
uint16_t inter_char_duration; // Sequence LED off duration (ms)
uint16_t space_duration;      // 'Space' character duration (ms)

Step 2: User Interface

Apologies for the user interface design... I didn't spend much time on it so it is purely functional (not pretty). The app has four main sections that are accessible via the bottom tabs. Wall lets you interact with the alphabet lights in real-time; pressing a letter in the app will illuminate the corresponding letter in the frame. Message lets you input a text string to display letter-by-letter like in the television show. The function iterates over the character array and activates the corresponding LED in a timed sequence. Light Patterns contains some easter eggs to recreate the messages from the show ("right here", "run") and some other fun things like a random yes/no Magic 8 Ball. Settings gives you full control to monitor the battery level and adjust the timing and LED color/brightness settings. Using max brightness white is easiest because the light bulbs are already tinted.

The mobile app was written in Javascript using React Native and the react-native-ble-manager library. Button onPress events can simply use the sendWallMessage() function to trigger the lights sequence.

export const sendWallMessage = (peripheralId, text) => {
  var data = [bleConst.HEADER_MESSAGE[0], bleConst.HEADER_MESSAGE[1]];
  for(var ii = 0; ii < text.length; ii++) {
    var val = text.charCodeAt(ii);
    data.push(val);
  }
  writeEllieChar(data, peripheralId, bleConst.EG_UART_SERVICE_UUID, bleConst.EG_UART_RX_CHAR_UUID);
};

...

// Usage Examples:
actions.sendWallMessage(CONNECTED_PERIPHERAL.id, 'A')
actions.sendWallMessage(CONNECTED_PERIPHERAL.id, 'hello world')
actions.sendWallMessage(CONNECTED_PERIPHERAL.id, this.state.text)

Step 3: Easter Eggs

The firmware also includes a few easter egg references from the Stranger Things show. Calling these commands will also display a colorful blinking light sequence at the end to mimic the "RUN" scene from the television show.

void stranger_things_easter_egg_0(void) {
  abc_display_string("right here");
  eg_leds_off();
}

void stranger_things_easter_egg_1(void) {
  abc_display_string("run ");
  all_leds_blink(g_led_r, g_led_g, g_led_b, 100, 100);
  all_leds_blink(g_led_r, g_led_g, g_led_b, 100, 100);
  all_leds_blink(g_led_r, g_led_g, g_led_b, 100, 100);
  all_leds_blink(g_led_r, g_led_g, g_led_b, 100, 100);
  all_leds_blink(g_led_r, g_led_g, g_led_b, 100, 100);
  all_leds_blink(g_led_r, g_led_g, g_led_b, 100, 100);
  all_leds_blink(g_led_r, g_led_g, g_led_b, 100, 100);
  all_leds_blink(g_led_r, g_led_g, g_led_b, 100, 100);
  theater_chase_rainbow(25);
  eg_leds_off();
}

Final Assembly

Step 1: Glue Christmas Lights

Position the Christmas lights strands against the wallpaper plywood to align with the letters and match the configuration of the real Stranger Things wall. Use super glue for a more secure and permanent bond.

assembly_glue

Step 2: Insert Into Frame

Fold the wires around to the backside of the plywood and insert into the frame. Secure with the frame tabs and clear room for any wall-mounting hardware.

assembled_lights_off

Step 3: Connect Electronics

Connect the light strands together with the extension cables and plug it into the electronics board. Connect the battery or power the board via USB cable.

assembled_back

Step 4: Send A Message

Launch the mobile app and establish a Bluetooth connection. Then use the various tab options to send a message.

Examples:

Gifting

The primary motivation for this project was to be a gift for my friend and coworker, Regina. A few months prior, she had a hemorrhage that required multiple brain surgeries. She experienced paralysis on the right side of her body and had some difficulty speaking. We were both fans of the Stranger Things show and joked that she resembled one of the main characters (Eleven) with her shaved head and slow speech. I had previously worked on a project with her that utilized electronics and a mobile app to control addressable LEDs, so the inner workings were already familiar to me. In fact, I was able to use old prototype hardware.

I was compelled to build this project because I felt that it was a gift that only I could give—and if I didn't, she would never receive something so special. I'm happy to report that she is doing well 2 years later, continuing her recovery with the best of spirits and brightest of smiles.

gift_regina_hospitalgift_regina_update

I also added a nameplate with a custom message on the back of the frame. The nameplate itself was a small sheet of anodized aluminum, which could easily be engraved by the laser. It turned out great.

assembled_nameplate

Resources