Pi-based multi-prop trigger for animatronics, Part 2

Back in March I wrote about a Pi-based controller for multiple Halloween props. As I go the props ready this year, I realized three things: 1) I wanted to change the routine from what I planned, 2) The way I needed to connect this particular set of props was different than what I’d been planning and 3) it turns out I couldn’t use an electromechanical relay board to react to the trigger signal from the Pi to one of the skeletons, because it holds open too long. So, back to the drawing board, as well as desoldering and resoldering.

My setup for this year includes two skeletons talking to one another. One is a simple talking pose-and-stay type of skeleton, with light up eyes and a moving jaw driven by a motor. The other is a talking and moving skeleton prop called Grim. Besides wanting movement to trigger them, I needed to be able to provided custom audio phrases for them to say to one another.

Talking Skeleton

The talking skeleton [insert photo] uses a motor to drive the jaw movement, and has light up LED eyes. In order to allow for custom audio, I disconnected the built in sensor and sounds and connected a commercial audio controller called a Jemmy Talk. The Gemmy Talk takes line level audio input and sends out voltages to move the motor. It also has a pass through for the audio, so that you can send line level output to an amplifier. I don’t use this latter feature in my set up. I use a DFPlayer MP3 player as my audio source. It has both a line level output, which I feed to the Jemmy Talk, and amplified audio that I feed directly to the speaker built into the skeleton. The board with the DFPlayer is also where the power is supplied, through a barrel jack connector to a 5V supply. The button switch on the board is to test things without requiring an external trigger signal. The two 3-pin connectors on the board are not used. The three boards are shown in the picture. Besides the Jemmy Talk and the board with the DFPlayer, the third board receives the triggers from a Raspberry Pi (see “Controller,” below).

Picture showing the audio source and controls for the skeleton, showing the Jemmy Talk board, the board with the DFPlayer MP3 player, and the board with input from an external controller and Darlington array. All are wired together as they are when in use.

The audio source and controls for the skeleton, showing the Jemmy Talk board, the board with the DFPlayer MP3 player, and the board with input from an external controller and Darlington array.

The circuit board on the bottom will receive the triggers from a Raspberry Pi (not shown) and features a Darlington ULN2003 transistor array chip that acts as a set of relays to signal the DFPlayer to play the audio and also to turn the skeleton’s eyes on. I had originally used an electro-mechanical relay rather than the Darlington array, but the MP3 player requires that the button press to play the audio be short, and the relay held closed too long when triggered. The MP3 player uses a short drop to ground to signal to play the next track, which is what I needed, while a longer drop on the same pin signals the player to turn up the volume. Had I known that I would be using the Darlington array from the start, rather than a separate relay board, I could have fit everything on just one, rather than two, boards.

If the skeleton was like many, with simple LED eyes, I could have used the Jemmy Talk to control them as well, but it doesn’t. So I kept the Try Me wires connected to trigger the eyes to go on. That is what the second trigger on the Darlington is for. That means that I needed two signals from the Pi, one to turn on the audio and one to light the eyes, but this gives me more flexibility for the future. Here’s a picture of the final circuits in a small project box I printed for the project:

Grim

The Grim prop was modified by adding a Grim Talker board from the same source as the Jemmy Talk. Once that was installed per the directions, I just needed to put the correct new audio file on the SD card that goes into the Grim Talker (no external MP3 player needed) and determine how to trigger it. It can be triggered to activate by either the sensor built into the original Grim prop, by cycling the power on and off, or by a Try Me button switch connected through a 1/8″ MONO cable jack. When triggered, the audio and motion routine starts. The audio will play through completion, but the motion will stop once it’s routine (about 30 seconds) ends. If the audio is longer (as in my case) and you retrigger the prop before the audio ends, the motion will start up again. This is what I wanted to do.

