Making the Fox Head

I'd never made a puppet head before but I'm pretty crafty and during my cosplay days I'd discovered the material Worbla, which is a thermoplastic that can be easily shaped when heated and has adhesive on one side that is also heat activated. When it cools it retains its shape and can be reheated over and over again. I've previously used it to make some pretty cool armor and uniquely shaped props so I thought it would be just what I needed.

That said, I always do better when I have a shape to place the Worbla over, so I headed over to thingiverse.com to see if there were any fox skulls 3D print designs that looked promising.

I found a Fennec Fox Puppet head base created by Tioh:

Created by Tioh

I scaled it down using my 3D printer slicer software Flash Print to be about 3-4 inches wide and sent it off to print. After a successful print, I began to cut out small pieces of Worbla and began applying it to the outside of the print with the shiny side facing out as this is the adhesive side that we'll need later to stick the fur to:

IMPORTANT: Heat the Worbla pieces away from the 3D print, as the PLA will start to warp when too much heat is applied.

After the 3D skull was completely covered with Worbla I cut out a section of faux fur and shaved it down using a beard trimmer. Don't go as short as you want the finished project as you'll do some more trimming once everything is assembled, but getting some of the bulk of the fur removed early on is helpful for attaching it to the 3D printed skull. This was SUPER messy, do this outside if you can.

I then traced lines on the back radiating out from areas I knew it would have to curve around the shape of the skill, generally radiating from the bridge of the nose. Using a utility knife, I carefully cut the lines.

Make sure to only cut through until the base of the fabric separates, do not chop any of the fur on the other side.

I then heated the Worbla on the 3D printed skull and began sticking the fur to the activated adhesive. This part is tricky because your PLA will also get warm enough to start to warp so as it cools make sure you're helping the plastics reform to the right positions. You may need to cut a few extra lines, trim off excess or otherwise manipulate the fabric to be where you need it.

I also had to cut a few extra few extra pieces that I did not trim the fur on that would go behind the ears so it was a smooth transition when I eventually create a body for the fox.

This wasn't an exact science, do what you have to do to make it look right.

I then trimmed out the eye shape with sharp pair of embroidery scissors.

The ears were created using trimmed down fur of the same color as the head and also some trimmed down white fabric. I didn't capture photos of the process but here are the step I followed:

1. Cut out a triangle shape out of cardboard and cut a slightly curved line along the bottom that follows the general slop of your fox head where the ears will be places.

2. Use this as a template to cut out the Worbla, make sure to flip the template over for the second one, as you need ears sloping in opposite directions.

3. Cut out fur slightly bigger than your template.

4. Cut a wooden dowel about 2 inches long, The dowel should be around 1/4 inch thick or less but don't go too thin.

5. Heat your Worbla to the point where it feels stick on both sides and put your dowel so it's 1/2 inch from the bottom of the ear in the center of your ear. Place your normal fur color to one side, and the white fur to dowel side, press firmly until cooled.

6. Re-heat and gently shape the ear so it has a small rounded fold around the edges and gently curve over all.

7. Repeat for the other ear.

8. IMPORTANT: WAIT TO DO THIS STEP UNTIL YOU'RE READY TO MOUNT YOUR SEVOS. See further down in the instructions. Drill holes in the head the size of your dowel where the ears should be placed and insert ears. They should swivel freely without resistance when you try to move them.

Next I made eye lenses so the eyes would have depth and reflection. I used the oval shape from this mold on Amazon and some clear hard cast resin. I then attached the lenses using some Worbla (always save your scraps!).

And that's it you've got a fox head ready for some tiny screens and servos! Along the way your head might have gotten warped. Don't be afraid to re-heat it and shape it back to how it's supposed to look.

Programming and Mounting the Eyes

This section primarily a repost of this project I did earlier but does have some new information related to mounting the eyes on the skull at the end.

Before You Get Started

I started with absolutely ZERO experience with Linux, Raspberry Pi, and SPI devices. Here’s some things I learned along the way that may be helpful to a beginner like me:

Helpful commands:

cd ~ will take you to the home directory

cd.. will take you one folder back

ls will list files in the folder you’re currently in

