Naughty Elf Animatronic Holiday Air Freshener

Table of contents

Naughty Elf Animatronic Holiday Air Freshener

Abstract

How about an mischievous Elf on the Shelf that farts peppermint, butter cookie dough, or holiday pine scents as an air freshener ? An Elf doesn’t fart continuously, only attempting secretly ninja style strikes , so there needs to be a trigger and animatronic movements that play along with songs and sound effects. Oh What Fun !!

INTRO

Holiday Projects are so fun to build. I was dreaming about a project that my grandson would get a kick out of, I finally came on an idea that really got my juices percolating.

It had to be Naughty Elf on the shelf.

There is a naughty elf on his Christmas tree at home, so he is familiar with the concept.

My 6 year old grandson also loves potty humor.

How about an elf that farts peppermint, butter cookie dough, or holiday pine scents as an air freshener ? YAY ! that’s it.

An Elf doesn’t fart continuously, only attempting secretly ninja style strikes, so there needs to be a trigger and animatronic movements. 

The Holidays are all about family, fun, laughter, food and songs.  Yep, this is an entertaining and worthy holiday project.

Before getting into details, lets see the final  video and glamor photos

schematics, details, and step by step follow the video and photos 

video:   https://youtu.be/ihv4U8OYnzI

photos:

Elf normal innocent position, putting a gift under a decorated tree 

image

After motion triggers a song, about 40 seconds into the audio, the elf bends over and has a gaseous accident

releasing your favorite scent 

image

image

image       

after his emission is done, 5 seconds, the elf returns to his normal position, music will stop until the next trigger 

The Schematics: 

image

image

image

atomizer slightly hacked

image

// OPERATION DESCRIPTION
// on power up, delay a 15 seconds to allow PIR to initialize to correct state 
//
// use PIR to trigger sequence if no audio is not busy
// on trigger, start audio file ( this testing version only play audio track 1 )
// wait 40 seconds 
// elf will bend over from standing straight up 
// the elf waist servo moves from 90 degrees to zero degrees in about 7 seconds 
//
// at time = 40 secs, enable atomizer for 5-10 seconds
// when audio track is complete (DFPLAYER BUSY = HIGH)start elf to stand up 
// after elf is standing , delay 15 seconds before a retrigger is allowed 



#include <Servo.h>

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

int pos = 90;    // variable to store the servo position
int motionDetected = false; 
int DFplayerBusy;
int toggle = 0; // toggle value between 0 & 1 to alternate which audio track plays
int trackNumber =0; // track number for which DFplayer relay to turn on


void setup() 
{
  ElfMove.attach(9);  // attaches the servo on pin 9 to the servo object
  
  pinMode(3, INPUT); //PIR motion detected, HIGH for 6 seconds
  pinMode(5, INPUT); //DFplayer is playing when value = false
  
  ////pinMode(9, OUTPUT); //output already defined to servo 
  pinMode(10, OUTPUT); //atomizer relay 
  pinMode(11, OUTPUT); // play audio 1 relay, picks up with relay module input=0
  pinMode(12, OUTPUT); // play audio 2 relay, picks up with relay module input=0
  Serial.begin(9600); // serial monitor for troubleshooting
  
 // delay(15000); // wait 15 seconds for PIR to initialze 
  
}

    
void loop() {

    digitalWrite(10, LOW); //for initalization
    digitalWrite(11,HIGH); // for initalization
    digitalWrite(12,HIGH); // for initialzation

trackNumber=0;  // location for selecting the track number relay, now is only 0 

delay (10000); // some settling time 

motionDetected=digitalRead(3); // high means PIR is triggered
DFplayerBusy=digitalRead(5);//low when DFplayer is active
//Serial.print("motion detected =");
//Serial.println(motionDetected);
//Serial.print("DFplayer Busy =");
//Serial.println(DFplayerBusy);


////////////////////// code to turn on DFplayer audio via relays ////////////////////////
if ((DFplayerBusy==HIGH) && (motionDetected==HIGH)) // only replay if not dfplayer is not busy
//if ((motionDetected==HIGH)) // this test doesnt worrry about BUSY signal
  { 
    // start playing audio 
          if (trackNumber==0) 
          { 
            digitalWrite(11,LOW); //LOW turns on the relay
            digitalWrite(12,HIGH);   
            delay(100);
            digitalWrite(11,HIGH);
            digitalWrite(12,HIGH);  
          }
       
          if (trackNumber==1) 
          { 
            digitalWrite(11,HIGH); //LOW turns on the relay
            digitalWrite(12,LOW);   
            delay(100);
            digitalWrite(11,HIGH);
            digitalWrite(12,HIGH);  
           }

////////////// wait for farting in the tracks
delay(32000); /// wait for 35 seconds to prep fart sounds in audio 
delay(3000); 
/////////////// FARTING SEQUENCE servo motion code forward and atomizer enable /////

///////// now in fart position, fire the atomiser for 5 seconds /////////
        digitalWrite(10, HIGH);
        delay(200);
        digitalWrite(10, LOW);
    
    for (pos = 90; pos <= 135; pos += 1) // this move takes 6.75 secs
        { // goes from 0 degrees to 180 degrees
        // in steps of 1 degree
        ElfMove.write(pos);              // tell servo to go to position in variable 'pos'
        delay(150);                       // waits 15ms for the servo to reach the position
        }

///////// now in fart position, fire the atomiser for 5 seconds /////////
//        digitalWrite(10, HIGH);
 //       delay(500);
 //       digitalWrite(10, LOW);
        

   /// ----- stop mist by closing pb twice ------

     delay(5000);
     digitalWrite(10,HIGH); // start mist
     delay(200);
     digitalWrite(10,LOW); // start mist
     delay(500);
     digitalWrite(10,HIGH); // start mist
    delay(200);
     digitalWrite(10,LOW); // start mist  


    for (pos = 135; pos >= 90; pos -= 1) // goes from 180 degrees to 90 degrees
      { 
        ElfMove.write(pos);              // tell servo to go to position in variable 'pos'
        delay(10);                       // waits 10ms for the servo to reach the position
      }
         
////////////// STOPPING SEQUENCE //////////////////////

DFplayerBusy=digitalRead(5);//low when DFplayer is active

/////////// if DFplayer is busy, wait for audio track to complete //////////
while (DFplayerBusy==LOW)/// if audio track is done, restart loop 
       {  
        delay(1000);
        DFplayerBusy=digitalRead(5);
        //Serial.print("DFplayer Busy in stopping sequence =");
        //Serial.println(DFplayerBusy);
       }        
  
  } /// end bracket for running 

delay(2000); /// allow DF player and sequencing to totally stop 


}  //bracket for void loop

