Maker.io main logo

Metronome CLUE

2024-02-28 | By Adafruit Industries

License: See Original Project Displays

Courtesy of Adafruit

Guide by John Park

Overview

 

Practice makes perfect when it comes to learning a musical instrument ‎‎-- and sometimes you need a metronome to really drive home the ‎tempo. In this project you'll learn how to make a metronome using the ‎CLUE board and CircuitPython.‎

As a bonus, you can 3D print a classic metronome style stand for your ‎CLUE!‎

Parts

These are the parts you'll need:‎

Optional

  • Little Rubber Bumper Feet - Pack of 4‎

Looking for a PyBadge metronome? Check this one ‎out: https://github.com/gmeader/pybadge/blob/master/metronome.py

CircuitPython on CLUE

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 flash ‎drive to iterate.‎

The following instructions will show you how to install CircuitPython. If ‎you've already installed CircuitPython but are looking to update it or ‎reinstall it, the same steps work for that as well!‎

Set up CircuitPython Quick Start!‎

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

Download the latest version of CircuitPython for CLUE from ‎circuitpython.org

Click the link above to download the latest version of ‎CircuitPython for the CLUE.‎

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

download_1

Plug your CLUE 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 on the top (magenta arrow) on your ‎board, and you will see the NeoPixel RGB LED (green arrow) turn green. ‎If it turns red, check the USB cable, try another USB port, ‎etc. Note: The little red LED next to the USB connector will pulse red. ‎That's ok!‎

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

board_2

You will see a new disk drive appear called CLUEBOOT.‎

Drag the adafruit-circuitpython-clue-etc.uf2 file to CLUEBOOT.‎

drag_3

drag_4

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

If this is the first time, you're installing CircuitPython or you're doing a ‎completely fresh install after erasing the filesystem, you will have two ‎files - boot_out.txt, and code.py, and one folder - lib on ‎your CIRCUITPY drive.‎

If CircuitPython was already installed, the files present before reloading ‎CircuitPython should still be present on your CIRCUITPY drive. Loading ‎CircuitPython will not create new files if there was already a ‎CircuitPython filesystem present.‎

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

done_5

CLUE CircuitPython Libraries

The CLUE is packed full of features like a display and a ton of sensors. ‎Now that you have CircuitPython installed on your CLUE, you'll need to ‎install a base set of CircuitPython libraries to use the features of the ‎board with CircuitPython.‎

Follow these steps to get the necessary libraries installed.‎

Installing CircuitPython Libraries on ‎your CLUE

If you do not already have a lib folder on your CIRCUITPY drive, create ‎one now.‎

Then, download the CircuitPython library bundle that matches your ‎version of CircuitPython from CircuitPython.org.‎

Download the latest library bundle from circuitpython.org

The bundle downloads as a .zip file. Extract the file. Open the resulting ‎folder.‎

folder_6

Open the lib folder found within.‎

open_7

Once inside, you'll find a lengthy list of folders and .mpy files. To ‎install a CircuitPython library, you drag the file or folder from ‎the bundle lib folder to the lib folder on your CIRCUITPY drive.

list_8

Copy the following folders and files from the bundle lib ‎folder to the lib folder on your CIRCUITPY drive:

  • adafruit_apds9960
  • adafruit_bmp280.mpy
  • adafruit_bus_device
  • adafruit_clue.mpy
  • adafruit_display_shapes
  • adafruit_display_text
  • adafruit_lis3mdl.mpy
  • adafruit_lsm6ds
  • adafruit_register
  • adafruit_sht31d.mpy
  • adafruit_slideshow.mpy
  • neopixel.mpy

Your lib folder should look like the image on the left. These libraries ‎will let you run the demos in the CLUE guide.‎

lib_9

Code the Metronome

Libraries

We'll need to make sure we have these libraries installed. (Check out ‎this link on installing libraries if needed.)‎

  • adafruit_apds9960
  • adafruit_bmp280.mpy
  • adafruit_bus_device
  • adafruit_clue.mpy
  • adafruit_display_shapes
  • adafruit_display_text
  • adafruit_lis3mdl.mpy
  • adafruit_lsm6ds.mpy
  • adafruit_register
  • adafruit_sht31d.mpy
  • neopixel.mpy
  • simpleio.mpy

library_10

Text Editor

Adafruit recommends using the Mu editor for editing your ‎CircuitPython code. You can get more info in this guide.‎

Alternatively, you can use any text editor that saves files.‎

Code

Copy the code from the code-block below and paste it into the Mu ‎editor and save it to your CLUE as code.py (or copy code.py from the ‎zip file and place on the CIRCUITPY drive.)‎

Download Project Bundle

Copy Code
# SPDX-FileCopyrightText: 2020 John Park for Adafruit Industries
#
# SPDX-License-Identifier: MIT

import time
import board
import displayio
import terminalio
import simpleio
from adafruit_display_text import label
from adafruit_display_shapes.rect import Rect
from adafruit_clue import clue

blink_light = True # optional flashing backlight on accent
tempo = 120 # in bpm
print("BPM: {}".format(tempo))
time_signature = 4 # Beats per measure
BEEP_DURATION = 0.05
delay = 60 / tempo