If you veer off this tutorial to troubleshoot or find other options please note that anything you find with OMXplayer will no longer work. It was depreciated a year or so ago and it's core library is not available to download. This also means that the Adafruit Video Looper tutorial does not work anymore. I went down a ton of frustrating rabbit holes that were all reliant on the OMXplayer either obviously or not so obviously before cobbling together a solution with the VLC player.

Important Notes

This will only work with a 32-bit version of the Raspberry Pi OS with desktop and was last tested on 12/9/2023 with Bullseye 11.

Wire Your LCD Screen

Wire your LCD screen to your Pi according to the wiring diagram here:

https://www.waveshare.com/wiki/1.14inch_LCD_Module

Image Raspberry Pi V

1. Download and install the Raspberry Pi Imager: https://www.raspberrypi.com/software/

2. Launch Program and install Pi Os with Desktop

I used Bullseye 11 (12/5/2023 version listed in the Imager)

3. I like to pre-configure settings and recommend you do so as well:

Set username and password, configure wireless lan, and set locale settings:

Enable SSH incase you ever need it:

Boot and Setup Your Pi

Put your micro SD card into your Pi, connect a monitor, keyboard and mouse combo (or use a USB hub to use two separate devices), and lastly power

1. Connect Your Pi: Put your micro SD card into your Pi, connect a monitor, keyboard and mouse combo (or use a USB hub to use two separate devices), and lastly power

2. Allow the Pi OS to fully boot and open the Desktop

Connect via SSH

1. On your PC computer go to the search bar and type CMD to open a Command Prompt window

2. Ping Your Pi: Type: ping raspberry.pi You should get results back from the ping, if not, try waiting a minute or two, your pi may still be loading. If that still doesn’t work, make sure your Pi is not in the Looper program

3. SSH into your Pi, type: ssh pi@raspberrypi Login is the same as previous steps

You are now connected and can continue setting up your Pi from the PC desktop in the Command Prompt window!

Enable SPI

1. Enter config settings by typing: sudo raspi-config

2. Choose Interfacing Options -> SPI -> Yes to enable SPI interface

3. Exit

Configure Pi for LCD Screen

These steps are directly from https://www.waveshare.com/wiki/1.14inch_LCD_Module with minor modification for clarity. Enter each of these commands and let finish before moving to the set.

1. Install BCM2835 Libraries:

wget http://www.airspayce.com/mikem/bcm2835/bcm2835-1.71.tar.gz

tar zxvf bcm2835-1.71.tar.gz

cd bcm2835-1.71/

sudo ./configure && sudo make && sudo make check && sudo make install

2.Install WiringPi libraries

cd ~

sudo apt install wiringpi

For Raspberry Pi systems after May 2019 (earlier than that can be executed without), an upgrade may be required:

wget https://project-downloads.drogon.net/wiringpi-latest.deb

sudo dpkg -i wiringpi-latest.deb

gpio -v

