text.skipToContent text.skipToNavigation

Shake the Present

Download Project Resources View on Github

hero image

Shake the box to find what you get in this magic 8-ball styled Christmas gift game.

shaking gif

Bill of Materials

Qty Code Description
1 XC4410 Arduino Uno Compatible Board
1 XC3728 1.3" Monochrome OLED
1 XC3732 Tri Axis Digital Tilt Sensor
1 WC6028 Plug Socket Leads
1 PH9251 Battery DC Lead
1 SB2423 Battery

You might also want

  • Some sort of "project box" to mount it all in so you can dress it up like a present. We do have a range of enclosures available and for our Purposes we used the box from the Duinotech Starter Kit (- only $40 so it's a good buy for Christmas if you are stuck for ideas anyway)

How to build

Wiring Diagram

UNO OLED screen Tilt sensor
3v3 VCC
13 CLK
12 RES
10 DC
9 CS

The wiring for this is fairly simple as we only have to connect up two modules. The OLED screen is an SPI device so we connect it up through the SPI ports with some extra digital pins for signaling (RES and DC).

The Tri-axis tilt sensor is a standard i2c device with SDA and SCL. It does have interrupt pins but we don't need to worry about them for now as we are just waiting for the device to talk, rather than getting the device to tell us when it can talk.

For this shake the box present, you'll probably want to tape or hot glue the connections to the arduino so they don't come undone when you shake the box too hard. You'll effectively be mounting everything in the box as shown.


When doing something like the OLED connections, it's eaiser to keep all of the wires attached to each other from a fresh pack of WC6028.


It also makes it easier when poking through any present-styled box if you aim to put this in. For our purposes we used the box from the duinotech starter kit.

poking through

Once it's all mounted in the box, you can decorate it however you want like a small present.


Software Libraries

For this project you will need to use the arduino library manager to download some libraries:

Library Author Version
Sparkfun_MMA8452Q Sparkfun 1.4.0
U8g2lib oliver olikraus@gmail.com 2.27.6

How to create OLED images

Usually it is quicker and easier to first draw the images in MS Paint, as they have the handy shapes and lines that we can use to make the picture how we want.

Edit the file properties so that it is a black and white image of size 128 x 64. For instance, we are going to go with something like this: (zoom in 800% so it's easier to see while working)


Once you have made your image, select all (Ctrl-A) and copy (Ctrl-C) to paste into gimp ( Ctrl-V ).

In gimp, there's a few extra tools, such as 360 degree rotation, and other things.

Using GIMP

Firstly download and run GIMP.

If you did not create an image with MS paint, you can create a new image of size 128x64 pixels as shown in the picture below:


or otherwise get your image and reduce it in size to 128 x 64 via Image -> Canvas Size.


1-bit pallet

As the OLED screen we are using only has 1 bit data (ie: on or off) we must change the image mode to be similar 1-bit sized.

Firstly go to Image -> Mode -> Indexed.. And set the colormap to the 1-bit pallet


1 bit

Exporting as XBM

The filetype we want for the OLED is actually an XBM filetype; Go to File -> Export As and choose XBM with the "Select File Type (By Extension)"

save as

you can name the file something easy to remember, such as santa.xbm

Once you have exported the file as XBM, you can then rename it to santa.h file. This is so the arduino IDE can pick it up and include it normally. XBM is an old file format used in the early days of computers which were just straight C code, such as what's seen below:


We've managed to fit 2 images into the program this way, but space is limited so it might not be a good idea to fit a 3rd image unless you get something big and chunky like the XC3812 SAMD12 board.

Working principle

The basis of this is using the XC3732 Tri Axis tilt sensor to detect the magnitude of acceleration that the box is going under

We use Pyagrath's Theorem to find the total magnitude, and use a Rolling, or Simple Moving Average to smooth out spikes in the data, so a sharp knock will not trip the shake counter (as the spike in data will be smoothed out). If you want to see this in action, uncomment the RAW_LOG define near the top of the code.

After about 5 shakes, we show another image on the OLED, and after 10 shakes, we generate a random number and "roll" to the gift that the person gets.

Memory Limitations

There's very limited memory on the ATMEGA 328P chip, which isn't made any easier with the variety of feature-full libraries that are available through the library manager. For this project, the memory space very quickly ran out of room trying to manage both the accelometer and oled objects, causing a reboot once it reaches to a certain point in the program.

To overcome this we used some resource allocation in our core methods: draw() and measureShake().

Here, each method creates the object that it is managing. For instance, the draw() function creates the U8g2lib object, draws things on the screen, and then deletes the object, thus freeing the memory. Similarly, the measureShake() will create the accelerometer management object, take readings, and store it in the buffer to be averaged later, before deleting the accelometer object again.

In many applications this is slow to do, but for our purposes, it actually functions fine and utilises more of the speed that is available for us via the ATMEGA328P.