How To Make A Magic 8-Ball With Raspberry Pi and Sense HAT

Magic 8-Ball With Raspberry Pi
(Image credit: Tom's Hardware)

The Raspberry Pi Foundation released its Sense HAT add on back in 2015 and yet this board remains one of the best Raspberry Pi HATs, because it  still packs a full scientific platform and an 8x8 RGB LED matrix for a little fun in your Raspberry Pi projects. The Sense HAT is packed with sensors for temperature, humidity, acceleration, orientation and air pressure. Plus we have a great RGB LED matrix and a joystick that can be used in our projects. 

To control the Sense HAT we used Python, but we can also use Scratch and Node-RED. Sense HAT was developed alongside a project called AstroPi which saw two Raspberry Pi B+ boards being sent to the International Space Station. These two Pis had their own Sense HAT boards, official Pi cameras and a custom designed aluminium case designed to protect and cool the Pis in space. Projects written by children across the world were run on those two Raspberry Pis and that project still exists today and you can take part via their website https://astro-pi.org/ 

In this tutorial we shall introduce the board, show text on the LED matrix and learn how to read accelerometer data for a classic game of chance.

For this project you will need 

  • Any Raspberry Pi that has 40 GPIO pins
  • A SenseHAT
  • Raspberry Pi OS on a microSD card

If you have never set up a Raspberry Pi before, see our articles on how to set up a Raspberry Pi for the first time or how to do a headless Raspberry Pi install, which doesn’t require a keyboard, mouse or screen. 

Connecting the Sense HAT To a Raspberry Pi 

Connecting a Sense HAT to the Raspberry Pi is simple. With the Raspberry Pi powered off, connect the Sense HAT to all of the GPIO pins, ensuring that the Sense HAT perfectly overlaps the Raspberry Pi. 

Use the included stand offs to securely mount the SenseHAT. Now attach your keyboard, mouse, HDMI, micro SD and finally power to boot the Raspberry Pi to the desktop. As we are using the latest version of Raspberry Pi OS, we do not need to install any software or Python packages.

Writing a Hello World Program with Sense HAT

(Image credit: Tom's Hardware)

The first project with any new piece of tech or software is “Hello World”. It proves that our kit is working, and that everything is ready for us to move further. The first project is a simple scrolling message you program in your preferred Python editor: Thonny, IDLE, Mu or a text editor. Create a new file and call it text_scroll.py. Remember to save often!

1. Import the SenseHat class from the sense_hat module, then create an object, “sense” for easy use of the module. 

from sense_hat import SenseHat
sense = SenseHat()

2. Create two objects to store the RGB color values for red and white. These objects are tuples, data storage structures which can be created and destroyed but never updated. These tuples store the RGB color values for a particular colour in a format that Sense() expects. 

red = (255, 0, 0)
white = (255, 255, 255)

3. Create a variable to store a message that will scroll across the screen. 

message = "Hello World"

4. Create an exception handler and loop. The handler will try to run the code indented within, and the loop will continuously run project code. 

try:
    while True:

5. Inside of the loop, use the show_message function to print the message to the screen. In this case it will scroll “Hello World”, the color of the text will be red, set via the tuple. The background color is white, again set via the tuple. The scroll speed is set to 0.1, slow enough to be read. Note that the spelling of color is UK English. 

 sense.show_message(message, text_colour=red, back_colour=white, scroll_speed=0.1)

6. Outside of the loop, create an exception, in this case a KeyboardInterrupt. When the user presses CTRL + C it will stop the code, and clear the LED matrix of the Sense HAT.

except KeyboardInterrupt:
    sense.clear()

The code for this project should look like this.

from sense_hat import SenseHat
sense = SenseHat()

red = (255, 0, 0)
white = (255, 255, 255)
message = "Hello World"
try:
    while True:
      sense.show_message(message, text_colour=red, back_colour=white, scroll_speed=0.1)
except KeyboardInterrupt:
    sense.clear()

7. Save the code and run via your Python editor. Thonny and Mu have a run / play button. IDLE uses F5 or via the Run menu. “Hello World” should now scroll across the LED matrix. When finished, press CTRL + C to clear the matrix.

Magic 8 Ball on Raspberry Pi 

The Magic 8 Ball is a classic game. We ask a question out loud, then shake the 8 ball. In a few seconds a message floats to a viewing portal, ready to read. With the Sense HAT we can make a modern day version which uses raw data from the accelerometer to determine that it has been shook. 

Create a new Python project in your favourite editor, call the project 8ball.py and remember to save often.

1. Import the SenseHat class from the sense_hat module, then import the choice function from the random module. Next create an object, “sense” for easy use of the module. 

from sense_hat import SenseHat
from random import choice
sense = SenseHat()

2. Create two objects to store the RGB color values for red and white. These objects are tuples, data storage structures which can be created and destroyed but never updated. These tuples store the RGB colour values for a particular colour in a format that Sense() expects. 

red = (255, 0, 0)
white = (255, 255, 255)

3. Create a list, “answers” that stores five text strings that are the answers to our eager player’s questions. Lists are what is known as arrays in other programming languages. A list stores data using an index which starts at zero. The first item in a list is at position zero, and subsequent items have their own numerical position. Lists can be created, destroyed and updated.

answers = ["Not likely","Chances are slim","Maybe","Quite possibly","Certainly"]

4. Create an exception handler and loop. The handler will try to run the code indented within, and the loop will continuously run project code.

try:
    while True:

5. Create an object, “acceleration” which is used to get raw accelerometer data from the Sense HAT’s onboard accelerometer. 

acceleration = sense.get_accelerometer_raw()

6. Create three variables, x,y,z to store the raw accelerometer data for each axis. 

 x = acceleration['x']
 y = acceleration['y']
 z = acceleration['z']

7. Using abs() we can update the variables x,y,z to store an absolute value that ignores if the value is positive or negative. The values stored inside the variables x,y,z can be positive or negative values, it all depends on the orientation of the Sense HAT. Our code will not need to understand negative numbers, just that the numbers can go over a threshold that will trigger the answers to appear. 

        x = abs(x)
        y = abs(y)
        z = abs(z)

8. Create a simple conditional test that checks the value stored inside the three variables x,y,z and if any of the values are greater than 1 then the indented line of code is run. 

        if x > 1 or y > 1 or z > 1:

9. Using the show_message function, employ the choice function to randomly select a string from the list “answers”. This is scrolled across the LED matrix with red text, and a white background. The background colors are set using the red and white tuples we earlier created. 

sense.show_message(choice(answers), text_colour=red, back_colour=white, scroll_speed=0.05)

10. Use an else condition to clear the LED matrix when the Sense HAT has not been shook. 

        else:
            sense.clear()

11. Create an exception, in this case a KeyboardInterrupt. When the user presses CTRL + C it will stop the code, and clear the LED matrix of the Sense HAT. 

except KeyboardInterrupt:
    sense.clear()

The code for this project should look like this.

from sense_hat import SenseHat
from random import choice

sense = SenseHat()

red = (255, 0, 0)
white = (255,255,255)
answers = ["Not likely","Chances are slim","Maybe","Quite possibly","Certainly"]

try:
    while True:
        acceleration = sense.get_accelerometer_raw()
        x = acceleration['x']
        y = acceleration['y']
        z = acceleration['z']

        x = abs(x)
        y = abs(y)
        z = abs(z)

        if x > 1 or y > 1 or z > 1:
            sense.show_message(choice(answers), text_colour=red, back_colour=white, scroll_speed=0.05)
        else:
            sense.clear()
except KeyboardInterrupt:
    sense.clear()

12. Save and run the code. Pick up the Sense HAT and give it a little shake. The answer to your questions is now but a shake away.

This article originally appeared in an issue of Linux Format magazine.

Les Pounder

Les Pounder is an associate editor at Tom's Hardware. He is a creative technologist and for seven years has created projects to educate and inspire minds both young and old. He has worked with the Raspberry Pi Foundation to write and deliver their teacher training program "Picademy".