Maker.io main logo

RGB Matrix Dreidel Game

2022-01-13 | By Adafruit Industries

License: See Original Project STEMMA

Courtesy of Adafruit

Guide by Liz Clark

Overview

In this project, you can build your own electronic dreidel game, complete with a servo motor and festive music, to celebrate Hanukkah. To play, drop chocolate coins into the slot at the top of the matrix. The RGB matrix will spin the dreidel while playing the classic dreidel song. If you roll gimel, you win! All of the chocolate coins will spill out for you.

screen_1

An IR breakbeam sensor is located at the top of the matrix to detect when a chocolate coin is dropped. This triggers the dreidel to spin.

Sensor_2

A servo motor is attached to the chocolate coin cup. The servo tilts the cup when the dreidel sprite sheet lands on gimel.

Motor_3

A STEMMA speaker plays the dreidel song while the RGB matrix spins the dreidel.

Speaker_4

If you've ever played dreidel before, you'll note that this version is slightly modified since it doesn't account for rolling hei to get half of the pot. A servo dumping out the entire pot when you roll gimel should hopefully make up for that though.

Parts

Circuit Diagram

Diagram_5

Wiring Connections

STEMMA Speaker

  • Speaker GND to MatrixPortal M4 GND

  • Speaker Power to MatrixPortal M4 Power

  • Speaker SIG to MatrixPortal M4 A0

IR Breakbeam Sensor

  • Receiver black wire to MatrixPortal M4 GND

  • Receiver red wire to MatrixPortal M4 3V

  • Receiver yellow wire to MatrixPortal M4 A1

  • Transmitter black wire to MatrixPortal M4 GND

  • Transmitter red wire to MatrixPortal M4 3V

Servo

  • Servo black wire to MatrixPortal M4 GND

  • Servo red wire to MatrixPortal M4 5V

  • Servo yellow wire to MatrixPortal M4 A4

3D Printing

The RGB Matrix Dreidel Game uses some 3D printed parts to complete the build. All of the parts can print without supports.

3D_6

It consists of three parts:

  • matrixDreidel_roof

  • matrixDreidel_legs

  • matrixDreidel_bucket

The files can be downloaded directly here or through Thingiverse.

matrixDreidel-STLs.zip

Thingiverse download

The roof mounts to the top of the RGB matrix and has mounts for the breakbeam sensor. The sensors are placed on either side of the chocolate coin slot.

The legs mount to the bottom of the RGB matrix and allow it to stand up freely. Additionally, it has mounts for the servo motor and the STEMMA speaker.

The bucket attaches to the servo motor horn and will catch the chocolate coins as they're dropped in through the slot at the top.

Bucket_7

Install CircuitPython

CircuitPython is a derivative of MicroPython designed to simplify experimentation and education on low-cost microcontrollers. It makes it easier than ever to get prototyping by requiring no upfront desktop software downloads. Simply copy and edit files on the CIRCUITPY drive to iterate.

Set up CircuitPython Quick Start!

Follow this quick step-by-step for super-fast Python power :)

Download the latest version of CircuitPython for this board via circuitpython.org

Further Information

For more detailed info on installing CircuitPython, check out Installing CircuitPython.

Click the link above and download the latest UF2 file.

Download and save it to your desktop (or wherever is handy).

Install_8

Plug your MatrixPortal M4 into your computer using a known-good USB cable.

A lot of people end up using charge-only USB cables and it is very frustrating! So, make sure you have a USB cable you know is good for data sync.

Double-click the Reset button (indicated by the green arrow) on your board, and you will see the NeoPixel RGB LED (indicated by the magenta arrow) turn green. If it turns red, check the USB cable, try another USB port, etc.

If double-clicking doesn't work the first time, try again. Sometimes it can take a few tries to get the rhythm right!

Reset_9

You will see a new disk drive appear called MATRIXBOOT.

Drag the adafruit_circuitpython_etc.uf2 file to MATRIXBOOT.

Disk_11

Disk_10

The LED will flash. Then, the MATRIXBOOT drive will disappear and a new disk drive called CIRCUITPY will appear.

That's it, you're done! :)

Drive_12

Coding the RGB Matrix Dreidel Game

Once you've finished setting up your MatrixPortal M4 with CircuitPython, you can access the code, audio file, bitmap and necessary libraries by downloading the Project Bundle.

To do this, click on the Download Project Bundle button in the window below. It will download as a zipped folder.

Download Project Bundle

Copy Code
# SPDX-FileCopyrightText: 2021 Liz Clark for Adafruit Industries
#
# SPDX-License-Identifier: MIT

import time
import random
import board
import pwmio
import displayio
import adafruit_imageload
from audiocore import WaveFile
from audioio import AudioOut
from adafruit_motor import servo
from digitalio import DigitalInOut, Direction, Pull
from adafruit_matrixportal.matrix import Matrix