clue.display.brightness = 1.0
clue.pixel.brightness = 0.2
screen = displayio.Group()
TEAL = 0x009E98
LT_TEAL = 0x000F0F
GRAY = 0x02403E
BLACK = 0x000000
WHITE = 0xFFFFFF
YELLOW = 0xFFFF00

clue.pixel.fill(0) # Turn off the pixel

# Setup screen
# BG
color_bitmap = displayio.Bitmap(240, 240, 1)
color_palette = displayio.Palette(1)
color_palette[0] = TEAL
bg_sprite = displayio.TileGrid(color_bitmap, x=0, y=0, pixel_shader=color_palette)
screen.append(bg_sprite)

# title box
title_box = Rect(0, 0, 240, 60, fill=GRAY, outline=None)
screen.append(title_box)

# title text
title_label = label.Label(
terminalio.FONT, text="Metronome", scale=4, color=TEAL
)
title_label.x = 14
title_label.y = 26
screen.append(title_label)

# interval text
interval_label = label.Label(
terminalio.FONT, text="{} BPM".format(tempo), scale=5, color=WHITE
)
interval_label.x = 20
interval_label.y = 95
screen.append(interval_label)

# mid line
mid_line = Rect(0, 134, 240, 3, fill=GRAY, outline=None)
screen.append(mid_line)

# vert line
vert_line = Rect(117, 134, 3, 56, fill=GRAY, outline=None)
screen.append(vert_line)

# Signature text
sig_label = label.Label(
terminalio.FONT,
text="{}/4".format(time_signature),
scale=3,
color=BLACK,
)
sig_label.x = 30
sig_label.y = 160
screen.append(sig_label)

# play text
play_label = label.Label(
terminalio.FONT, text=" play", scale=3, color=BLACK
)
play_label.x = 138
play_label.y = 160
screen.append(play_label)

# footer line
footer_line = Rect(0, 190, 240, 3, fill=GRAY, outline=None)
screen.append(footer_line)

# increment label
increment_label = label.Label(
terminalio.FONT, text="-1 +1", scale=3, color=GRAY
)
increment_label.x = 3
increment_label.y = 220
screen.append(increment_label)

# show the screen
clue.display.root_group = screen


def metronome(accent): # Play metronome sound and flash display
clue.display.brightness = 0.5 # Dim the display slightly
if accent == 1: # Put emphasis on downbeat
if blink_light:
clue.pixel.fill(YELLOW) # Flash the pixel
simpleio.tone(board.SPEAKER, 1800, BEEP_DURATION)
else: # All the other beats in the measure
if blink_light:
clue.pixel.fill(LT_TEAL) # Flash the pixel
simpleio.tone(board.SPEAKER, 1200, BEEP_DURATION)
if blink_light:
clue.pixel.fill(0) # Turn off the pixel
clue.display.brightness = 1.0 # Restore display to normal brightness


time.sleep(0.2)
tempo_increment = 1 # increment for tempo value setting
feedback_mode = 0 # 0 is sound and visual, 1 is sound only, 2 is visual only
running = False

t0 = time.monotonic() # set start time

while True:

# play/pause
if clue.button_b:
if play_label.text == " play":
play_label.text = "pause"
else:
play_label.text = " play"
running = not running
time.sleep(0.4)
beat = 1 # start with downbeat

# Time Signature change
if clue.button_a:
print("sig change")
if time_signature == 4:
time_signature = 3
else:
time_signature = 4
sig_label.text = "{}/4".format(time_signature)
time.sleep(0.4)
beat = 1 # start with downbeat

if running and (time.monotonic() - t0) >= delay:
t0 = time.monotonic() # reset time before click to maintain accuracy
metronome(beat)
beat = beat - 1
if beat == 0: # if the downbeat was just played, start at top of measure
beat = time_signature

# tempo changes
if clue.touch_0:
if tempo_increment is 1:
tempo_increment = 10
increment_label.text = "-10 +10"
else:
tempo_increment = 1
increment_label.text = "-1 +1"
time.sleep(0.2) # debounce

if clue.touch_1:
if tempo > 40:
tempo = tempo - tempo_increment
delay = 60 / tempo
interval_label.text = "{} BPM".format(tempo)
time.sleep(0.2) # debounce

if clue.touch_2:
if tempo < 330:
tempo = tempo + tempo_increment
delay = 60 / tempo
interval_label.text = "{} BPM".format(tempo)
time.sleep(0.2) # debounce

‎View on GitHub

How to Use the CLUE Metronome

  • Press B button to play/pause
  • Press A button to switch time signatures
  • Press touch pad #0 to switch BPM adjustment increments
  • Press touch pads #1 or #2 to decrease or increase tempo

 

3D Print the Metronome Stand‎

stand_11

Download the .stl files and print the parts using PLE at 0.2mm layer ‎height, no support needed.‎

The bottom cover won't be necessary.‎

STL Files

Assembly

Place the CLUE into the case back and then snap-fit the front cover ‎into place.‎

place_12

Push the CLUE in its case into the stand face until the front plate is ‎just proud of the surface.‎

push_13

You can optionally add a bead of CA glue along the back edges for a ‎more secure fit.‎

add_15

To prevent sliding, adhere three rubber bumper feet to the underside ‎of the base.‎

slip_16

slip_17

Set the face plate and CLUE into the base as shown.

face_18

clue_19

制造商零件编号 4500
CLUE NRF52840 EXPRESS
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