Cycling the power wouldn’t do what I wanted, as it would kill the audio. I didn’t want to mess with the built in PIR sensor, as I may want to use it in the future. And I needed to coordinate Grim with the other skeleton. So that left the try me switch. So the multi-prop controller that I put together (a modification of what I described in the Pi-based controller for multiple Halloween props write-up, uses another Darlington to act as a switch that closes to trigger the prop.

Controller

Pictorial diagram of the controller. PI on the left has connections to the other board for power, one connector to a 3 pin female header on the other board for input from a PIR, and four GPIO output connections (one to a 3 pin header for a PIR type of controlled prop, two to a 3-pin connector for either a PIR control or one needing two separate signal inputs, and one that goes to the input of a ULN2003 Darlington on the board, which is connected to close a connection when triggered.

Raspberry Pi based multi-prop controller

In order to control multiple, coordinated, props from a single motion sensor, I put together a simple circuit that controls up to three props, of a couple of different types. A PIR provides input to the Raspberry Pi, which then sends output signals for up to three props. One output simply closes a switch, and it is good for triggering props through their “try me” button wires (replacing the button / switch). For this, the trigger output from one of the GPIO pins on the Pi triggers a relay in a Darlington. This is a bit of an overkill, as I’m only using one of the eight channels on the Darlington, but it’s cheap, easy to use, and works.

Another GPIO pin sends and output voltage to the sensor wire in a 3 pin servo connector. The grounds also link the prop to the controller to provide a common ground. This works for any prop set up to look for input from a PIR or similar sensor providing a positive low voltage signal. What would normally be the voltage source on a servo connector is left unconnected, as it’s not needed to power anything.

Finally, two other GPIO pins send output to another 3-pin connector, using what would normally be the signal and voltage lines on a servo connector. This is for the talking skeleton as described above, with one signal to start the MP3 audio player and the other to control the eyes. Again, the ground is connected to ensure a common ground. This connector could also be used to simply control a prop that only needs a single signal, rather than two, providing flexibility.

The python controller program for this year is really quite simple:

from gpiozero import DigitalOutputDevice
from gpiozero import MotionSensor
import time

skel_talk = DigitalOutputDevice(23)
skel_try_me = DigitalOutputDevice(24)
grim_trigger = DigitalOutputDevice(25)
pir = MotionSensor(15)

while True:
    pir.wait_for_motion()
    print("motion detected")
    skel_talk.on()
    skel_try_me.on()
    grim_trigger.on()
    time.sleep(0.2)
    skel_talk.off()
    skel_try_me.off()
    grim_trigger.off()
    time.sleep(30)
    print("waited 30 seconds")
    grim_trigger.on()
    time.sleep(0.2)
    grim_trigger.off()
    time.sleep(50)
    print("ready to trigger again")

The program uses the gpiozero library for interfacing with the Pi’s GPIO pins. Three pins are used for outputting signals: named skel_talk to trigger the skeleton’s audio, skel_try_me to trigger the relay to close the skeleton’s try me connection, and grim_trigger to send a trigger signal to the Grim prop. These are all defined as simple DigitalOutpuDevice pins. There is one input pin, named pir, which is defined as a MotionSensor input.

The program is an endless loop which waits for the PIR sensor to be set off. When that happens, the three output triggers are both set high (True) for 0.2 seconds and then set back off. Then the program sleeps for 30 seconds while the Grim motion is running, then the grim_trigger is again set high again for 0.2 seconds to trigger the motion to restart (the audio, which is about 1 minute long, is still running). Finally, the program waits 50 seconds. The audio and motion will continue for approximately 30 of these seconds, with the additional 20 seconds being a dead time so that the props don’t immediately retrigger. The print statements are there simply for initial debugging. I used Crontab to set the script to autorun in the background upon startup. I need to modify the script so that once triggered, it also periodically closes the try me switch on the talking skeleton. At present, the eyes only light for a short time at the start of the dialog.

Results

Here’s the two circuits, in their circuit boxes, and then a video

Photo of the electronics for the skeleton in one project box and the pi-based multi-prop controller in a second project box. The skeleton controller has a Jemmy Talk circuit board, a board with the MP3 player, and a third board. The prop controller has a raspberry pi and a board with a Darlington array, source for power, and several female 3-pin headers.

The electronics for the talking skeleton on the left and the Pi-based multi-prop controller on the right.

of the final result in operation. Unfortunately, it’s not a great video clip, but it does show the two skeleton props talking back and forth in a short excerpt from their longer dialog. An mentioned above, I need to add a line or two to the script to periodically retrigger the eyes of the smaller skeleton, so that they stay lit during the whole dialog.

It took more effort than I originally thought it would, partly due to faulty planning on my part, but I think it all came together nicely.

Crowd-Sourced List of Python Resources Related to Halloween

An AI-generated image. bats fly overhead, with a full moon visible. On the left is a laptop showing some computer code. In the middle is a pumpkin with the Python logo carved in it. There is also a black cat with green glowing eyes. If you look at this blog, you’ll quickly see that many of my projects relate to Halloween. I don’t know if this is a good, bad, or dumb idea, but as I was thinking about my use of Python for controlling Halloween props, I had the thought that it might be nice to have and share a crowdsourced list of python-related resources relating to Halloween, such as useful libraries (e.g., pyAudio, various libraries for using the GPIO pins on a Raspberry Pi), complete software packages (e.g., my own ChatterPi), or even Halloween-themed games written with Python. So, with some help from ChatGPT, I’ve put together a Google sheet, Python Resources for Halloween,  with some pre-populated content that anyone can view, along with a Google Form, Submit Python Resource for Halloween, where anyone can submit additional resources for inclusion.

The submissions are moderated, so they won’t show up immediately in the resource sheet. If you have anything to propose adding, please do so using the Google Form. If you have any other feedback, I welcome it as a comment on this post.

Pi-based multi-prop trigger for animatronics, Part 1

UPDATE: My setup changed between writing this and Halloween 2025. Updates and complete description, including revisions are in my later post.

Next Halloween, my setup will include three coordinated skeletons performing together (probably doing “King Tut“). I want to use a single PIR motion detector to trigger three different props at different offsets from the original trigger. And some of the props can only speak or move for short amounts of time, so for a longer performance, they need to be repeatedly triggered. To do this, I have a PIR providing input to a Raspberry Pi Zero W. A python program running on the Pi then sends brief output trigger voltages individually to each of the props, according to the preset schedule for the routine. This same approach could easily be modified to trigger 2, 4, 5, or more coordinated props from a single start trigger. The hardware setup is very simple, and is shown in the figure.

Wiring diagram for the multi-prop trigger. The left is a Raspberry Pi Zero W with the pins enlarged, and the right is a breadboard. The breadboard has a barrel jack for power (that also is wired to the Pi). There are four 3 pin female headers on the breadboard. One is for the PIR sensor, and has all three connections wired. The other three are to send signals to three props. These have the ground and signal wires connected.
Wiring diagram

Power is provided via the barrel jack on the prototype board. This is also what powers the Pi. Their are four 3-pin female headers on the board. The one on the left is for the PIR sensor input. It has the power and ground connections, and the signal wire is an input that goes to GPIO pin 15 on the Pi. The other three headers are to go out to the three props. The grounds are connected so that the prop controls and this trigger share a common ground. The signal connections are outputs from GPIO pins 23, 24, and 25. There is no need for power for these connections. 

In order to test the hardware, I rigged up one LED to each of the three signal outputs, put a resistor in to avoid burning out any of the LEDs, and linked the grounds. The test setup is shown below below:

Picture showing a Raspberry Pi Zero W on the right, with soldered connections to a soldered breadboard with a 3 pin header that a PIR sensor is plugged into, and three other 3 pin headers that connect to a solderless breadboard with three LEDs connected.

Test setup to make sure the hardware works and that I got the soldering correct.

I used the GPIO Zero library to write a simple test script for this test setup:

from gpiozero import LED
from gpiozero import MotionSensor

myLED1 = LED(23)
myLED2 = LED(24)
myLED3 = LED(25)
pir = MotionSensor(15)

while True:
    if pir.wait_for_motion():
        print("motion detected")
        myLED3.off()
        myLED1.blink(1)
        myLED2.blink(2)
        pir.wait_for_no_motion()
        print("no motion")
        myLED1.off()
        myLED2.off()
        myLED3.blink(3)

This has the pi wait until the PIR detects motion. Then it begins blinking the first 2 LEDs at different rates. When motion stops, those two LEDs are turned off and the third LED begins to blink. This cycle then repeats until the user hits CTRL-C to stop the test script.

Black project box without the top. It has a large round opening where the barrel jack for power resids, and a large rectangular opening where the micro SC card can be accessed. Inside are the Pi Zero W and the solderable breadboard.

Completed electronics in project box

Completed project box with electronics inside. The cover is on to top. You can see the solderable breadboard with headers through the top cutout.

Completed project box with electronics inside and lid on the top

The circuit is mounted in a custom 3d printed project box with slots for the power, sensor, and output wires, as well as a slot for accessing the Pi’s micro SD card. I designed the box using TinkerCad. I also 3d printed the standoffs, and just used hot glue to glue the Pi and the breadboard in place. I put in large holes so that it would be easy to plug and unplug the connectors and also get my fingers in to insert or remove the micro SD card. The top has a large cutout to make it easy to access the 3-pin headers. The finished hardware is shown in the figures on the right.