Tuesday, May 8, 2012

Digital Magic 8 Ball

Is this one of the coolest projects I've made on the spur of the moment?
 The magic 8 ball is always correct!

I remember I used to have a magic 8 ball key-chain as a kid. I loved asking it the stupidest questions and seeing it magically divine the answer. Either that or it just repeatedly responded with an anti-climatic ask again later. One day the magic just dried up ... literally, the purple fluid in the cavity evaporated! Randomly remembering this device, I decided on the spur of the moment, after learning how to seed and use the rand() function in the standard c library, to make my very own digital magic 8 ball (which would be impervious to drying up, but still vulnerable to releasing its magic smoke).

I've moved on up from the pic16f84a to the 16f886. I know it is overkill for most of what I use it for, but it is great for prototyping because of the large program memory, abundance of peripherals, and gpio. Plus I love using the internal oscillator for anything that doesn't require an accurate clock.

This is the prototyping breadboard I use for everything with the icsp header in the middle, a built in li-polymer battery on the back and integrated charge controller at the top. Ignore the 8 pin dip rtc above the pic, I might add a clock feature and make my magic 8 ball a watch.

The pic starts counting on start up until the user presses the button. This count value (which in effect is somewhat random) then seeds the pseudo random number generator. The number that it comes up with then determines which of the 20 replies the magic 8 ball will give. When the button is pressed again, the user is returned to the main screen asking for another question.

I ported the code I wrote is assembly for the 16f84a which handles spi serial communication in software (I know I could have done it in hardware, but this way was more fun). Then I needed a function to initialize and clear the ram of the oled display. In addition, I ended up having to write a function which would handle parsing strings and generate the data necessary to write them to the graphical display. I wrote most of this months ago and reused code but for a different application. I haven't really optimized anything but everything works and I am happy with it.

The only way to cheat the system is to hold the button or hit it immediately after the main screen loads, which ensures that the count value would be zero, which when seeded into rand() would produce the same value, which will always give the same reply.

I plan on using smt components, ditching the oled pcb, using a CR2032, and polling another button via interrupt so that I can put the micro to sleep and wake it for software power control. The entire device should be not much larger than the 3cm oled (aka perfect as a key-chain). I might think of using an accelerometer or tilt switch and put the oled in the window of an actual magic 8 ball. It would look really cool glowing eerily from the surrounding dark window, magically predicting the future. Might add a clock and fit the entire device to a watch strap so I can wear it around, tell time, and make life altering decisions with it. Maybe I'll add some simple games. Who knows? Either way it will be a great gift for my sister.

Ok ... there's one more question I need to ask it ... magic 8 ball ... will I ever become a famous electrical or computer engineer?
... fine then if you don't want to answer me, who needs you anyway ...

ps. A friend suggested I also make a miniature 20 questions ... hmmmm interesting ... maybe later ...
pps. Since summer is here expect many more projects :-)
ppps. I might make a digital fortune cookie with hundreds of different fortunes. Not too hard if I reuse most of my current code.

Here are the C and hex files for the project: Magic 8 Ball files.

Update: Added Schematic

If you have any questions feel free to shoot below. Enjoy


  1. Looking forward to the schematic.
    Can you give me the details on the display>

  2. I posted the schematic. It is easy enough to port my code to other micros. The display is a graphical oled off of ebay, just search for 128x64 oled module, there are many different versions but they all cost around $15 with the breakout board. Most use the SSD1306 driver (or similar) with an internal charge pump for driving the oled segments. The display is 3.3v tolerant (no 5V sorry). I rewired the jumpers on the back so that I could drive it via 3 wire SPI serial. If you need any help or the datasheet just hit me up.

    1. I've picked up your original design with plans to extend it with the goal installing it in a eight ball.
      Wondering if you want any attribution in my implementation.

  3. Hi,
    I have been searching for blogs like this for quite sometime. Thank you for posting the details of your circuit. may i know what compiler did you use for this one?

    This is certainly not MikroC. I tried Hi-Tech, CCS or am I just missing something.

    My main objective is to just make the OLED similar to the one you use display Hello World using MikroC. Once I have done that, I can make whatever i want to program. I just need to make the OLED works and everything will follow.

    Thank you very much.

  4. Hi,
    Its me again. I ported your code to MikroC. I use pic16f877a and 128x32 OLED (ssd1306) from adafruit. I am able to get data flowing in PORTC, i verify it using oscilloscope. I follow your schematic diagram but the OLED does not respond.

    When I transfer my OLED to the ATmega32 circuit. It works.
    Maybe there is still lacking in the MikroC code or Schematic.