Page 1 of 1

RTTTL - Ring Tone Text Transfer Language driving a Piezo Speaker

Posted: Sun Jul 24, 2016 5:54 am
by dhylands
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.

Re: RTTTL - Ring Tone Text Transfer Language driving a Piezo Speaker

Posted: Thu May 31, 2018 12:01 am
by mcauser
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/

Re: RTTTL - Ring Tone Text Transfer Language driving a Piezo Speaker

Posted: Tue Feb 19, 2019 12:30 pm
by Trapsis
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)

Re: RTTTL - Ring Tone Text Transfer Language driving a Piezo Speaker

Posted: Tue Feb 19, 2019 5:01 pm
by dhylands
You probably don't want this line:

Code: Select all

tone = PWM(Pin(speaker_pin, Pin.OUT), freq=int(freq), duty=512)
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.

Re: RTTTL - Ring Tone Text Transfer Language driving a Piezo Speaker

Posted: Thu Feb 21, 2019 2:41 pm
by Trapsis
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

Posted: Thu Feb 21, 2019 3:19 pm
by dhylands
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

Posted: Mon Feb 22, 2021 8:29 pm
by scruss
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)