The Horrifying Chocolate Easter Bunny - a Simple Electronics Game
658 Views, 1 Favorites, 0 Comments
The Horrifying Chocolate Easter Bunny - a Simple Electronics Game
Chocolate Easter Bunnies - well, I am not sure how typically German they are.
So for all these not seeing them every spring: they are hollow pieces of chocolate shaped like a rabbit and wrapped in colorful printed aluminum foil.
A few days before Eastern 2021, buying some for my grandchildren, I had an idea for a game which I would like to present in the following:
"The horrifying chocolate Easter Bunny".
The rules are simple:
- There is a row of [n] chocolate Easter bunnies
- When a bunny is touched, an animal sound is being played
- Its [n-1] times the sound of a friendly farm animal, as pigs, sheep, goat, horses, cow an so on
- But one of the animals is a mean tiger!
- The player who's raising the tiger is getting snatched and eaten by the tiger and has lost!
- That is the end of the game => start a new round by resetting the device
- As the order of animals get randomized in each round, nobody knows where the bad tiger is.
- So the game is basically a kind of Russian roulette for kindergarten kids.
- If a bunny is touched for a second time, an elephant appears.
- There are rules for two levels of players:
a) for small kids: the elephant tells you that you have to pick an other bunny
b) for older kids and adults: the mad elephant has got you, you're out.
So better remember which bunnies were already touched.
- There are rules for two levels of players:
As chances as similar for all, it is a game for the whole family.
In technical terms, the device is a simple MP3 player just consisting of a RPi Pico microcontroller, a MPR121 12 channel capacitive touch sensor (I2C), a MAX98357 I2S amp and a 3 Ohm speaker. Well, not to forget some cables, up to twelve chocolate Easter bunnies, two LEDs and a momentary switch to reset the device.
To power the Pico, you also need a USB power supply or power pack and a USB cable.
The script is written in CircuitPython, so it is very easy to adapt the code to your layout of the game.
The Pico is playing MP3 files but its storage capacity is limited, to a bit less than 1000 kB. So you may store about 20 short sound MP3s. I used some publicly available sound files and truncated some of them a bit using the program "Audacity". The sound files are stored in a folder called "MP3s". Except for "Elephant.mp3", they were renamed "Animal_10.mp3" (the tiger) to "Animal_17.mp3".
Supplies
- Raspberry Pi Pico, 4 US$
- MPR121 breakout (Adafruit, gator version), 7 US$
- MAX98357 I2S amp (Adafruit), 6 US$
- 3 Ohm 4W speaker or similar, 4 US$
- 8-12 chocolate Easter bunnies (you may use chocolate Santas as well, just depending on the season)
- two LEDs
- large momentary switch
- cables
- a cardboard box
- USB power supply & cables
- Brass M3 screws, nuts and washers
In total about 30 - 40 US$ or €
Assembly
- Have a look on the images and the Fritzing drawing
- Find a fitting box. I used a cardboard box for a large kitchen knife my wife had put into our paper trash basket.
-
I glued a green piece of cardboard to the top of the box. Looks nicer, no function.
- Assemble the Raspberry Pi Pico and add headers if you like to use a breadboard.
- In case, place it on the breadboard.
- Add headers and connectors to the MAX98357 breakout (if required)
- Load the latest CircuitPython uf2 file to your Pico
- Get the latest Adafruit CircuitPython library and extract the MPR121.mpy file and move it to the lib circuitpython/subfolder on the Pico
- Copy the script file and copy it as code.py on the CircuitPython root directory on the Pico.
- Get some animal sound MP3 files. I used a variety of farm animals, tiger and elephant from freeanimalsounds.org . Modify them if required, you may use Audacity or some other program.
Rename the files to Animal_10.mp3 to Animal_xx.mp3, let Animal_10.mp3 be the Tiger.
Name the elephant sound file Elephant.mp3. - On the Pico make new folder called "MP3s".
- Copy the MP3s into the "MP3s" folder on the Pico.
- Attach the MPR121 and MAX98357 breakouts to the breadboard as indicated, connecting
- MPR121: GND to GND, Vin to 3V3, SCL to GP17, SDA to GP16
- MAX98357: GND to GND, Vin to 3V3, din to GP09 BCLK to GP10, LRCLK to GP11
- Connect the speaker cables with the I2S amp, check for polarity.
- Connect the momentary switch to GND and RUN on the Pico
- Place a 220 Ohm resistor to the breadboard, between GND and one of the columns
- Connect the LEDs to the breakout:
- LED1 (power on): connect (+) to 3v3 and (-) to the column connected via the resistor to GND
- LED2 (touch now): connect (+) to GP05 and (-) to the column with the resistor
-
Connect the momentarily button (reset) to GND and the RUN pin on the Pico
-
For the prototype I used jumper cables to connect the LEDs. Drill holes for the LEDs into the cardboard box and fix the LEDs
- Place the bunnies on the box. Mark the points for the cable holes and drill or push holes into the box.
- Cut pieces of cable about, they were about 15-20 cm in my case, and remove about 1 cm of isolation on both sides
- Twist the ends of thee cables if required
- Stick the cables through the holes
- Fix the cables on the bottom of the bunnies. I used a bit of adhesive tape.
- Glue the bunnies to the top of the box. I used hot glue, but waited until it cooled but was still sticky before fixing the bunnies. To give them a bit more stability, I added a supporting wooden triangle on their backs
- Connect cables and washers
- Fix washers with screws and nuts at the MAX98357 breakout (Adafruit gator version), see images
- Connect amp and speaker
Check everything and run the device.
The sound might be slightly distorted if the device is powered by a computer. This will improve when powered from a power supply or power bank.
Downloads
The Script
I am dwarf, standing on the shoulder of giants. So I have used the Adafruit CircuitPython MPR121 driver and the MPR121 example script, and learned a lot from the Lars the sloth puppet project by John Park.
- The script a first generates a list of n numbers (10 to [10+n-1]) and then shuffles the list to generate a random order
- If a bunny gets touched, the script first checks if it had been touched before => elephant.
- It then identifies the according sound by correlating the number of the bunny with the corresponding position of the list.
- It then retrieves the MP3 sound file, decodes it and plays the sound.
- If the tiger has appeared, the game ends.
- You now have to restart by pressing the momentary button, generating new randomized list.
Here is the script.
Feel free to optimize and modify.
import time
import busio
import digitalio
import board
import sys
import random
import audiomp3
import audiobusio
import adafruit_mpr121
onboard_led = digitalio.DigitalInOut(board.GP25) # Pico onboard LED: now playing
onboard_led.direction = digitalio.Direction.OUTPUT
touch_led = digitalio.DigitalInOut(board.GP5) # indicates touch now
touch_led.direction = digitalio.Direction.OUTPUT
# I2S settings
bit_clock = board.GP10 # for i2s breakout, pin 12
word_select = board.GP11 # for i2s breakout, pin 14
data_in = board.GP9 # for i2s breakout, pin 15
# I2C settngs
SCL_0 = board.GP17 # for i2c sensor, pin 22
SDA_0 = board.GP16 # for i2c sensor, pin 21
i2c_0 = busio.I2C(SCL_0, SDA_0) # , frequency=100000)
# mp3 audio settings and functions
gap = 2 # set length of break
a_mp3 = audiobusio.I2SOut(bit_clock, word_select, data_in) # define I2S as output channel
# Create MPR121 object.
mpr121 = adafruit_mpr121.MPR121(i2c_0)
# Note you can optionally change the address of the device:
# mpr121 = adafruit_mpr121.MPR121(i2c, address=0x91)
n = 8 # number of touch pins used (0 ... n-1)
MP3_File = ""
def shuffle(arr):
last_index = len(arr)-1
while last_index > 0:
rand_index = random.randint(0, last_index)
temp = arr[last_index]
arr[last_index] = arr[rand_index]
arr[rand_index] = temp
last_index -= 1
def play(animal):
print("playing :", animal)
mp3out = audiomp3.MP3Decoder(open(animal, "rb")) # decode mp3 file
a_mp3.play(mp3out) # play MP3
t = time.monotonic()
while time.monotonic() - t < 6:
pass
animal_list = [10, 11, 12, 13, 14, 15, 16, 17] # elongate/adjust if required
shuffle(animal_list) # randomize order
print(animal_list) # for cheating or development
time.sleep(3)
played_list = []
touch_led.value = True # turn the "free to touch" indicator on
# Loop forever testing each input and printing when they're touched.
while True:
# Loop through all n inputs (0 to n-1).
for i in range(n):
# print((i, 0)) # output for mu plotter
# Call is_touched and pass it then number of the input. If it's touched
# it will return True, otherwise it will return False.
if mpr121[i].value:
touch_led.value = False
onboard_led.value = True # turn on onboard LED
# print("Input {} touched!".format(i))
print((i, 0)) # output for mu plotter
if i in played_list: # if already been touched/played
print("already touched")
animal = "/MP3s/Elephant.mp3" # picks the according MP3 file
play(animal)
else: # if not been played before
played_list.append(i)
print(played_list)
p = animal_list[i] # pick corresponding value from randomized list
animal = "/MP3s/Animal_{}.mp3".format(p) # picks the according MP3 file
play(animal)
onboard_led.value = False # turns of onboard led
if p == 10:
# end program/restart if the Tiger was found
print("Ouch, you have been eaten by the tiger! \n Good Bye")
time.sleep(3)
sys.exit()
time.sleep(gap) # give it a break!
touch_led.value = True # turn on the free to touch indicator
time.sleep(1)
Downloads
Open Issues
As this has just been a fast build and not a well planed project, there are some points that require optimization.
Sensitivity:
A least some of the bunnies were hypersensitive, they were activated by just nearing. In addition there are noise signals, so I got spontaneous animal sounds without anyone touching.
And finally the sensor seems to remember long touches, so there will be too much elephants sounds filling the room. For the later issue introducing longer breaks seems to help, but extends responses times (see video).
Sound:
You may also like to be able to control loudness.
One way would be to control the gain of the amplifier by adding resistors to the gain pin of the breakout. See the Adafruit documentation.
More sounds:
In theory, you could use up to four MPR121 units in parallel if you have set them to different I2C addresses, so you can read up to 48 touch pads. You may even double it by using both I2C_0 and I2C_1. But here the Pico's storage capacity for MP3 files then may become a limiting factor. In addition, some modification of the script will be required.