Searching for a simple costume project to bring your Unikitty or Lady Rainicorn to the next level? 3D print a flexible unicorn horn and illuminate it from within with NeoPixels and a GEMMA M0, GEMMA v1 or GEMMA v2 based microcontroller. Or forget the electronics and use glow in the dark NinjaFlex filament for a green glow with no batteries required.

This guide was written for the Gemma v2 board, but can be done with either the original or Gemma M0. We recommend the Gemma M0 as it is easier to use and is more compatible with modern computers!

This is a pretty quick soldering project that is suitable for attentive beginners! Prerequisite guides:

For this project you will need:

Unicorn glamour shots by Andrew Tingle.

Download the printable unicorn horn file:

3D Printer

To print the unicorn horn, the 3D printer will need to be capable of printing a minimum of 140mm tall. The diameter of the horn is 40mm x 48mm, which should be enough to fit on most beds, such as the Printrbot Simple Metal.

For 3D printing with Ninjaflex material, we recommend using a printer with a direct direct, spring loaded extruder. The horn can be printed in PLA, ABS and other filaments.

Slicer Settings

For the best quality when printing with NinjaFlex, we recommend the following slicing settings:

  • Retraction: Off
  • Speeds: 90/150
  • Extruder Temp: 230c
  • Infill 10%
  • Raft+Support: Off
  • No Heated Bed

Print time is approximately 3 hours.

From left to right: translucent, white, glow in the dark, white

This diagram uses the original Gemma but you can also use the Gemma M0 with the exact same wiring!

Two NeoPixel sticks are wired in parallel to GEMMA:

  • GEMMA GND to NeoPixel sticks GND
  • GEMMA D1 to NeoPixel sticks DIN
  • GEMMA Vout to NeoPixel sticks 4-7VDC
  • 500mAh battery connected to GEMMA's JST port
  • GEMMA's on/off switch used to toggle power

Here's a simplified version of the NeoPixel sample code that just cycles a slow rainbow on eight pixels connected to D1:

The Arduino code presented below works equally well on all versions of GEMMA: v1, v2 and M0. But if you have an M0 board, consider using the CircuitPython code on the next page of this guide, no Arduino IDE required!
// SPDX-FileCopyrightText: 2015 Phil Burgess for Adafruit Industries
//
// SPDX-License-Identifier: MIT
//
#include <Adafruit_NeoPixel.h>

#define PIN 1

// Parameter 1 = number of pixels in strip
// Parameter 2 = Arduino 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(8, PIN, NEO_GRB + NEO_KHZ800);

// IMPORTANT: Avoid connecting on a live circuit...if you must, connect GND first.

void setup() {
  strip.begin();
  strip.setBrightness(100); //adjust brightness here
  strip.show(); // Initialize all pixels to 'off'
}

void loop() {
  rainbowCycle(20);
}


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



// 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) {
  if(WheelPos < 85) {
   return strip.Color(WheelPos * 3, 255 - WheelPos * 3, 0);
  } else if(WheelPos < 170) {
   WheelPos -= 85;
   return strip.Color(255 - WheelPos * 3, 0, WheelPos * 3);
  } else {
   WheelPos -= 170;
   return strip.Color(0, WheelPos * 3, 255 - WheelPos * 3);
  }
}

Installing Arduino libraries is a frequent stumbling block. If this is your first time, or simply needing a refresher, please read the All About Arduino Libraries tutorial.If the library is correctly installed (and the Arduino IDE is restarted), you should be able to navigate through the “File” rollover menus as follows:

File→Sketchbook→Libraries→Adafruit_NeoPixel→strandtest

Connect up your NeoPixels in a solderless breadboard and use alligator clips to attach to GEMMA, referring to the circuit diagram if necessary.

You’ll need to change a few lines in the code regarding the data pin (1), type of pixels (RGB vs GRB), and number of pixels (5). The resulting (and slightly simplified) code is below:

From the Tools→Board menu, select the device you are using: 

  • Adafruit Gemma M0
  • Adafruit Gemma 8 MHz 
  • Connect the USB cable between the computer and your device. The original Gemma (8 MHz) need the reset button pressed on the board, then click the upload button (right arrow icon) in the Arduino IDE. You do not need to press the reset on the newer Gemma M0 or Trinket M0.

When the battery is connected, you should get a light show from the LEDs. All your pixels working? Great! You can take apart this prototype and get ready to put the pixels in the collar. Refer to the NeoPixel Uberguide for more info.

