3D print this Frankenstein's Monster head, nicknamed Frank, to build a light-up Halloween decoration. NeoPixels illuminate the inside of the model for a clean and even lighting effect. Frank's brains are powered by a QT Py board, making this build nice and compact.

Capacitive Touch

Frank's bolts have copper tape for capacitive touch. Tapping either bolt will change the colors of the NeoPixels.

Parts

Adafruit QT Py - SAMD21 Dev Board with STEMMA QT
What a cutie pie! Or is it... a QT Py? This diminutive dev board comes with our favorite lil chip, the SAMD21 (as made famous in our GEMMA M0 and Trinket M0 boards).This time it...
Out of Stock
GD25Q16 - 2MB SPI Flash in 8-Pin SOIC package
These little chips are like miniature SSD drives for your electronics. When you don't need something with as much storage as a micro SD card, but an EEPROM is too small, SPI (or...
Out of Stock
Adafruit NeoPixel LED Side Light Strip - Black 90 LED
Fancy new side light LED strips are a great alternative for folks who have loved and used Adafruit LED strips for a few years but want gorgeous, glowy light emitting at...
$26.95
In Stock
Copper Foil Tape with Conductive Adhesive - 6mm x 5 meters long
Copper tape can be an interesting addition to your toolbox. The tape itself is made of thin pure copper so it's extremely flexible and can take on nearly any shape. You can solder...
$4.95
In Stock
USB Type A to Type C Cable - 1ft - 0.3 meter
As technology changes and adapts, so does Adafruit. This  USB Type A to Type C cable will help you with the transition to USB C, even if you're still...
$3.95
In Stock
USB Battery Pack - 2200 mAh Capacity - 5V 1A Output
A smaller-sized rechargeable battery pack for your Raspberry Pi or Raspberry...
Out of Stock
Adafruit Perma-Proto Quarter-sized Breadboard PCB - Single
Customers have asked us to carry basic perf-board, but we never liked the look of most basic perf: its always crummy quality, with pads that flake off and no labeling. Then we thought...
$2.95
In Stock
20-pin 0.1" Female Headers - Rainbow Color Mix - 5 pack
Female header is like the duct tape of electronics. It's great for connecting things together, soldering to perf-boards, sockets for wires or break-away header, etc. We go through...
$2.50
In Stock
4 x Acrylic paint
Acrylic paint for the hair, scar, teeth and bolts

Wired Connections

NeoPixel Strip

  • DIN to A3 on the QT Py
  • 5V to 5V on the QT Py
  • GND to GND on the QT Py

Capacitive Touch

  • Copper tape to A1 on the QT Py
  • Copper tape to A2 on the QT Py

Power

The QT Py has a USB C port, making it perfect for powering it with a USB battery. Connect a USB C to USB A cable to your preferred USB battery bank for instant power.

The .STL file is available for you to print Frank on your FDM-style printer. Frank prints with no supports, making for an easy print. A full-sized Frank takes approximately 21 hours, but you can scale him down for a faster print time.

Painting

To make Frank really pop, you can paint his scar, hair, teeth and bolts. Acrylic paint works really well for 3D printed parts and can be found in many different stores.

CircuitPython is a derivative of MicroPython designed to simplify experimentation and education on low-cost microcontrollers. It makes it easier than ever to get prototyping by requiring no upfront desktop software downloads. Simply copy and edit files on the CIRCUITPY drive to iterate.

Set up CircuitPython Quick Start!

Follow this quick step-by-step for super-fast Python power :)

If you want to get started with your QT Py, and you have NOT soldered a chip to the back of it, download CircuitPython from the following link:

If you have soldered a GD25Q16 SPI flash chip to the bottom of your board, you must use the Haxpress version of CircuitPython for the Adafruit QT Py for the flash to work! If you have NOT soldered a SPI flash chip to your QT Py, do NOT use this download! It will not give you 2MB of flash space without a chip!

Click the link above and download the latest UF2 file.

Download and save it to your desktop (or wherever is handy).

Plug your QT Py into your computer using a known-good USB cable.

A lot of people end up using charge-only USB cables and it is very frustrating! So make sure you have a USB cable you know is good for data sync.

