Christmas fun for makers
Maker Christmas
Make your own Christmas music box with a microcontroller, servomotor, NeoPixel LED ring, and mini-MP3 player.
Music boxes and Christmas pyramids are among the top sellers in Germany during the Advent season. Expensive, hand-carved items can fetch four-figure sums, whereas cheap imitations sell for EUR20 (~$17). Christmas pyramids are often powered by the heat of candles, and the cheaper ones in particular have such an unfavorable candle-to-propeller ratio that the pyramid will not turn without mechanical help. Music boxes are driven by fragile springs, but the constant need to rewind them spoils the fun.
My idea of building a music box of my own design was born from these frustrations. In terms of the electronics, you do not need many components. The following sections are intended to give you some ideas for your own projects; the parts used in this example can easily be replaced by whatever delving into the depths of your lumber box reveals. The only important elements in this project are light, motion, and music.
Controls
To control the project, I used a Trinket M0 microcontroller [1] by Adafruit (Figure 1), which runs CircuitPython, a minimalist Python that supports a wide range of peripherals with its many libraries. The price of the controller is in the same range as a Pi Zero, including an SD card, but it is easier to put into operation because you do not need to install and configure an operating system.
Another advantage of a microcontroller is that you do not have to boot it, and you can simply switch it off without damaging the installation. The biggest advantage, though, is the CircuitPython support. The examples offered here illustrate how little code is needed to implement your ideas. Independently, the project could also be implemented with a Pi Zero, but some tweaks would be necessary at various points, such as the power supply.
Let There Be Light
In this project I use LEDs – more precisely, NeoPixel LEDs [2] – to create the illumination effects. NeoPixel LEDs are available in all shapes and sizes, from long strips through rings and arrays to individual LEDs. The components already contain the driver chips, which make them a bit more expensive than normal LEDs, but make controlling the LEDs far simpler.
NeoPixels normally require 5V. Three connections are all you need: supply voltage, ground, and data. If the cables are short and the number of pixels is low, 3.3V might be sufficient for the power supply and control. The maximum brightness is reduced a little, but because the LEDs are very bright anyway, the low voltage doesn't matter in practical terms. Regardless of the selected voltage, it is important to check that the NeoPixels do not overload the voltage source. The Raspberry Pi's 3.3V pins are not designed to deliver high currents. The Trinket's 3.3V rail has fewer problems: The built-in converter outputs 500mA.
I chose to use a 24-pixel RGBW LED ring (Figure 2). This device could easily be supplied with 3.3V from the Trinket M0 and controlled directly. The power consumption with the LEDs turned down is about 60mA maximum. The LED ring is the most expensive single component in the project ($17/EUR21). When soldering the cables, avoid creating a solder bridge to the adjacent LEDs.
In the minimal application program (Listing 1), the neopixel library for CircuitPython (imported in line 3) expects the code in the lib/
subdirectory. However, the library has a bug: When initializing the object (lines 8-12), you have to specify the pixel_order=neopixel.GRBW
argument, even though the value you are passing in is the default.
Listing 1
NeoPixel Control
01 import time 02 import board 03 import neopixel 04 05 pixel_pin = board.D2 06 num_pixels = 24 07 08 pixels = neopixel.NeoPixel(pixel_pin, 09 num_pixels, 10 pixel_order=neopixel.GRBW, 11 brightness=0.05, 12 auto_write=False) 13 14 def colorwheel(pos): 15 if pos < 0 or pos > 255: 16 return (0,0,0,0) 17 if pos < 85: 18 return (255 -- pos * 3,pos * 3,0,0) 19 if pos < 170: 20 pos -= 85 21 return (0,255 -- pos * 3,pos * 3,0) 22 pos -= 170 23 return (pos * 3,0,255 -- pos * 3,0) 24 25 def rainbow(wait): 26 for j in range(255): 27 for i in range(num_pixels): 28 rc_index = (i * 256 // num_pixels) + j 29 pixels[i] = colorwheel(rc_index & 255) 30 pixels.show() 31 time.sleep(wait) 32 33 while True: 34 rainbow(0.1)
The program generates rainbow colors across all pixels and rotates more or less slowly, depending on the wait
parameter (lines 25 and 31). CircuitPython does not support interrupts, so if you want to connect an additional button to the Trinket M0 (e.g., for an on/off switch or to switch between effects), you have to query the switch at a suitable point. In the example, this would be either inside the while
loop (lines 33-34) or before line 31.
In Motion
A continuous rotation servomotor rotates the music box. In contrast to stepper motors, which support precise positional control, only speed and direction can be specified for rotating servos. In this project, I use a Fitec FS90R [3] ($5, EUR6; Figure 3), which is available from various vendors.
Again, a few lines of code are all you need for control (Listing 2). First, a pulse-width modulation (PWM) object is created in line 6, along with a control object for the motor in line 7. The throttle
parameter controls the direction (sign) as well as the speed and expects values between -1
and 1
. Depending on the model and power supply, the motor does not stop for a value of
. In my lab, it stopped for values between 0.05
and 0.10
.
Listing 2
Servomotor Control
01 import time 02 import board 03 import pulseio 04 from adafruit_motor import servo 05 06 pwm = pulseio.PWMOut(board.D0, frequency=50) 07 my_servo = servo.ContinuousServo(pwm) 08 my_servo.throttle = 0.01 09 10 while True: 11 time.sleep(1)
Without a while
loop, the program ends and the microcontroller resets the hardware – hence lines 10 and 11. You can start, stop, or change the speed of the motor within this loop, but for this project, no further support after startup would be practical, because you will be manipulating the LEDs in the while
loop of the main program (Listing 1).
Buy this article as PDF
(incl. VAT)
Buy Linux Magazine
Subscribe to our Linux Newsletters
Find Linux and Open Source Jobs
Subscribe to our ADMIN Newsletters
Support Our Work
Linux Magazine content is made possible with support from readers like you. Please consider contributing when you’ve found an article to be beneficial.
News
-
Juno Computers Launches Another Linux Laptop
If you're looking for a powerhouse laptop that runs Ubuntu, the Juno Computers Neptune 17 v6 should be on your radar.
-
ZorinOS 17.1 Released, Includes Improved Windows App Support
If you need or desire to run Windows applications on Linux, there's one distribution intent on making that easier for you and its new release further improves that feature.
-
Linux Market Share Surpasses 4% for the First Time
Look out Windows and macOS, Linux is on the rise and has even topped ChromeOS to become the fourth most widely used OS around the globe.
-
KDE’s Plasma 6 Officially Available
KDE’s Plasma 6.0 "Megarelease" has happened, and it's brimming with new features, polish, and performance.
-
Latest Version of Tails Unleashed
Tails 6.0 is based on Debian 12 and includes GNOME 43.
-
KDE Announces New Slimbook V with Plenty of Power and KDE’s Plasma 6
If you're a fan of KDE Plasma, you'll be thrilled to hear they've announced a new Slimbook with an AMD CPU and the latest version of KDE Plasma desktop.
-
Monthly Sponsorship Includes Early Access to elementary OS 8
If you want to get a glimpse of what's in the pipeline for elementary OS 8, just set up a monthly sponsorship to help fund its continued existence.
-
DebConf24 to be Held in South Korea
Busan will be the location of the latest DebConf running July 28 through August 4
-
Fedora Unleashes Atomic Desktops
Fedora has combined its solid distribution with rpm-ostree system to make it possible to deliver a new family of Fedora spins, called Fedora Atomic Desktops.
-
Bootloader Vulnerability Affects Nearly All Linux Distributions
The developers of shim have released a version to fix numerous security flaws, including one that could enable remote control execution of malicious code under certain circumstances.