GEMMA M0 boards can run CircuitPython — a different approach to programming compared to Arduino sketches. In fact, CircuitPython comes factory pre-loaded on GEMMA M0. If you’ve overwritten it with an Arduino sketch, or just want to learn the basics of setting up and using CircuitPython, this is explained in the Adafruit GEMMA M0 guide.

These directions are specific to the “M0” GEMMA board. The original GEMMA with an 8-bit AVR microcontroller doesn’t run CircuitPython…for those boards, use the Arduino sketch on the “Arduino code” page of this guide.

Below is CircuitPython code that works similarly (though not exactly the same) as the Arduino sketch shown on a prior page. To use this, plug the GEMMA M0 into USB…it should show up on your computer as a small flash drive…then edit the file “code.py” with your text editor of choice. Select and copy the code below and paste it into that file, entirely replacing its contents (don’t mix it in with lingering bits of old code). When you save the file, the code should start running almost immediately (if not, see notes at the bottom of this page).

If GEMMA M0 doesn’t show up as a drive, follow the GEMMA M0 guide link above to prepare the board for CircuitPython.

# SPDX-FileCopyrightText: 2017 Mikey Sklar for Adafruit Industries
# SPDX-FileCopyrightText: 2021 Kattni Rembor for Adafruit Industries
#
# SPDX-License-Identifier: MIT
#
import time

import board
import neopixel
from rainbowio import colorwheel
from digitalio import DigitalInOut, Direction

pixpin = board.D1
numpix = 8

led = DigitalInOut(board.D13)
led.direction = Direction.OUTPUT

strip = neopixel.NeoPixel(pixpin, numpix, brightness=1, auto_write=True)


def rainbow_cycle(wait):
    for j in range(255 * 5):
        for i in range(len(strip)):
            idx = int((i * 256 / len(strip)) + j)
            strip[i] = colorwheel(idx & 255)
        time.sleep(wait)


def rainbow(wait):
    for j in range(255):
        for i in range(len(strip)):
            idx = int(i + j)
            strip[i] = colorwheel(idx & 255)
        time.sleep(wait)


while True:
    rainbow_cycle(0.05)

This code requires the neopixel.py library. A factory-fresh board will have this already installed. If you’ve just reloaded the board with CircuitPython, create the “lib” directory and then download neopixel.py from Github.

For the headband version, measure two pieces of grosgrain ribbon to fit your skull, and mark/cut to length. The hair elastic will make up for the lack of seam allowance.

Using a zigzag stitch on your sewing machine, stitch the edges of the ribbons together leaving the last 1.5 inches unstitched.

Fold over the raw ends around a hair elastic and stitch in place for a stretch fit!

If you don’t plan to add electronics, you can make the headband with just one piece of ribbon.

 

Fold the headband in half and crease it at the mid point, then hand stitch the horn in place through the sew tabs and wear.

Set up your NeoPixel sticks in a pair of helping hands with the input ends facing you and close to one another.

 

Tin the pads with solder and connect one ground to another with a small piece of silicone coated wire. Also solder on a long wire to another ground pad, to extend to GEMMA.

 

Similarly solder up parallel connections between the pairs of digital inputs and power pads according to the circuit diagram. Take care where two wires are soldered to the same pad to avoid shorts.

If you’re making a headband, snip a hole in the outer layer of ribbon at the front center and thread the long wires through to the back of the headband. Use a seam ripper to open up the zigzag stitching a bit to get the wires out and make room for the GEMMA and battery. Solder the three wires to GEMMA according to the circuit diagram.

If you’re making a baseball cap, cut a hole in the front with a seam ripper and thread the long wires through before soldering to GEMMA.

Upload the rainbow sample code to GEMMA with the Arduino Code or to the GEMMA M0 using the CircuitPython Code. This will allow confirmation that your solder joints are solid before sticking the NeoPixel sticks together, back to back, using double-stick foam tape.

Use an optional tuft of fiberfill to help keep the sticks centered within the horn, and place inside. Rotate the assembly until you’re happy with the arrangement.

Thread a needle, double over the thread, and knot the ends together. Hand stitch each sew tab and knot/cut the thread individually.

Inside the cap, tack the wires down along their way to the GEMMA and battery inside the trim.

Use GEMMA’s onboard on/off switch to toggle the circuit’s power. This project is fun with or without electronics, make one to fit your costume's style!

Consider further protecting the circuit with a coating or covering if you plan to be very active/sweaty or in wet conditions. Tips on that can be found in this video:

This guide was first published on Aug 05, 2015. It was last updated on Aug 05, 2015.