#  setup for down button on matrixportal
switch = DigitalInOut(board.BUTTON_DOWN)
switch.direction = Direction.INPUT
switch.pull = Pull.UP

#  setup for break beam sensor
break_beam = DigitalInOut(board.A1)
break_beam.direction = Direction.INPUT
break_beam.pull = Pull.UP

#  pwm for servo
servo_pwm = pwmio.PWMOut(board.A4, duty_cycle=2 ** 15, frequency=50)

#  servo setup
servo = servo.Servo(servo_pwm)
servo.angle = 90

#  import dreidel song audio file
wave_file = open("dreidel_song.wav", "rb")
wave = WaveFile(wave_file)

#  setup for audio out
audio = AudioOut(board.A0)

#  setup for matrix display
matrix = Matrix(width=32, height=32)
display = matrix.display

group = displayio.Group()

#  import dreidel bitmap
dreidel_bit, dreidel_pal = adafruit_imageload.load("/dreidel.bmp",
                                                 bitmap=displayio.Bitmap,
                                                 palette=displayio.Palette)

dreidel_grid = displayio.TileGrid(dreidel_bit, pixel_shader=dreidel_pal,
                                 width=1, height=1,
                                 tile_height=32, tile_width=32,
                                 default_tile=0,
                                 x=0, y=0)

group.append(dreidel_grid)

#  show dreidel bitmap
display.show(group)

timer = 0 #  time.monotonic() holder
spin = 0 #  index for tilegrid
speed = 0.1 #  rate that bitmap updates
clock = 0 #  initial time.monotonic() holder to act as time keeper
gimel = 3 #  bitmap index for gimel, the winning character
countdown = 5 #  countdown for length of game. default is 5 seconds
beam_state = False #  state machine for break beam
reset = False #  state for reset of game
dreidel = False #  state to track if dreidel game is running

clock = time.monotonic() #  initial time.monotonic()

while True:
    #  debouncing for break beam sensor
    if not break_beam.value and not beam_state:
        beam_state = True

    #  if the break beam sensor is triggered or the down button is pressed...
    if (not break_beam.value and beam_state) or not switch.value:
        #  update break beam state
        beam_state = False
        #  begin reset for game states
        reset = True
        print("pressed")
        #  quick delay
        time.sleep(0.1)

	#  if reset state...
    if reset:
        #  hold time.monotonic() value
        clock = time.monotonic()
        #  reset countdown
        countdown = 5
        #  choose random side of dreidel to begin spinning on
        spin = random.randint(0, 3)
        #  choose random speed spin the dreidel
        speed = random.uniform(0.05, 0.1)
        #  set game state to True
        dreidel = True
        #  turn off reset state
        reset = False

	#  if the game is running...
    if dreidel:
        #  play the dreidel song
        audio.play(wave)

        #  while the dreidel song is playing...
        while audio.playing:
            #  if more time has passed than the random delay setup in reset...
            if (timer + speed) < time.monotonic():
                #  dreidel grid index is set to spin value
                dreidel_grid[0] = spin
                #  spin is increased by 1
                spin += 1
                #  timer is updated to current time
                timer = time.monotonic()

                #  if a second has passed...
                if time.monotonic() > (clock + 1):
                    print(clock)
                    print(spin)
                    #  the delay is increased to slow down the dreidel
                    speed += 0.05
                    #  clock is set to current time
                    clock = time.monotonic()
                    #  countdown value is decreased by 1
                    countdown -= 1

                #  if countdown is 0 aka 5 seconds has passed since the start of game...
                if countdown == 0:
                    #  if the bitmap is showing gimel...
                    #  you win!
                    if spin is gimel:
                        #  the servo turns 90 degrees to dump out chocolate coins
                        servo.angle = 0
                        #  2 second delay
                        time.sleep(2)
                        #  servo turns back to default position
                        for i in range(0, 90, 2):
                            servo.angle = i
                            time.sleep(0.1)
                        #  ensures servo is in default position
                        servo.angle = 90
                        #  stop playing the dreidel song
                        audio.stop()
                        #  game state is turned off
                        dreidel = False

                    #  if you didn't win...
                    else:
                        #  the dreidel song stops
                        audio.stop()
                        #  game state is turned off
                        dreidel = False

                #  if you are at the end of the sprite sheet...
                if spin > 3:
                    #  index is reset to 0
                    spin = 0

View on GitHub

Upload the Code, Audio File, Bitmap and Libraries to the MatrixPortal M4

After downloading the Project Bundle, plug your MatrixPortal M4 into the computer's USB port. You should see a new flash drive appear in the computer's File Explorer or Finder (depending on your operating system) called CIRCUITPY. Unzip the folder and copy the following items to the MatrixPortal M4's CIRCUITPY drive.

  • lib folder

  • code.py

  • dreidel_song.wav

  • dreidel.bmp

