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
¥365.90
Details
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