Behold the Yack-O-Lantern!

With just a handful of parts and a couple of hours of work, you can easily repulse all of your co-workers at this year's office Halloween party!

Favorited Favorite 1

Ah, autumn! That wonderful time of year when makers, crafters, hackers and DIY-ers of every stripe get down to the business of creating the masterpiece they've been planning since November first of the previous year. Sometimes, however, life gets a bit too busy, and you realize that your perfect Halloween build barely has a chance of being finished by Christmas, nevermind Halloween. These are the times when you need a quick build that still shows that you're very creative, yet slightly disturbed. That's where the Yack-O-Lantern comes in! This table display uses an Infrared Proximity Sensor to trigger a horrible vomiting sound (it cycles through nine different sounds!) when anyone reaches for a treat from the tray.

The parts list is fairly simple for this one. I'm using a Sparkfun RedBoard, Sparkfun MP3 Player Shield (along with a set of Stackable Headers ), a Sharp GP2Y0A21YK Infrared Proximity Sensor along with the necessary IR Sensor Jumper, and a Hamburger Mini Speaker. For power I used a 4xAA to Barrel Jack Connector Battery Holder with a latching switch spliced into the line, but you could also use a battery holder with its own built-in switch. To add a little flickering candle effect, I also threw in a couple of Super Bright Yellow LEDs and an orange LED from our LED Rainbow Pack. Oh, and if you don't have a spare one sitting around, you'll need a microSD card for your sounds. You can also find the wishlist here:

Putting it together

There's not much to the assembly here at all. Like I said, sometimes you just need quick and easy. Simply solder the stackable headers into the MP3 Player Shield, and nest it onto the RedBoard. I soldered the two yellow Super Bright LEDs in series, and while I perhaps should have added a 22 Ohm resistor, I skipped it for expediency's sake, and because the LEDs won't be constantly powered. I wired the yellow LEDs to pin 9, the orange LED to pin 10, and the IR sensor to pin A0. Then just add the speaker and the battery pack, and Bob's your uncle!

Finding the sounds

If you're really into SFX or foley work, you may want to record your own sound files for this one. However, there are other options available, without having to hang out in the bathroom at a fraternity party with recording equipment. I used royalty-free files from, along with another site that no longer exists. But there are sound effects sites out there, it will just take some digging to find the ones you like. Please just remember to respect the licenses of the files you use.

The MP3 Player Shield has firm requirements regarding the naming of the files. I would definitely suggest reading the full hookup guide for the MP3 Player Shield here, but the short of it is that you'll need to name your files “track001.mp3,” “track002.mp3,” etc.

A bit of code

While there is a fair bit of coding needed for the MP3 Player Shield, the code for the Proximity Sensor is fairly simple. The sensor reads the intensity of the returned light, and the higher the intensity - that is, the closer the object - the higher the value returned. Adjust the variable "val" in the code so that the sensor only triggers when a hand gets to the edge of the serving plate.

Puking Party Pumpkin, AKA The Yack-O-Lantern!

Example sketch for the Sharp Ifrared Proximity Sensor GP2Y0A21YK
  and Sparkfun's MP3 Player Shield

Rob Reynolds @ Sparkfun Electronics
Oct 8, 2018  

Based heavily on the prior work of  
Jim Lindblom @ SparkFun Electronics

The proximity sensor has a three-pin JST connector terminating it. Connect
the wire colors like this:
- Yellow: A0 - signal output (pulled up internally)
- Ground: GND
- Red: 5V

Whenever the proximity sensor detects movement within a certain distance, it'll write the alarm pin LOW.

Development environment specifics:
Arduino 1.8.5

License: This code is public domain but you buy me a beer if you use this and we meet someday (Beerware license).    


// First, we'll include the needed libraries

#include <SPI.h>           // SPI library
#include <SdFat.h>         // SDFat Library
#include <SdFatUtil.h>     // SDFat Util Library
#include <SFEMP3Shield.h>  // Mp3 Shield Library

SdFat sd; // Create object to handle SD functions
SFEMP3Shield MP3player; // Create Mp3 library object
// These variables are used in the MP3 initialization to set up
// some stereo options:
const uint8_t volume = 0; // MP3 Player volume 0=max, 255=lowest (off)
const uint16_t monoMode = 1;  // Mono setting 0=off, 3=max

const int ledPinY = 9; // Yellow LED pin - active-high
const int ledPinR = 10; // Red LED pin - active-high
int sensorPin = 0; //analog pin 0 to read distance
int ledStateY = LOW;
int ledStateR = HIGH;
unsigned long previousMillis = 0;
unsigned long interval = random(50, 250);
int pukeSound;

void setup() 
  Serial.begin(9600); //For testing purposes, to send message to Serial Monitor

  pinMode(ledPinY, OUTPUT);
  pinMode(ledPinR, OUTPUT);

  initSD();  // Initialize the SD card
  initMP3Player(); // Initialize the MP3 Shield
  delay(10000); // allows 10 seconds for initial setup without triggering SFX

