Sand Physics Toy

Build a beautiful 3D printed hourglass physics toy using LED matrices and an Adafruit Feather Sense. Use CircuitPython to simulate particle collision code on a small microcontroller packed with tons of sensors. With built-in lipo charging over USB, your projects can be small and portable!

Sand Toy Upgrade

This is an add-on to Carter Nelson's Time Triangle Thing learn guide. It uses a similar circuit and slight code adjust to make a portable hourglass in a 3D printed case.

This uses the Feather Sense on-board accelerometer to simulate an hourglass with interactive grains of sand. This looks and feels like it’s actually been affected by gravity.

3D Printed Case

The hourglass is made up 3D printed parts that snap fit together. The electronics are housed in the base. The assembly is modular and easy to put together. Parts are 3D printed without any support material.

Project Inspiration

This was inspired by @david_proyectos See his LED hourglass build posted on instagram

Prerequisite Guides

Take a moment to walk through the following learn guides.


Mini and Small

The LED Matrices are available in 1.2in and 0.8in sized displays. The case was designed for both sizes and feature similar circuits and assembly. The LEDs come in various colors, so there are a few options to choose from.

1 x Silk Gold PLA
2.85mm diameter filament on Amazon
1 x Silk Gold PLA
1.75mm diameter filament on Amazon
Angled shot of Adafruit Feather.
The Adafruit Feather Bluefruit Sense takes our popular Feather nRF52840 Express and adds a smorgasbord of sensors...
Out of Stock
Adafruit Mini 8x8 LED matrix w/I2C Backpack- Yellow.
What's better than a single LED? Lots of LEDs! A fun way to make a small display is to use an 8x8 matrix or a
In Stock
Adafruit Small 1.2" 8x8 Yellow LED Matrix w/I2C Backpack assembled and powered on. A yellow graphic smiley is displayed.
What's better than a single LED? Lots of LEDs! A fun way to make a small display is to use an 8x8 matrix or a
In Stock
Slim Lithium Ion Polymer Battery 3.7v 400mAh with JST 2-PH connector and short cable
Lithium-ion polymer (also known as 'lipo' or 'lipoly') batteries are thin, light, and powerful. The output ranges from 4.2V when completely charged to 3.7V. This...
Out of Stock
Breadboard-friendly SPDT Slide Switch
These nice switches are perfect for use with breadboard and perfboard projects. They have 0.1" spacing and snap in nicely into a solderless breadboard. They're easy to switch...
In Stock
Angled shot of JST SH 4-pin Cable with Premium Female Sockets.
This 4-wire cable is a little over 150mm / 6" long and fitted with JST-SH female 4-pin connectors on one end and premium female headers on the other. Compared with the chunkier...
In Stock
Angled shot of ten 4-pin JST-SH connectors.
If you're a DIY enthusiast who likes to micro-manage your project's connections, here is a 10-pack of some micro JST SH...
In Stock
10 wire Silicone Cover Stranded-Core Ribbon Cable
For those who are fans of our silicone-covered wires, but are always looking to up their wiring game. We now have Silicone Cover Ribbon cables! These may look...
In Stock
USB cable - USB A to Micro-B - 3 foot long
This here is your standard A to micro-B USB cable, for USB 1.1 or 2.0. Perfect for connecting a PC to your Metro, Feather, Raspberry Pi or other dev-board or...
In Stock

The diagram below provides a visual reference for wiring of the components. This diagram was created using the software package Fritzing.

Adafruit Library for Fritzing

Use Adafruit's Fritzing parts library to create circuit diagrams for your projects. Download the library or just grab individual parts. Get the library and parts from GitHub - Adafruit Fritzing Parts.

A0 – I2C Address Change

You'll also need to change the I2C address of one of the matrices. Solder the A0 jumper on one of the LEDs matrices to set the address to 0x71. That way we will end up with these addresses for our matrices:

  • Matrix 1 = 0x70 (default, no solder)
  • Matrix 2 = 0x71

The 0x70 address matrix in on top and the 0x71 address matrix in on the bottom. Also reference the photos in the general build.

Wired Connections

  • VCC from Mini Matrix (0x70) to VCC on Mini Matrix (0x71 – A0)
  • GND from Mini Matrix (0x70) to GND on Mini Matrix (0x71 – A0)
  • SDA from Mini Matrix (0x70) to SDA on Mini Matrix (0x71 – A0)
  • SCL from Mini Matrix (0x70) to SCL on Mini Matrix (0x71 – A0)
  • VCC from Mini Matrix (0x71 – A0) to 3V on Feather Sense
  • GND from Mini Matrix (0x71 – A0) to GND on Feather Sense
  • SDA from Mini Matrix (0x71 – A0) to SDA on Feather Sense
  • SCL from Mini Matrix (0x71 – A0) to SCL on Feather Sense

Now let's get the Feather setup with CircuitPython, the necessary libraries, and the hourglass code.

Prepare the Feather Sense

Follow this guide for setting up CircuitPython on the Feather nRF52840 Sense:

Install Libraries

Follow this guide for installing libraries:

This guide has specifics on the libraries used with the LED matrices:

Make sure these libraries are in your CIRCUITPY/lib folder:

Hourglass Code

And here is the hourglass code. If you haven't already, also make sure to have copied to your CIRCUITPY folder. If you worked through the examples in the previous section, then that should already have been done.

Then save the code below as and the hourglass should start.

# SPDX-FileCopyrightText: 2020 Carter Nelson for Adafruit Industries
# SPDX-License-Identifier: MIT

import time
import board
import adafruit_lsm6ds.lsm6ds33
from adafruit_ht16k33 import matrix
import matrixsand

DELAY = 0.05 # overall update rate

# the accelo
accelo = adafruit_lsm6ds.lsm6ds33.LSM6DS33(board.I2C())

# the matrices
m1 = matrix.Matrix8x8(board.I2C(), 0x70)
m2 = matrix.Matrix8x8(board.I2C(), 0x71)

# the sand
sand1 = matrixsand.MatrixSand(8, 8)
sand2 = matrixsand.MatrixSand(8, 8)

# simple helper
def update_matrix(m, s):
    for x in range(8):
        for y in range(8):
            m[x,y] = s[x,y]

# fill up some sand
for sx in range(8):
    for sy in range(8):
        sand1[sx, sy] = True
sand1[0,0] = sand1[0,1] = sand1[1,0] = False
sand1[0,2] = sand1[1,1] = sand1[2,0] = False

update_matrix(m1, sand1)
update_matrix(m2, sand2)

updated1 = updated2 = False

while True:
    # read accelo
    ax, ay, az = accelo.acceleration
    # rotate coords
    xx = -ax - ay
    yy = -ax + ay
    zz = az

    # move grain of sand from upper to lower?
    if yy > 0 and sand1[7,7] and not sand2[0,0] and not updated2:
        sand1[7,7] = False
        sand2[0,0] = True
        updated1 = updated2 = True
    # move grain of sand from lower to upper?
    elif yy <= 0 and sand2[0,0] and not sand1[7,7] and not updated1:
        sand2[0,0] = False
        sand1[7,7] = True
        updated1 = updated2 = True
    # nope, just a regular update
        updated1 = sand1.iterate((xx, yy, zz))
        updated2 = sand2.iterate((xx, yy, zz))

    # update matrices if needed
    if updated1:
        update_matrix(m1, sand1)
    if updated2:
        update_matrix(m2, sand2)


Adjust Code

The original code from Carter's Triangle Time Thing learn guide will need to be modified slightly. The Feather Sense is mounted in a different orientation so the accelerometer coordinates will need to be changed in order to match the new position.

Look for line 42 in the code and update the following values to match the new coordinates.

# rotate coords
    xx = az - ay
    yy = az + ay
    zz = ax

Save the updated values to the file using Mu editor or your preferred text editor. Make sure the file has been updated on the CIRCUITPY drive.

Parts List

STL files for 3D printing are oriented to print "as-is" on FDM style machines. Parts are designed to 3D print without any support material. Original design source may be downloaded using the links below.

Mini or Small 8x8

The two versions feature identical file names. Choose the version you want to build.

Fusion 360 Download

The links below will launch the CAD in a browser. You can interact with the model and download files using links in the top right.

CAD Assembly

The Feather Sense, slide switch and battery are housed in the bottom base cover using tabs and built-in standoffs. The 3x spindles are secured to the base covers using 6x M3 screws. The top and bottom base feature snap fit covers.

Slicing Parts

No supports are required. Slice with settings for PLA material. 

The parts were sliced using CURA using the slice settings below.

  • PLA filament 220c extruder
  • 0.2 layer height
  • 10% gyroid infill
  • 60mm/s print speed
  • 60c heated bed

Slice with Brim

Adding a brim can help improve adhesion to the build plate. Brim adds a single layer around the base of the model. Models with small surface area touching the bed is prune to peel off especially with tall objects. Use a brim with a 3mm width when slicing the three spindles.

Design Source Files

The project assembly was designed in Fusion 360. This can be downloaded in different formats like STEP, STL and more. Electronic components like Adafruit's board, displays, connectors and more can be downloaded from the Adafruit CAD parts GitHub Repo.

LED Matrices and Backpacks

The 2x mini 8x8 LED matrices are soldered to the backpacks. The pinouts are symmetrical so they can be orientated either way.

Solder LED Matrix

Insert the pins from the 8x8 LED matrix through the top of the backpack. Ensure the LED matrix is installed correctly and flush with the PCB. A stick vise can help keep the components in place while soldering. 

Soldered LED Matrix

Check all of the pins are properly soldered.

Trim Pins

The pins are long and need to be trimmed in order to fit inside the 3D printed enclosure. Use flush cutters to shorten the pins from the LED matrix.

Jumper A0

Solder the A0 jumper on one of the LEDs matrices to set the address to 0x71. This matrix will be setup as the bottom half of the hourglass.

Ribbon Wire JST Cables