(Run gpio -v and version 2.52 will appear, if it doesn't it means there was an installation error)

3. Install Python Libraries

sudo apt-get update

sudo apt-get install python3-pip

sudo apt-get install python3-pil

sudo apt-get install python3-numpy

sudo pip3 install RPi.GPIO

sudo pip3 install spidev

4.Test Your Screen, download examples:

d ~

sudo apt-get install unzip -y

sudo wget https://files.waveshare.com/upload/8/8d/LCD_Module_RPI_code.zip

sudo unzip ./LCD_Module_RPI_code.zip

5.Compile and Run Code

cd LCD_Module_RPI_code/RaspberryPi/

cd c

Sudo make clean

sudo make -j 8

cd ~

6.Run an Example

cd LCD_Module_RPI_code/RaspberryPi/python/example

ls -l

sudo python3 1inch14_LCD_test.py

Your screen should now be displaying a test image! This is also where you'll use a different code from waveshare to test is your screen size is different than mine.

Install VLC Player (do this BEFORE setting up FBCP)

Install VLC Player (do this BEFORE setting up FBCP)

In your open Command Window, ensure your Pi is entirely up to date, type:

1. In your open Command Window, ensure your Pi is entirely up to date, type:

cd ~

sudo apt update

sudo apt upgrade

2. Install VLC, type:

sudo apt install -y vlc

Add Your Video Your Pi via SCP

This requires you to be able to connect to the Raspberry Pi from your PC. Your Raspberry Pi OS install at this point already has a folder called Videos, so we’ll be using that destination for your files.

1. Move your video file to your desktop on your PC

2. Open a Command Prompt window: Click your start bar search and type cmd to open a Command Prompt on your PC

3. Connect to your Pi via SSH, type:

ssh pi@raspberrypi.local

Type yes if promoted and then login with your pi password.

4. Open a second command prompt window and send files via SCP, type:

cd desktop

scp filenameofvideo.mp4 pi@raspberrypi.local:~/Videos

Your result should show your file name and the a 100% indicator. Repeat as many times as needed for whatever videos you’d like to have play on startup!

Make VLC Autostart, Full Screen and Play from your Videos Folder

Make VLC Autostart, Full Screen and Play from your Videos Folder

Instructions were taken from here with slight modification: https://forums.raspberrypi.com/viewtopic.php?t=17051

IMPORTANT: Do not use sudo on any of these commands or it will set permissions in a way that the pi user that is automatically logged in will not be able to use it and it will not autostart.

1. Create an Autostart directory, type:

mkdir /home/pi/.config/autostart

2.Create a.desktop file with the instructions for autostarting VLC and looping the video with no video title, type:

nano /home/pi/.config/autostart/autovlc.desktop

Add the lines:

[Desktop Entry]

Type=Application

Exec=/usr/bin/vlc -f -- random --loop --no-video-title /home/pi/Videos

Press CTRL X and type Y for yes when asked to save

4. Reboot your Pi, type:

Sudo reboot

Make sure your Pi is hooked up to a monitor, you should be able to see the VLC player load, full screen, play your playlist and loop back to the start of the playlist when at the end! Important: Your video will not yet be playing on your small LCD screen, you will need to complete the FBCP Porting steps.

FBCP Porting

This will mirror your HDMI output to your SPI LCD. These steps are from: https://www.waveshare.com/wiki/1.14inch_LCD_Module

Important: If following the directions directly on the waveshare page linked above, the script function would not work for me and I had to use the manual instructions to finish setup. I believe this has something to do with the newer Pi OS.

1. Install the drivers, type:

cd ~

sudo apt-get install cmake -y

wget https://files.waveshare.com/upload/1/18/Waveshare_fbcp.zip

unzip Waveshare_fbcp.zip

cd Waveshare_fbcp/

sudo chmod +x ./shell/*

2. Remove the conflicting DRMVC4 statement, type:

sudo nano /boot/config.txt

Delete this section:

CTRL X to exit, Y to save

3. Reboot the pi, type:

sudo reboot

4. Configure, compile and run, type:

cd Waveshare_fbcp/

mkdir build

cd build

sudo cmake -DSPI_BUS_CLOCK_DIVISOR=20 -DWAVESHARE_1INCH14_LCD=ON -DBACKLIGHT_CONTROL=ON -DSTATISTICS=0 ..

^^ (from sudo to =0 is all one line, make sure to copy the whole thing)

sudo make -j

sudo ./fbcp

This is another place where you'll use different code if your screen is a different size than mine. Change the line that starts with sudo cmake with the appropriate one from the waveshare website linked above.

5. Setup this functionality to start automatically when you boot your Pi, type:

sudo cp ~/Waveshare_fbcp/build/fbcp /usr/local/bin/fbcp

sudo nano /etc/rc.local

Add fbcp& before exit 0.

Important: You must add "&" to run in the background. Otherwise, the system may not be able to start.

Important: My video files are already formatted for my screen resolution when I create them. Yours may not be be, so if things look wonky, check out the final steps in the waveshare guide for setting the display resolution: https://www.waveshare.com/wiki/1.14inch_LCD_Module#Set_the_Display_Resolution

Add a Second SPI LCD

1. Splice together the wires of both screens and put a male pin connector on the end

2. Plugin the wires to the Pi exactly how you did previously

When your Pi boots, it should be playing the same video on both screens.

Creating the Eye Animations

I don't have any experience with animation software so I just used Canva and used the slide transition Match & Move to make several videos where the eyes either blinked or moved left/right. I also created a few videos where the eye didn't move that were just specific durations such as 5 seconds and 10 seconds. Having still animations that the playlist. I've included my files where the canvas is set to the right size for the resolution of the eyes.

Mount the Eyes

First put globs of mounting putty on front and back corners of your screens. GENTLY get your screens into position resting flat against the lenses on the inside of the skull. If you press too hard your screens WILL break.

I recommend having your screens on with the animation playing so you can see where you're positioning your eyes. When you're happy with the placement carefully place mounting tape all around the edges of the back of the screen and the inside of the skull.

Programming and Mounting the Servos

This section primarily a repost of this projectI did earlier but does have some new information related to mounting and connection of the servos.

Notes: This project assumes you have Arduino IDE setup and know how to connect and write to an Arduino Uno board.

Hook Up Your Servos

The first step is to hook up your servos to your UNO. If you purchased the same servos I used from Amazon the wires are as follows:

The Uno has issues powering servos consistently at 5V and you'll be hooking up multiple servos to 5V, so I recommend using an 5V power supply.

The signal wires will connect to Uno Pins 9, 10, and 11 and the servo power and ground will connect to the power supply. ** Make sure you connect your power supply's ground to your Uno's ground**

Write Sketch and Upload the Code

Plug your Uno into your computer and open a new sketch in Arduino IDE. Copy and paste the code from the code section of this project.

#include 

//original code transcribed from Mike Theevil's video: 
//modified by Smalls on Nov 8 2023

Servo rear; //create servo object to control a servo
Servo lear; //create servo object to control a servo
Servo head; //create servo object to control a servo
// twelve servo objects can be created on most boards

void loop_rear() {
 int r1 = random(10, 90); //defines variable and sets servo step amount between 0 and 170 degrees
 int r2 = random(500, 2000); //defines variable and sets random delay 
 int r3 = random(2000, 10000); //defines variable and sets neutral random delay     

 rear.write(r1); //makes servo position random
 delay(r2); //triggers random relay
 rear.write(90); //resets servo to neutral position
 delay(r3); //triggers neutral random delay           
}

void loop_lear() {
 int l1 = random(90, 170); //defines variable and sets servo step amount between 0 and 170 degrees
 int l2 = random(500, 2000); //defines variable and sets random delay 
 int l3 = random(2000, 10000); //defines variable and sets neutral random delay     

 lear.write(l1); //makes servo position random
 delay(l2); //triggers random relay
 lear.write(90); //resets servo to neutral position
 delay(l3); //triggers neutral random delay           
}

void loop_doubleear() {
 rear.write(10); //right ear at 10
 lear.write(170); //left ear at 170
 delay(1000); //delay for
 rear.write(90); //makes servo position random
 lear.write(90); //resets servo to neutral position          
}

void loop_head() {
 int h1 = random(40, 140); //defines variable and sets servo step amount between 0 and 170 degrees
 int h2 = random(500, 2000); //defines variable and sets random delay 
 int h3 = random(2000, 10000); //defines variable and sets neutral random delay     

 head.write(h1); //makes servo position random
 delay(h2); //triggers random relay
 head.write(90); //resets servo to neutral position
 delay(h3); //triggers neutral random delay           
}

void setup() {
  rear.attach(9); //attaches the servo on pin 9 to the servo object
  lear.attach(10); //attaches the servo on pin 9 to the servo object
  head.attach(11); //attaches the servo on pin 9 to the servo object
}

void loop() {
  byte randNum = random(4); //max range of numbers
  switch (randNum) //switches between the random numbers assigned in this loop
  {
    case 0:
      loop_rear();
      break;
    case 1:
      loop_lear();
      break;
    case 2:
      loop_head();
      break;
    case 3:
      loop_doubleear();
      break;
  }            
}

Understanding the Code

Servo and Uno Circuit Diagram

How to connect the servos, uno, and power supply.

Randomized Multiple Servo Code

This code is different than the linked project above and has been calibrated to add in pauses and specific angle limitations to prevent the head from seeming uncanny in its movements.

#include <Servo.h>//original code transcribed from Mike Theevil's video: https://www.youtube.com/watch?v=1doy5nNS-cg//modified by Smalls on Nov 8 2023Servo rear; //create servo object to control a servoServo lear; //create servo object to control a servoServo head; //create servo object to control a servo// twelve servo objects can be created on most boardsvoid loop_rear() {int r1 = random(10, 90); //defines variable and sets servo step amount between 0 and 170 degreesint r2 = random(500, 2000); //defines variable and sets random delayint r3 = random(2000, 10000); //defines variable and sets neutral random delayrear.write(r1); //makes servo position randomdelay(r2); //triggers random relayrear.write(90); //resets servo to neutral positiondelay(r3); //triggers neutral random delay}void loop_lear() {int l1 = random(90, 170); //defines variable and sets servo step amount between 0 and 170 degreesint l2 = random(500, 2000); //defines variable and sets random delayint l3 = random(2000, 10000); //defines variable and sets neutral random delaylear.write(l1); //makes servo position randomdelay(l2); //triggers random relaylear.write(90); //resets servo to neutral positiondelay(l3); //triggers neutral random delay}void loop_doubleear() {rear.write(10); //right ear at 10lear.write(170); //left ear at 170delay(1000); //delay forrear.write(90); //makes servo position randomlear.write(90); //resets servo to neutral position}void loop_head() {int h1 = random(40, 140); //defines variable and sets servo step amount between 0 and 170 degreesint h2 = random(500, 2000); //defines variable and sets random delayint h3 = random(2000, 10000); //defines variable and sets neutral random delayhead.write(h1); //makes servo position randomdelay(h2); //triggers random relayhead.write(90); //resets servo to neutral positiondelay(h3); //triggers neutral random delay}void setup() {rear.attach(9); //attaches the servo on pin 9 to the servo objectlear.attach(10); //attaches the servo on pin 9 to the servo objecthead.attach(11); //attaches the servo on pin 9 to the servo object}void loop() {byte randNum = random(4); //max range of numbersswitch (randNum) //switches between the random numbers assigned in this loop{case 0:loop_rear();break;case 1:loop_lear();break;case 2:loop_head();break;case 3:loop_doubleear();break;}}

Mount Your Servos

I created mounting brackets and connectors for my servos in Fusion 360 and have attached the STL to this project.

1. Is a cross sectional bracket that will be glued to the inside of the skull under where the ears go and will hold the two ear servos.

2. Is a mounting bracket to hold the larger servo that controls the head tilt and is connected to whatever will be your spine apparatus. I designed the mounting hole to be compatible with this poseable ball socket armature, but I may swap this out for something else later.

3. Print 2 of these, they're the connectors between the small servos and the dowels extending from your fox ears.

Place the #1 cross sectional bracket where you want it in the skill, with the servo slots pointing towards the top of the head and hot glue in place.

Drill two holes in the skull slightly larger than your dowel connectors on your fox ears and lined up with where the servos will be placed and the where the connectors will extend to.

Next make sure to set your servos to 90 degrees:

In order for your ears and head to be at the right position and able to move to the left and right, you need to set your servos to be stuck in the 90 degree position, which is the middle position for your servos that can rotate between 0 and 180 degrees. By setting them to this position when you attach everything, they'll be in the "neutral" position.

Upload the following code to your Uno:

#include <Servo.h>//created by Smalls on Nov 8 2023Servo right; //create servo object to control a servoServo left; //create servo object to control a servoServo center; //create servo object to control a servo// twelve servo objects can be created on most boardsvoid setup() {right.attach(9); //attaches the servo on pin 9 to the servo objectleft.attach(10); //attaches the servo on pin 9 to the servo objectcenter.attach(11); //attaches the servo on pin 9 to the servo object}void loop() {right.write(90); //resets servo to neutral positionleft.write(90); //resets servo to neutral positioncenter.write(90); //resets servo to neutral position}

Advice I've gotten from others who have made companion bots is that you need to make it so some of your more common parts, like servos, can be easily replaced. To make sure this was possible I used hot glue to attach the dowel connectors to the servo heads, and mounting putty to place the servos into their slots.

Fill the dowel (wider) end of the dowel connectors with got glue, wiping away any excess from the top and then place your servos into their slots inside the head, push the rod from the outside of the head and then into the dowel connector on the other side, hold until dried. I recommend doing one at a time.

The larger servo that connects to the head can be slide into place and shouldn't require any glue, but you ca use some mounting putty to help ensure the servo never wanders:

I did glue my spine apparatus into place, but make sure you know exactly what you're going to use to attach the head to the body before you do so.

The las step is to connect in the hole cross connector to the larger servo post. This was designed to be a friction fit and should not require glue.

Re-upload the random servo code from earlier in the project to your Uno.

Plug in power to your Uno and Raspberry Pi and watch your little buddy come to life!