void loop() 
  // This first section is for the flickering candle effect, based on BlinkWithoutDelay
  unsigned long currentMillis = millis();
  if (currentMillis - previousMillis > interval) {
    previousMillis = currentMillis;
    if (ledStateY == LOW){
      ledStateY = HIGH;
      ledStateR = LOW;
      interval = random(50, 250);}
    else {
      ledStateY = LOW;
      ledStateR = HIGH;
    digitalWrite(ledPinY, ledStateY);
    digitalWrite(ledPinR, ledStateR);

  int val = analogRead(sensorPin);
  Serial.println(val); // Watch the value, and adjust it as needed for proper distance to trigger sfx

  if (val > 250) // This is the number to adjust for distance tuning
      pukeSound = ++pukeSound;
//    Serial.println("Motion detected!");
    uint8_t result = MP3player.playTrack(pukeSound);

    delay(10000); // give it 10 seconds before it will re-trigger
//    digitalWrite(ledPinRED, LOW);

    if (pukeSound == 9){
      pukeSound = 0;

// initSD() initializes the SD card and checks for an error.
void initSD()
  //Initialize the SdCard.
  if(!sd.begin(SD_SEL, SPI_HALF_SPEED)) 

// initMP3Player() sets up all of the initialization for the
// MP3 Player Shield. It runs the begin() function, checks
// for errors, applies a patch if found, and sets the volume/
// stereo mode.

void initMP3Player()
  uint8_t result = MP3player.begin(); // init the mp3 player shield
  if(result != 0) // check result, see readme for error codes.
    // Error checking can go here!
  MP3player.setVolume(volume, volume);

The first part of the void loop() is for the flickering candle effect, and is a slight variation on the Blink Without Delay sketch. That is definitely a bit of coding with which you should be familiar. You know from your first Arduino sketch that the simplest way to blink an LED is with the delay() command – however, that stops the script from continuing on, so it's not ideal for most applications. Blink Without Delay works around this, so that you can set the duration of the LED blinks without holding up the rest of your code. For this build, I've added a random component to give the blink more of an illusion of a flickering candle.


Why certainly I want to eat whatever is dribbling out of his mouth!

What is happening

Once you have your Yack-O-Lantern assembled, coded and running, here's what is actually happening. The infrared sensor is sending out an IR beam. When this beam hits an object - say, a hand reaching for a delicious treat - that beam is reflected back to the IR receiver. However, unlike a LIDAR unit or an ultrasonic sensor, the IR sensor isn't measuring the time it takes for the beam to return. It's measuring the intensity of the returned light, so the closer the object, the higher the intensity. If you watch the data being returned in the Arduino serial monitor, you'll see that the closer an object gets to the sensor, the higher the number the sensor returns.

alt text

Leonardo, is that you?

What's in your vomit?

Too much? Oh well. So for this demo, I used classic twin snakes gummies, because they were easy for people to grab. I've also used guacamole, which looks great coming out of the pumpkin, but requires chips, and is a bit messier. But really, even if you just have little candy bars coming out of the mouth, the effect will still be there. So have fun with carving the face, have fun sourcing the sounds and have a hack-tacular Halloween!

Interested in learning more about distance sensing?

Learn all about the different technologies distance sensors use and which products would work best for your next project.

Take me there!

Comments 7 comments

  • Member #134773 / about 5 years ago / 2

    Off topic, but time dependant!

    Hey, Feldi, you might like this!

    Yesterday I went to Costco. They have beautifully faceted plastic boxes (that I'm thnking will make great housings for projects) that contain 48 Ferrero Rocher hazelnut/chocolate candies. These seem to be a "Christmast season" item at Costco, and their normal price is a smokin' deal at somewhat over $12, but they're currently on sale for a bit less than $10. (For comparison, I've seen 3-packs of Ferrero Rochers, in bland packaging, for about $2. I've only ever seen the 48 packs at Costco.)

    My girlfriend has a birthday in a couple of weeks, so guess what's she's getting, though I'm going to tell her not to throw out the box! ;-)

    • Feldi / about 5 years ago / 1

      Ohhhhhh that's a hot tip! Nothing like a good pre-made enclosure, especially when there's chocolate involved :)

  • Member #134773 / about 5 years ago / 2

    Two quick comments on the code:

    pukeSound = ++pukeSound;

    It's more common to just say


    Also, it's easy to radomize the sounds (keeps "repeat customers" guessing!):

    pukeSound = random(9) + 1;

    (Note that random(9) returns a number between 0 and 8, inclusive, thus the need for the "+1", and yes, using Arduino, "random(1,10)" would eliminate the need for the "+1", but that's not true for all implementations of C/C++.)

    FWIW, I first started doing C programming about 40 years ago. :-)

    • ROB-24601 / about 5 years ago / 1

      It’s more common to just say


      Yes, thank you! As I was finishing up the code for this project at about 2:45am on the first day of my vacation, I knew there was a more succinct way to code it, but could not for the life of me remember it. I had considered randomizing, too, but again, at 2:45am, I was willing to let that go!

  • Bryan M / about 5 years ago * / 2

    I love it! That's very similar to what I did last year. I set mine up in one of our real jack-o-lanterns next to another jack-o-lantern with a real candle in it, and then we put our candy bowl in front of them. Then instead of vomiting I had various scary monster sounds. I used some neopixels for the candle effect (I had some extras from another project that never came to fruition) and it was realistic enough that you really couldn't tell the two lanterns apart.

    Unfortunately, I spent so much time on getting a good candle flame that I ran out of time to get the proximity sensor (motion sensor in my case) working, so instead I wired it up to a manual push button. It allowed me to perfectly time the scare (or avoid scaring the smaller children), but it also gave another chance for the particularly smart/observant ones to predict what was going to happen... Kids these days are so jaded!

    Edit: here's a link if anyone's interested in seeing what I made.

  • Does this code working. I tried but there is an error.

    • ROB-24601 / about 5 years ago / 1

      Hmmm. I just reloaded the code, and it seems to work fine for me. I would say check your wiring, and make sure that you've copied all of the code. If you're still having trouble, you can always reach out to If you're getting an error message in Arduino, let the support team know what that message is, that will help them to help you.

Related Posts

Recent Posts


All Tags