Your MatrixPortal M4 CIRCUITPY drive should look like this after copying the lib folder and the code.py, dreidel_song.wav and dreidel.bmp files.

Circuit_13

How the CircuitPython Code Works

"Spin" the Dreidel

The MatrixPortal M4's onboard down button and an IR breakbeam sensor are setup as digital inputs that can be read to start up the dreidel game sequence. If either input is triggered in the loop, then the reset state is set to True. This resets all of the game's values to launch a new sequence.

Download File

Copy Code
#  if the break beam sensor is triggered or the down button is pressed...
    if (not break_beam.value and beam_state) or not switch.value:
        #  update break beam state
        beam_state = False
        #  begin reset for game states
        reset = True
        print("pressed")
        #  quick delay
        time.sleep(0.1)

 

reset State

The reset state acts as a way to make sure everything is ready for a new round of dreidel. Most importantly, the values of spin and speed are set to random values. This allows for some variation in how the dreidel spins. spin affects the first index that is shown in the tilegrid and speed affects the speed at which the indexes change on the matrix.

Download File

Copy Code
#  if reset state...
    if reset:
        #  hold time.monotonic() value
        clock = time.monotonic()
        #  reset countdown
        countdown = 5
        #  choose random side of dreidel to begin spinning on
        spin = random.randint(0, 3)
        #  choose random speed spin the dreidel
        speed = random.uniform(0.05, 0.1)
        #  set game state to True
        dreidel = True
        #  turn off reset state
        reset = False

The Dreidel is Rolling

When the dreidel state is True, then the dreidel song will play through the STEMMA speaker and you'll see the dreidel sprite sheet iterate through the four sides with the different characters.

speed is used as the delay, with timer being reset to the current time with each iteration. This lets you avoid using time.sleep(), which would pause the entire loop.

Download File

Copy Code
#  if the game is running...
    if dreidel:
        #  play the dreidel song
        audio.play(wave)

        #  while the dreidel song is playing...
        while audio.playing:
            #  if more time has passed than the random delay setup in reset...
            if (timer + speed) < time.monotonic():
                #  dreidel grid index is set to spin value
                dreidel_grid[0] = spin
                #  spin is increased by 1
                spin += 1
                #  timer is updated to current time
                timer = time.monotonic()

The game is setup to "spin" the dreidel for 5 seconds. With each passing second, the value of speed is increased by 0.05 seconds. This slows the dreidel down gradually to mimic how it would spin in real life. countdown keeps track of how many seconds are left in the game.

Download File

Copy Code
#  if a second has passed...
                if time.monotonic() > (clock + 1):
                    print(clock)
                    print(spin)
                    #  the delay is increased to slow down the dreidel
                    speed += 0.05
                    #  clock is set to current time
                    clock = time.monotonic()
                    #  countdown value is decreased by 1
                    countdown -= 1

Once the game is over, it's determined whether or not you've won the pot of chocolate coins. If the matrix is showing gimel, which is the third index of the sprite sheet, then you've won! As a result, the servo will turn to dump out the chocolate coins for you and then turn back to its default position. The dreidel song will also stop playing and dreidel is set to False, stopping the game sequence.

If you didn't win, the song stops playing and the dreidel state is set to False, but there isn't any servo action.

Download File

Copy Code
#  if countdown is 0 aka 5 seconds has passed since the start of game...
                if countdown == 0:
                    #  if the bitmap is showing gimel...
                    #  you win!
                    if spin is gimel:
                        #  the servo turns 90 degrees to dump out chocolate coins
                        servo.angle = 0
                        #  2 second delay
                        time.sleep(2)
                        #  servo turns back to default position
                        for i in range(0, 90, 2):
                            servo.angle = i
                            time.sleep(0.1)
                        #  ensures servo is in default position
                        servo.angle = 90
                        #  stop playing the dreidel song
                        audio.stop()
                        #  game state is turned off
                        dreidel = False

                    #  if you didn't win...
                    else:
                        #  the dreidel song stops
                        audio.stop()
                        #  game state is turned off
                        dreidel = False

Wiring

Wiring_14

Make sure to use heat shrink for any exposed wire connections!

Insert the two breakbeam sensors into their slots at the top of the 3D printed lid.

Insert_15

Strip and tin the breakbeam sensors' ground and power connections. Solder their ground connections together. Then, solder their power connections together.

Connections_16

Connections_17

The JST 3-pin socket cable will plug into the servo motor. Solder the cable's ground connection to an additional wire.

Then, solder the breakbeam's shared ground connections to this ground junction. Cover the connection with heat shrink.