Double-click the small RST (reset) button, and you will see the NeoPixel RGB LED turn green. If it turns red, check the USB cable, try another USB port, etc.

If double-clicking doesn't work the first time, try again. Sometimes it can take a few tries to get the rhythm right!

You will see a new disk drive appear called QTPY_BOOT.

 

 

 

Drag the adafruit_circuitpython_etc.uf2 file to QTPY_BOOT

The red LED will flash. Then, the QTPY_BOOT drive will disappear and a new disk drive called CIRCUITPY will appear.

That's it, you're done! :)

As we continue to develop CircuitPython and create new releases, we will stop supporting older releases. Visit https://circuitpython.org/downloads to download the latest version of CircuitPython for your board. You must download the CircuitPython Library Bundle that matches your version of CircuitPython. Please update CircuitPython and then visit https://circuitpython.org/libraries to download the latest Library Bundle.

Each CircuitPython program you run needs to have a lot of information to work. The reason CircuitPython is so simple to use is that most of that information is stored in other files and works in the background. These files are called libraries. Some of them are built into CircuitPython. Others are stored on your CIRCUITPY drive in a folder called lib. Part of what makes CircuitPython so awesome is its ability to store code separately from the firmware itself. Storing code separately from the firmware makes it easier to update both the code you write and the libraries you depend.

Your board may ship with a lib folder already, it's in the base directory of the drive. If not, simply create the folder yourself. When you first install CircuitPython, an empty lib directory will be created for you.

CircuitPython libraries work in the same way as regular Python modules so the Python docs are a great reference for how it all should work. In Python terms, we can place our library files in the lib directory because its part of the Python path by default.

One downside of this approach of separate libraries is that they are not built in. To use them, one needs to copy them to the CIRCUITPY drive before they can be used. Fortunately, we provide a bundle full of our libraries.

Our bundle and releases also feature optimized versions of the libraries with the .mpy file extension. These files take less space on the drive and have a smaller memory footprint as they are loaded.

Installing the CircuitPython Library Bundle

We're constantly updating and improving our libraries, so we don't (at this time) ship our CircuitPython boards with the full library bundle. Instead, you can find example code in the guides for your board that depends on external libraries. Some of these libraries may be available from us at Adafruit, some may be written by community members!

Either way, as you start to explore CircuitPython, you'll want to know how to get libraries on board.

You can grab the latest Adafruit CircuitPython Bundle release by clicking the button below.

Note: Match up the bundle version with the version of CircuitPython you are running - 3.x library for running any version of CircuitPython 3, 4.x for running any version of CircuitPython 4, etc. If you mix libraries with major CircuitPython versions, you will most likely get errors due to changes in library interfaces possible during major version changes.

If you need another version, you can also visit the bundle release page which will let you select exactly what version you're looking for, as well as information about changes.

Either way, download the version that matches your CircuitPython firmware version. If you don't know the version, look at the initial prompt in the CircuitPython REPL, which reports the version. For example, if you're running v4.0.1, download the 4.x library bundle. There's also a py bundle which contains the uncompressed python files, you probably don't want that unless you are doing advanced work on libraries.

After downloading the zip, extract its contents. This is usually done by double clicking on the zip. On Mac OSX, it places the file in the same directory as the zip.

Open the bundle folder. Inside you'll find two information files, and two folders. One folder is the lib bundle, and the other folder is the examples bundle.

Now open the lib folder. When you open the folder, you'll see a large number of mpy files and folders

Example Files

All example files from each library are now included in the bundles, as well as an examples-only bundle. These are included for two main reasons:

  • Allow for quick testing of devices.
  • Provide an example base of code, that is easily built upon for individualized purposes.

Copying Libraries to Your Board

First you'll want to create a lib folder on your CIRCUITPY drive. Open the drive, right click, choose the option to create a new folder, and call it lib. Then, open the lib folder you extracted from the downloaded zip. Inside you'll find a number of folders and .mpy files. Find the library you'd like to use, and copy it to the lib folder on CIRCUITPY.

