# Designed by Larry Streck for a drummer who hates using a click, but desperately needs one.
import utime
import machine
from machine import Pin, I2C
from LCD1602 import LCD
import neopixel
def button_increase_handler(pin):
global bpm, beat_duration
utime.sleep_ms(20)
if not pin.value():
bpm += 1
beat_duration = 60 / bpm
lcd.write(0, 0, " Tempo: {} BPM ".format(bpm))
def button_decrease_handler(pin):
global bpm, beat_duration
utime.sleep_ms(20)
if not pin.value():
bpm -= 1
beat_duration = 60 / bpm
lcd.write(0, 0, " Tempo: {} BPM ".format(bpm))
def button_time_signature_handler(pin):
global current_time_signature_index, beat_duration
utime.sleep_ms(20)
if not pin.value():
current_time_signature_index = (current_time_signature_index + 1) % len(time_signatures)
beats_per_measure, beat_type = time_signatures[current_time_signature_index]
beat_duration = 60 / bpm / (beat_type / 4)
lcd.write(0, 1, " ")
lcd.write(0, 1, " Time Sig: {}/{}".format(beats_per_measure, beat_type))
led_pin = machine.Pin(11)
button_increase_pin = machine.Pin(1, machine.Pin.IN, machine.Pin.PULL_UP)
button_decrease_pin = machine.Pin(2, machine.Pin.IN, machine.Pin.PULL_UP)
button_time_signature_pin = machine.Pin(0, machine.Pin.IN, machine.Pin.PULL_UP)
num_leds = 1
led_strip = neopixel.NeoPixel(led_pin, num_leds)
adc = machine.ADC(26)
lcd = LCD(addr=0x27, blen=1, sda_pin=4, scl_pin=5, freq=400000)
lcd.clear()
lcd.message("Visual Metronome\n by Larry Streck")
button_increase_pin.irq(trigger=Pin.IRQ_FALLING, handler=button_increase_handler)
button_decrease_pin.irq(trigger=Pin.IRQ_FALLING, handler=button_decrease_handler)
button_time_signature_pin.irq(trigger=Pin.IRQ_FALLING, handler=button_time_signature_handler)
time_signatures = [
(2, 4), # 4/4 time signature
(3, 4), # 2/4 time signature
(4, 4), # 3/4 time signature
(5, 7), # 5/7 time signature
(3, 8), # 3/8 time signature
(6, 8), # 6/8 time signature
(7, 8), # 7/8 time signature
(9, 8), # 9/8 time signature
(12, 8) # 12/8 time signature
]
# Initial time signature index
current_time_signature_index = 2
# Define colors for each time signature
time_signature_colors = {
(4, 4): ((255, 0, 0), (0, 255, 0)),
(2, 4): ((255, 0, 0), (0, 255, 0)),
(3, 4): ((255, 0, 0), (0, 255, 0)),
(5, 7): ((255, 0, 0), (0, 255, 0)),
(3, 8): ((255, 0, 0), (0, 255, 0)),
(6, 8): ((255, 0, 0), (0, 255, 0)),
(7, 8): ((255, 0, 0), (0, 255, 0)),
(9, 8): ((255, 0, 0), (0, 255, 0)),
(12, 8): ((255, 0, 0), (0, 255, 0))
}
def flash_led(accent_color, other_color, beats_per_measure):
global beat_count
if beat_count % beats_per_measure == 0:
led_strip[0] = accent_color
else:
led_strip[0] = other_color
led_strip.write()
utime.sleep(0.1)
led_strip[0] = (0, 0, 0)
led_strip.write()
bpm = 120
beat_duration = 60 / bpm
beat_count = 0
while True:
beats_per_measure, beat_type = time_signatures[current_time_signature_index]
accent_color, other_color = time_signature_colors[(beats_per_measure, beat_type)]
flash_led(accent_color, other_color, beats_per_measure)
utime.sleep(beat_duration)
beat_count += 1
if beat_count == beats_per_measure:
beat_count = 0