# Ported code from https://www.cytron.io/tutorial/metronome-maker-pi-pico-programmed-with-circuitpython
import time
import machine
# Assuming NeoPixel and I2C LCD libraries are available for MicroPython
from machine import Pin, I2C, PWM
from pico_i2c_lcd import I2cLcd # Replace with actual MicroPython library
# Global consts
LCD_SDA = 4
LCD_SCL = 5
LCD_FRQ = 400000
BUZZER_PIN = 18
BEEP_DURATION = 0.05
BUTTON1_PIN = 20
BUTTON2_PIN = 21
BUTTON3_PIN = 22
DEBOUNCE = 200
# Initializae the lcd
def initialize_i2c_lcd(sda_pin, scl_pin, i2c_freq):
i2c_bus = I2C(0, sda=Pin(sda_pin), scl=Pin(scl_pin), freq=i2c_freq)
i2c_address = i2c_bus.scan()[0]
return I2cLcd(i2c_bus, i2c_address, 2, 16), i2c_address
# Define Sound
def metronome(accent):
if accent == 1: # Put emphasis on downbeat
buzzer = PWM(Pin(BUZZER_PIN))
buzzer.freq(1800)
time.sleep(BEEP_DURATION)
buzzer.duty_u16(0)
else:
buzzer = PWM(Pin(BUZZER_PIN))
buzzer.freq(1200)
time.sleep(BEEP_DURATION)
buzzer.duty_u16(0)
def main():
button1 = Pin(BUTTON1_PIN, Pin.IN, Pin.PULL_UP)
button1_count = 0
button2 = Pin(BUTTON2_PIN, Pin.IN, Pin.PULL_UP)
button2_count = 0
button3 = Pin(BUTTON3_PIN, Pin.IN, Pin.PULL_UP)
button3_count = 0
debounce_set=DEBOUNCE
debounce_time=0
tempo = 120
delay = 60 / tempo
time_signature = 4
tempo_increment = 1
beat = 1
lcd, i2c = initialize_i2c_lcd(sda_pin=LCD_SDA, scl_pin=LCD_SCL, i2c_freq=LCD_FRQ)
lcd.blink_cursor_on()
lcd.putstr("Metronome on\nMaker Pi Pico")
time.sleep(2)
lcd.clear()
lcd.putstr("Tempo: {} \nTSign: {}/4 ".format(tempo, time_signature))
t0 = time.ticks_ms()
while True:
if (button1.value() is 0) and (time.ticks_ms()-debounce_time) > debounce_set: # Button 1 is pressed
button1_count+=1
debounce_time=time.ticks_ms()
if tempo > 40:
tempo -= tempo_increment
delay = 60 / tempo
lcd.move_to(0,0)
lcd.putstr("Tempo: {} \nTSign: {}/4 ".format(tempo, time_signature))
elif (button2.value() is 0) and (time.ticks_ms()-debounce_time) > debounce_set: # Button 2 is pressed
button2_count+=1
debounce_time=time.ticks_ms()
if tempo < 330:
tempo += tempo_increment
delay = 60 / tempo
lcd.move_to(0,0)
lcd.putstr("Tempo: {} \nTSign: {}/4 ".format(tempo, time_signature))
elif (button3.value() is 0) and (time.ticks_ms()-debounce_time) > debounce_set: # Button 3 is pressed
button3_count+=1
debounce_time=time.ticks_ms()
time_signature = 3 if time_signature == 4 else 4
lcd.move_to(0,0)
lcd.putstr("Tempo: {} \nTSign: {}/4 ".format(tempo, time_signature))
beat = 1 # start with downbeat
elif time.ticks_diff(time.ticks_ms(), t0) >= delay * 1000:
t0 = time.ticks_ms() # reset time before click to maintain accuracy
metronome(beat)
beat -= 1
if beat == 0:
beat = time_signature
if __name__ == "__main__":
main()