This also applies to example files. They are only supplied as raw .py files, so they may need to be converted to .mpy using the mpy-cross utility if you encounter MemoryErrors. This is discussed in the CircuitPython Essentials Guide. Usage is the same as described above in the Express Boards section. Note: If you do not place examples in a separate folder, you would remove the examples from the import statement.

If a library has multiple .mpy files contained in a folder, be sure to copy the entire folder to CIRCUITPY/lib.

Example: ImportError Due to Missing Library

If you choose to load libraries as you need them, you may write up code that tries to use a library you haven't yet loaded.  We're going to demonstrate what happens when you try to utilise a library that you don't have loaded on your board, and cover the steps required to resolve the issue.

This demonstration will only return an error if you do not have the required library loaded into the lib folder on your CIRCUITPY drive.

Let's use a modified version of the blinky example.

import board
import time
import simpleio

led = simpleio.DigitalOut(board.D13)

while True:
    led.value = True
    time.sleep(0.5)
    led.value = False
    time.sleep(0.5)

Save this file. Nothing happens to your board. Let's check the serial console to see what's going on.

We have an ImportError. It says there is no module named 'simpleio'. That's the one we just included in our code!

Click the link above to download the correct bundle. Extract the lib folder from the downloaded bundle file. Scroll down to find simpleio.mpy. This is the library file we're looking for! Follow the steps above to load an individual library file.

The LED starts blinking again! Let's check the serial console.

No errors! Excellent. You've successfully resolved an ImportError!

If you run into this error in the future, follow along with the steps above and choose the library that matches the one you're missing.

Library Install on Non-Express Boards

If you have a Trinket M0 or Gemma M0, you'll want to follow the same steps in the example above to install libraries as you need them. You don't always need to wait for an ImportError as you probably know what library you added to your code. Simply open the lib folder you downloaded, find the library you need, and drag it to the lib folder on your CIRCUITPY drive.

You may end up running out of space on your Trinket M0 or Gemma M0 even if you only load libraries as you need them. There are a number of steps you can use to try to resolve this issue. You'll find them in the Troubleshooting page in the Learn guides for your board.

Updating CircuitPython Libraries/Examples

Libraries and examples are updated from time to time, and it's important to update the files you have on your CIRCUITPY drive.

To update a single library or example, follow the same steps above. When you drag the library file to your lib folder, it will ask if you want to replace it. Say yes. That's it!

A new library bundle is released every time there's an update to a library. Updates include things like bug fixes and new features. It's important to check in every so often to see if the libraries you're using have been updated.

Once you've finished setting up your QT Py with CircuitPython, you can add these libraries to the lib folder:

  • adafruit_led_animation
  • neopixel.mpy

Copy neopixel.mpy file and the adafruit_led_animation folder to the CIRCUITPY flash drive that appears when you plug your QT Py into your computer via USB.

Then, you can click on the Download: Project Zip link in the window below to download the code file and .STL file.

import time
import board
import touchio
import neopixel
from adafruit_led_animation.animation.pulse import Pulse
from adafruit_led_animation.color import (
    RED,
    YELLOW,
    ORANGE,
    GREEN,
    TEAL,
    CYAN,
    BLUE,
    PURPLE,
    MAGENTA,
    GOLD,
    PINK,
    AQUA,
    JADE,
    AMBER
)

#  NeoPixel pin
pixel_pin = board.A3
#  number of NeoPixels
pixel_num = 68

#  NeoPixels setup
pixels = neopixel.NeoPixel(pixel_pin, pixel_num, brightness=0.5, auto_write=False)

#  animation setup
pulse = Pulse(pixels, speed=0.1, color=RED, period=5)

#  two cap touch pins
touch_left = board.A1
touch_right = board.A2

#  cap touch setup
bolt_left = touchio.TouchIn(touch_left)
bolt_right = touchio.TouchIn(touch_right)

#  NeoPixel colors for animation
colors = [RED, YELLOW, ORANGE, GREEN, TEAL, CYAN, BLUE,
          PURPLE, MAGENTA, GOLD, PINK, AQUA, JADE, AMBER]

#  variable for color array index
c = 0

#  debounce states for cap touch
bolt_left_state = False
bolt_right_state = False

