I've put together an RTTTL parser and a sample which drives a piezo speaker.
The RTTTL parser can be found here: https://github.com/dhylands/upy-rtttl
I put together a quick video (so you can hear it playing a tune): https://www.youtube.com/watch?v=TadV2AEvfww
The pyb_test.py file has the function which plays a single tone, and rttlt.py has the RTTTL parser.
RTTTL - Ring Tone Text Transfer Language driving a Piezo Speaker
Re: RTTTL - Ring Tone Text Transfer Language driving a Piezo Speaker
Works great with my pyboard + Seeed Grove buzzer!
There's millions of RTTTL examples a short Google search away.
You can even play them online:
https://adamonsoon.github.io/rtttl-play/
I used this tool to help figure out the frequencies I wanted to play:
http://www.szynalski.com/tone-generator/
There's millions of RTTTL examples a short Google search away.
You can even play them online:
https://adamonsoon.github.io/rtttl-play/
I used this tool to help figure out the frequencies I wanted to play:
http://www.szynalski.com/tone-generator/
Re: RTTTL - Ring Tone Text Transfer Language driving a Piezo Speaker
Very cool! Just what I'm looking for. I'm trying to adapt your code to work on an ESP32 board using the machine.PWM library. I'm still debugging it but there is not much that needed to change. It doesn't get through a whole song before failing. Here is the code if you are curious:
from rtttl import RTTTL
import songs
import time
from machine import Pin, PWM
speaker_pin = 14 # Speaker is connected to this DIGITAL pin
# Initialize input/output pins
tone = PWM(Pin(speaker_pin, Pin.OUT), freq=0, duty=512)
def play_tone(freq, msec):
#print('freq = {:6.1f} msec = {:6.1f}'.format(freq, msec))
if freq > 0:
tone = PWM(Pin(speaker_pin, Pin.OUT), freq=int(freq), duty=512)
time.sleep(msec*0.001) # Play for a number of msec
tone.deinit() # Stop playing
time.sleep(0.05) # Delay 50 ms between notes
tune = RTTTL(songs.find('Super Mario - Main Theme'))
for freq, msec in tune.notes():
play_tone(freq, msec)
from rtttl import RTTTL
import songs
import time
from machine import Pin, PWM
speaker_pin = 14 # Speaker is connected to this DIGITAL pin
# Initialize input/output pins
tone = PWM(Pin(speaker_pin, Pin.OUT), freq=0, duty=512)
def play_tone(freq, msec):
#print('freq = {:6.1f} msec = {:6.1f}'.format(freq, msec))
if freq > 0:
tone = PWM(Pin(speaker_pin, Pin.OUT), freq=int(freq), duty=512)
time.sleep(msec*0.001) # Play for a number of msec
tone.deinit() # Stop playing
time.sleep(0.05) # Delay 50 ms between notes
tune = RTTTL(songs.find('Super Mario - Main Theme'))
for freq, msec in tune.notes():
play_tone(freq, msec)
Re: RTTTL - Ring Tone Text Transfer Language driving a Piezo Speaker
You probably don't want this line: inside the play_tone function.
You should initialize the PWM object once (outside the function) and only change the frequency inside the play_tone function.
Code: Select all
tone = PWM(Pin(speaker_pin, Pin.OUT), freq=int(freq), duty=512)
You should initialize the PWM object once (outside the function) and only change the frequency inside the play_tone function.
Re: RTTTL - Ring Tone Text Transfer Language driving a Piezo Speaker
Thanks for the advice. This works better and will get through the tune ok, but the timing seems off. I think it is the rests (pauses) that are not working well (sorry, code block not formatted. still noob here I guess :) )
Code: Select all
from rtttl import RTTTL
import songs
import time
from machine import Pin, PWM
speaker_pin = 14 # Speaker is connected to this DIGITAL pin
# Initialize input/output pins
tone = PWM(Pin(speaker_pin, Pin.OUT), freq=0, duty=0)
def play_tone(freq, msec):
print('freq = {:6.1f} msec = {:6.1f}'.format(freq, msec))
if freq > 0:
tone.duty(10)
tone.freq(int(freq))
time.sleep(msec*0.001) # Play for a number of msec
tone.duty(0) # Stop playing
time.sleep(0.01) # Delay 50 ms between notes
tune = RTTTL(songs.find('Super Mario - Main Theme'))
for freq, msec in tune.notes():
play_tone(freq, msec)
tone.deinit()
Re: RTTTL - Ring Tone Text Transfer Language driving a Piezo Speaker
You have the time.sleep(msec*0.001) inside the if. Try unindenting that line.
Re: RTTTL - Ring Tone Text Transfer Language driving a Piezo Speaker
I've added an example for running on the Raspberry Pi Pico, and entered a pull request. It's slightly different from all of the other variants.
Code: Select all
# Raspberry Pi Pico RTTTL example
# scruss - 2021-02: sorry, not sorry ...
from rtttl import RTTTL
from time import sleep_ms
from machine import Pin, PWM
# nicked from https://gist.github.com/mhungerford/0af269ee46c0d44a813c
NvrGonna = 'NvrGonna:d=4,o=5,b=200:8g,8a,8c6,8a,e6,8p,e6,8p,d6.,p,8p,8g,8a,8c6,8a,d6,8p,d6,8p,c6,8b,a.,8g,8a,8c6,8a,2c6,d6,b,a,g.,8p,g,2d6,2c6.,p,8g,8a,8c6,8a,e6,8p,e6,8p,d6.,p,8p,8g,8a,8c6,8a,2g6,b,c6.,8b,a,8g,8a,8c6,8a,2c6,d6,b,a,g.,8p,g,2d6,2c6.'
# pin 26 - GP20; just the right distance from GND at pin 23
# to use one of those PC beepers with the 4-pin headers
pwm = PWM(Pin(20))
def play_tone(freq, msec):
# print('freq = {:6.1f} msec = {:6.1f}'.format(freq, msec))
if freq > 0:
pwm.freq(int(freq)) # Set frequency
pwm.duty_u16(32767) # 50% duty cycle
sleep_ms(int(0.9 * msec)) # Play for a number of msec
pwm.duty_u16(0) # Stop playing for gap between notes
sleep_ms(int(0.1 * msec)) # Pause for a number of msec
tune = RTTTL(NvrGonna)
for freq, msec in tune.notes():
play_tone(freq, msec)