Jst_18

Jst_19

Solder an additional wire to the breakbeam sensors' power wires. Cover the connection with heat shrink.

Solder_20

Solder the following connections to the MatrixPortal M4's pins.

  • The group's ground connection to the MatrixPortal M4's ground pin

  • The breakbeam sensors' power connection to the MatrixPortal M4's 3V pin

  • The breakbeam sensors' data pin to A1

  • The JST socket's data pin to A4

Socket_21

Make a longer JST 3-pin cable

Cut a JST 3-pin cable in half. Then, strip and tin its wires.

Solder wires to each JST end to create a longer cable. Cover all connections with heat shrink. This cable will be used for the STEMMA speaker.

Wires_22

Wires_23

Assembly

Slide the servo motor into the servo motor slot on top of the 3D printed stand. Make sure to pass its wires through the cut-out on the side. Secure it with two M2 screws.

Assembly_24

Attach the STEMMA Speaker to the side of the 3D printed stand with four M2 screws and four M2 nuts.

Speaker_25

Attach the 3D printed lid to the top of the RGB matrix using three M3 screws.

Attach_26

Attach the 3D printed stand to the bottom of the RGB matrix using one M3 screw.

Stand_27

Plug the MatrixPortal M4 into the back of the RGB matrix.

Plug_28

Plug the STEMMA speaker into the MatrixPortal M4's onboard JST socket with the elongated 3-pin JST cable. This will connect the speaker to pin A0.

Cable_29

Cable_30

Plug the servo motor into the soldered 3-pin JST socket cable. This connects the servo to pin A4.

Motor_31

Attach the RGB matrix's power cable and the JST 3-pin socket cable's power pin to 5V on the MatrixPortal M4 by securing them with an M3 screw.

Attach the RGB matrix's ground cable to the MatrixPortal M4 with an M3 screw.

Plug the matrix power cable into the back of the matrix.

Power_32

Power_33

Super glue the servo horn to the 3D printed chocolate coin cup. Then, attach the servo horn to the servo motor.

Glue_34

Glue_35

Optional: cut a piece of LED acrylic to fit the 32x32 matrix and attach it to the front of the matrix with four squares of clear adhesive.

Acrylic_36

Play Dreidel!

After powering up the MatrixPortal M4 and the RGB matrix, you can begin your game of dreidel two ways: either by dropping a chocolate coin into the coin slot to trigger the break beam sensor or by pressing the down button on the side of the MatrixPortal M4.

Play_37

The classic dreidel song will begin playing through the STEMMA speaker and the dreidel will "spin" on the RGB matrix, iterating through the dreidel sprite sheet.

A dreidel has four characters, one on each side. The characters are:

  • Shin (ש)

  • He (ה)

  • Gimel (ג)

  • Nun (נ)

Traditionally when you are playing dreidel, each side has a different meaning in the game. For the purposes of this version though, you will keep adding coins to the pot until you roll gimel; winning the game.

Play_38

Play_39

Play_40

Play_41

For more information on the traditional dreidel game rules, check out this page in the Circuit Playground TFT Gizmo Dreidel Learn Guide

If you don't roll gimel to win the game, don't worry! You can keep dropping in coins or pressing the down button to launch a new cycle.

Cycle_42

If you do roll gimel though, congratulations! You've won the pot! The servo motor will tip the cup holding all of the chocolate coins, spilling them out for you to feast on.

Roll_43

制造商零件编号 4745
ADAFRUIT MATRIX PORTAL - CIRCUIT
Adafruit Industries LLC
制造商零件编号 2026
32X32 RGB LED MATRIX PANEL 5MM P
Adafruit Industries LLC
制造商零件编号 2168
SENSOR THRU-BEAM 508MM OPEN COL
Adafruit Industries LLC
制造商零件编号 4326
SERVOMOTOR RC 3-6V W/ 3-PIN JST
Adafruit Industries LLC
制造商零件编号 3885
STEMMA SPEAKER & AUDIO AMPLIFIER
Adafruit Industries LLC
制造商零件编号 4046
JST PH 3-PIN SOCKET TO COLOR COD
Adafruit Industries LLC
制造商零件编号 4336
JST PH 3-PIN PLUG-PLUG CABLE
Adafruit Industries LLC
制造商零件编号 4749
BLACK LED DIFFUSION ACRYLIC PANE
Adafruit Industries LLC
制造商零件编号 4298
AC/DC WALL MNT ADAPTER 5.1V 15W
Adafruit Industries LLC
制造商零件编号 4685
BLACK NYLON SCREW AND STAND-OFF
Adafruit Industries LLC
Add all DigiKey Parts to Cart
TechForum

Have questions or comments? Continue the conversation on TechForum, DigiKey's online community and technical resource.

Visit TechForum