while True:
    #  run animation
    pulse.animate()

    #  debounce for cap touch
    if not bolt_left.value and not bolt_left_state:
        bolt_left_state = True
    if not bolt_right.value and not bolt_right_state:
        bolt_right_state = True

    #  if the left bolt is touched...
    if bolt_left.value and bolt_left_state:
        print("Touched left bolt!")
        #  increase color array index by 1
        c += 1
        #  reset debounce state
        bolt_left_state = False
    #  if the right bolt is touched...
    if bolt_right.value and bolt_right_state:
        print("Touched right bolt!")
        #  decrease color array index by 1
        c -= 1
        #  reset debounce state
        bolt_right_state = False
    #  if the color array index is bigger than 13...
    if c > 13:
        #  reset it to 0
        c = 0
    #  if the color array index is smaller than 0...
    if c < 0:
        #  reset it to 13
        c = 13
    #  update animation color to current array index
    pulse.color = colors[c]
    time.sleep(0.01)

Your QT Py CIRCUITPY drive should look like this after you load the libraries and code.py file:

You'll need to solder the 2MB SPI flash to the QT Py to run the code as written.

Import the Libraries

The code begins by importing the libraries and the colors that Frank's NeoPixels will be able to switch between.

import time
import board
import touchio
import neopixel
from adafruit_led_animation.animation.pulse import Pulse
from adafruit_led_animation.color import (
    RED,
    YELLOW,
    ORANGE,
    GREEN,
    TEAL,
    CYAN,
    BLUE,
    PURPLE,
    MAGENTA,
    GOLD,
    PINK,
    AQUA,
    JADE,
    AMBER
)

Setup the NeoPixels

The NeoPixels are setup, along with the Pulse LED animation.

#  NeoPixel pin
pixel_pin = board.A3
#  number of NeoPixels
pixel_num = 68

#  NeoPixels setup
pixels = neopixel.NeoPixel(pixel_pin, pixel_num, brightness=0.5, auto_write=False)

#  animation setup
pulse = Pulse(pixels, speed=0.1, color=RED, period=5)

Setup Capacitive Touch

Capacitive touch is setup for pins A1 and A2.

#  two cap touch pins
touch_left = board.A1
touch_right = board.A2

#  cap touch setup
bolt_left = touchio.TouchIn(touch_left)
bolt_right = touchio.TouchIn(touch_right)

Array of Colors

The colors array is created to hold all of the NeoPixel color options. This array will be accessed in the loop to change the NeoPixel color.

#  NeoPixel colors for animation
colors = [RED, YELLOW, ORANGE, GREEN, TEAL, CYAN, BLUE,
          PURPLE, MAGENTA, GOLD, PINK, AQUA, JADE, AMBER]

Variables and States

c is setup to be the index variable for the colors array. Its value will be updated in the loop to change the NeoPixel color.

bolt_left_state and bolt_right_state are setup to debounce the capacitive touch inputs.

#  variable for color array index
c = 0

#  debounce states for cap touch
bolt_left_state = False
bolt_right_state = False

The Loop

The loop begins by running the Pulse animation and setting up debouncing for the capacitive touch inputs. The adafruit_led_animation library allows for the animation to run uninterrupted in the background in the loop while other processes can take place.

while True:
    #  run animation
    pulse.animate()

    #  debounce for cap touch
    if not bolt_left.value and not bolt_left_state:
        bolt_left_state = True
    if not bolt_right.value and not bolt_right_state:
        bolt_right_state = True

Capacitive Touch Inputs

The capacitive touch inputs affect the value of c. If Frank's left bolt is touched, then c increases by 1. If Frank's right bolt is touched, then c decreases by 1.

#  if the left bolt is touched...
    if bolt_left.value and bolt_left_state:
        print("Touched left bolt!")
        #  increase color array index by 1
        c += 1
        #  reset debounce state
        bolt_left_state = False
    #  if the right bolt is touched...
    if bolt_right.value and bolt_right_state:
        print("Touched right bolt!")
        #  decrease color array index by 1
        c -= 1
        #  reset debounce state
        bolt_right_state = False

Tracking the Color

c is tracking the index of the colors array. There are 14 colors total. If c goes above that range, it is reset to 0. If c goes below 0, it is reset to 13. This allows you to loop through the colors continuously.