The step by step:

First the concept:

  • Use an atomizer to spray air freshener from rear of Naughty elf
  • Elf rotates or bends over while pooting, use standard 180 degree servo
  • Play Xmas music and then poot, then laughter DFPLAYER & SPEAKER
  • Detect people using PIR & PING & random # sleep timer ? trigger if motion is in front of Elf
  • 2 Christmas songs are fine for this project. Other previous projects I’d created 200 or more unique audio files to avoid repetition, but no one listens that long anyway.

Gather the parts:

Ordered a Naughty Elf on the shelf and bought some candy canes. 

Scoured the shop for a solid base, decided to use a plastic drawer to start with. Glue gun works OK for securing boards to the plastic. They will stay in place, but can be pulled and moved non-destructively with minimal effort.

I usually start with cardboard or medium density fiberboard then move to different mediums depending on stiffness, weight, and durability needed. 

I already have a significant on hand inventory of Arduino & Raspberry Pi parts.

An analysis of my PIR inventory: HC-SR501, SR505, SR604, the SR505 had the shortest range which fit this project best, so to not constantly trigger the air freshener. 

My audio player inventory includes the WTV020-DP and DFplayer. DFplayer is becoming my go-to since it plays MP3s and has a built in 3W amplifier.

The atomizers need a relay interface, and to keep it simple, I another used a couple relays for the DFplayer triggering.

This project I used a PC power supply for 5V 4A rather than batteries and buck power supplies. I have a pretty good inventory of homemade power distribution boards rather than daisy chaining the 5V power everywhere.

Raspberry Pi Pico or Arduino ?  I re used an old bootloader Arduino Nano, as I could reference previous project’s code. Maybe Santa will gift me a Raspberry Pi Pico 2 or some newer Nano form factor.

Servo or DC motor for motion ? The DC motor is much better for speed control, but then again, I would need an H bridge and end limit switches or hall effect sensors+magnets. I decided a standard size servo this time, the 9G servo cant take the weight of a cookie fed elf.

I have a bunch of Christmas CDs, for sure I can find a couple signature tracks to use with some sound effect MP3 files for a fun display. Audacity was used to edit & generate the MP3 audio files.

After selecting the major components, I did a first pass IO assignment.

Starting with the PIR, it got powered and tested with a DVM, then wired to the Arduino to very it worked by observing in the serial monitor.

Next added in the DFplayer, first testing with hardware jumpers, then using forced IO, then simplifying to play just one track to work out bugs.

Next the atomizer code was added.

Please refer to the schematic for wiring and the IO assignments.

Functional details are explained in the Arduino code comment header

References

https://docs.arduino.cc/language-reference/

Category : project