Use a piece of 4-wire ribbon cable and cut to 9cm in length. Use a second piece of 4-wire ribbon cable and cut to 6cm in length. Use the full length of 4-pin JST SH cable and remove the ends with the jumper connectors. Using wire stripper, remove a bit of insulation from each wire. Tin the wires by adding a small amount of solder. This helps to prevent the wires from fraying.


DIY Stemma QT Cable

The 4-pin JST SH connector is soldered to the 9cm long ribbon cable. Insert the connector onto the 4-pin JST SH cable. Solder each wire from the 9cm ribbon cable to the 4-pin JST SH connector.

This requires fine precision soldering, please take precautions.

Wiring LED Matrix Backpack

Use the 6cm long ribbon cable to connect the two matrices. Solder the wires from the ribbon cable and the JST cable into the LED matrix with the A0 soldered jumper. Each pin shares two wires from each cable. Use the 3D printed matrix cover as a jig to hold PCBs in place while soldering.

Wiring Second Matrix

Solder the wires from the 6cm long ribbon cable to the pins on the second LED matrix (with no soldered jumper). Use the colored wires to reference the connections. Ensure connections are similar with VCC to VCC, GND to GND, SCL to SCL and SDA to SDA. 


Slide Switch Wiring

Use a 2-wire ribbon cable and cut to 5cm in length. This will connect the slide switch to the Feather Sense.

Solder Switch Wire

Remove one of the the pins on either far left or right but not the middle. Trim the remaining pins short so they're half their length. Solder the 2-wire ribbon cable to the remaining pins on the slide switch.

Connect Switch to Feather

Solder one wire from the switch to the EN pin on the Feather Sense. Solder the second wire from the switch to the GND pin on the Feather Sense. These connections will fit best in the enclosure when they're soldered from the bottom of the PCB.

Test Switch and Battery

Connect the 400mAh battery to the Feather Sense. Use the slide switch to power the Feather Sense on and off. The NeoPixel should power on green with the CircuitPython code loaded on board. 

Connect Matrices to Feather

Solder the 9cm long ribbon cable to the pins on the Feather Sense. Connect 4-pin JST SH cables together. Ensure the connection are correct. Make the following connections.

  • SDA from Matrix to SDA on Feather Sense
  • SCL from Matrix to SCL on Feather Sense
  • VCC from Matrix to 3V on Feather Sense
  • GND from Matrix to GND on Feather Sense

Test Circuit

Use the slide switch to power on the LED matrices.

Matrices Enclosure

Insert the 4-pin JST SH cable from the matrices through one of the holes on either side of the enclosure. Reference the photo for correct  placement. Check to ensure the top and bottom matrices are correctly positioned.

Install Cover

Place the cover with the matrices installed over the enclosure. Position wiring so it's fully inside the case and it does not get kinked. Firmly press the cover into the case to snap fit shut.

Secure Feather Sense and Switch

Insert the Feather Sense into the bottom base at an angle. Fit the PCB under the clips and fit mounting holes into the standoffs. Insert the slide switch at an angle into the built-in holder. 

Install Case to Bottom Base

Orient the case with the cutouts on the bottom base. Fit the case into the bottom base by press fitting snaps.

Secure Battery

Use a piece of double sided tape or mounting tack to secure the 400mAh battery to the bottom base.

Installing Spindles

The three spindles are secured to the top and bottom covers using M3 x 6mm long machine screws. They're symmetrical and can be installed in either direction.

Securing Spindles

Place one of the spindles onto the bottom covering that goes onto the top base. Line up the mounting holes and insert screw. Fasten tightly.

Secured Spindles

Repeat process for the other two spindles. Ensure the spindles are installed onto the correct side of the cover. Reference photo for correct placement.

Install Matrix Case

The matrix enclosure is press fitted into the covering that goes onto the bottom covering that goes onto the top base.

Bottom Cover – Top Base

The shape cutout in the center of the covering lines up with the end of the matrix enclosure. Firmly press the case through the covering so surfaces are flush.

Top Cover – Bottom Base

Insert the 4-pin JST cable from the matrix through the center hole of the top cover that goes onto the bottom base.

Install Cover to Matrix Case

Fit the end of the matrix case through the center hole of the top cover. Ensure the 4-pin JST cable is through the hole and accessible.

Secure Cover to Bottom Base

Insert and fasten three M3 x 6mm long machine screws to secure spindles to the top cover.

Connect Matrix to Feather

Grab the cable from the matrix and plug it into the JST cable on the Feather Sense. Double check the assembly is correctly installed.

Install Bottom Base

Fit the top cover onto the bottom base with the cut outs lined up properly. Firmly press edges together to snap fit shut.

Top Base

Install the top cover to the top base. The top base is symmetrical so it can be installed in either direction.

Install Top Base

Lastly, place the top base over the bottom cover and firmly press together to snap fit shut.

Final Build

And there we have it! Your LED matrix hourglass is assembled and ready for testing. Use the switch to power the Feather on and off.

When the battery is low, turn off the project and recharge the battery using a micro USB cable.

This guide was first published on Jul 07, 2020. It was last updated on Jul 07, 2020.