#  if the color array index is bigger than 13...
    if c > 13:
        #  reset it to 0
        c = 0
    #  if the color array index is smaller than 0...
    if c < 0:
        #  reset it to 13
        c = 13

Update the Color

Finally, the color of the NeoPixels is updated with pulse.color. You can access the animation's other parameters in the loop by using pulse.[parameter], for example: pulse.speed, pulse.period, etc.

#  update animation color to current array index
    pulse.color = colors[c]
    time.sleep(0.01)

Soldering the Flash Chip

See the QT Py guide for information on soldering the flash chip onto the back of the QT Py and ensuring you are running the "haxpress" version of CircuitPython downloaded from circuitpython.org.

You'll need to solder the 2MB SPI Flash to the back of the QT Py to run the code as written.

Headers and the Perma-Proto

A 1/4 Perma-Proto board is used to keep the wiring neat. The QT Py will plug-in with headers.

Solder two sets of socket headers, seven sockets long, onto the Perma-Proto. Space them for the QT Py.

Solder plug headers onto the QT Py, using the socket headers as a guide. 

Solder a piece of wire from the QT Py's 5V pin to the Perma-Proto's 5V rail. Then, solder a piece of wire from the QT Py's GND pin to the Perma-Proto's ground rail.

Prep the NeoPixels

Beginning with the second pixel on your strip, count off 34 pixels and mark the position with a marker. 

Cut off the first pixel with your snips and then cut at your marker position. Make sure to snip in the middle of the solder pads.

Using tweezers, pull your newly separated strip out of the silicone packaging.

Repeat this process for a second strand of 34 pixels. 

You'll have two strands of 34 pixels for a total of 68 for Frank.

Solder the NeoPixels

Using sticky tack, secure the first NeoPixel strip flat on your workspace.

Take three wires, tin them and then solder them to the NeoPixel strip's pads. A piece of sticky tack can be helpful to secure the wires as well.

Your wire lengths should be around 5 inches.

Solder the 5V wire to the Perma-Proto's 5V rail, the GND wire to the Perma-Proto's GND rail and the DIN wire to the Perma-Proto's A3 rail.

Connect the two NeoPixel strips together by soldering 5V to 5V, GND to GND and DIN to DOUT.

Your wire lengths should be around 4 inches.

Add the Capacitive Touch Pads

Cut two pieces of copper tape. The pieces should be approximately 4 inches long.

Tin the end of each piece of copper tape with wire. Then, solder a piece of wire to each piece of tape.

The wires should be approximately 5 inches long.

Solder the copper tape's wires to the A1 and A2 rails on the Perma-Proto, respectively.

Hot Glue the Perma-Proto

The Perma-Proto board is mounted between Frank's eyes and mouth with the QT Py's USB C port pointing down.

Using a hot glue gun, lay glue down across the solder points for the QT Py's sock headers and then attach to the inside of Frank.

Hot Glue the First NeoPixel Strip

Position the first NeoPixel strip so that the pixels are shining downward. Using sticky tack, position them just above Frank's brow so that they'll shine down above the eyes.

Once you're happy with the position, tack the strip in place with your glue gun. Put small dabs on top of the solder pads so that the strip is secure. 

Also put hot glue on the wire connections for the strip to prevent any shorts.

Attach the Capacitive Touch Strips

Remove the copper tape's backing and place the pieces so that they run down the middle of the bolts. The solder point should be mounted vertically inside of Frank.

Hot glue both pieces of tape's solder points and any contact points inside of Frank to avoid any shorting.

Hot Glue the Second NeoPixel Strip

Repeat the mounting and hot gluing process with the second strip, this time with the pixels facing up. They should be mounted just below Frank's bottom lip so that his mouth is illuminated.

Plug Frank's QT Py brain into a USB battery bank via the QT Py's USB C port. The Pulse animation will begin.

You can change the colors of the Frank's NeoPixels by touching either piece of copper tape that is located on Frank's bolts. You can adjust the color to fit yours and Frank's moods throughout the day or to best match your Halloween decor.

This guide was first published on Oct 27, 2020. It was last updated on Oct 27, 2020.