Pages: [1] 2   Go Down
Author Topic: Tone generation library  (Read 8049 times)
0 Members and 1 Guest are viewing this topic.
Toronto, ON
Offline Offline
Full Member
***
Karma: 10
Posts: 233
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

For those who are interested, I've created a tone generation library for the Arduino.  It is non-blocking (it will play tones while the rest of your program is working) and produces square wave tones only.

http://code.google.com/p/arduino-tone/

Tones can be played on any pin, but you are limited to the number of tones (depending on the type of Arduino you have).

Just connect the digital pin to a speaker with an in-line series resistor - say 1K, and the other side of the speaker to ground (GND).

You could also use a potentiometer to control the volume - I'd suggest a 10K pot.

Included in the library are three examples:

1) simple dual tone player (notes selected through serial port)
2) DTMF (Dual Tone Multiple Frequency) example.
3) RTTTL (Ring Tone Text Transfer Language) example.

Try it out!  Tell me what you think.

b
Logged


Toronto, ON
Offline Offline
Full Member
***
Karma: 10
Posts: 233
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Tom Igoe wrote this easy to use Theremin example.  See how you can translate the values from the analog pin to frequencies directly using the map() function?

Code:
/*
   Theremin

  Plays notes based on a sensor reading
  uses Tone library by Brett Hagman
  http://code.google.com/p/arduino-tone/

  circuit:
  * potentiometer on analog in 0
  * 8-ohm speaker on digital pin 8

  created 18 Aug 2009
  by Tom Igoe

  */

#include <Tone.h>


Tone musicMaker;              // instance of the tone library
int lastSensorReading = 0;    // value of the previous sensor reading
int threshold = 10;           // minimum difference between readings


void setup() {
   Serial.begin(9600);
   // start the music:
   musicMaker.begin(11);
}

void loop() {
   // read an analog input:
   int sensorReading = analogRead(0);
   // map the analog readings to a range from A3 to G5:
   int thisTone = map(sensorReading, 0, 1023, NOTE_A3, NOTE_G5);
   // if the sensor reading is different enough
   // from the last sensor reading, change the pitch:
   if (abs(sensorReading - lastSensorReading) > threshold) {
     musicMaker.play(thisTone);
     // save the current sensor reading
     // for next time through the loop:
     lastSensorReading = sensorReading;
   }
}
Logged


0
Offline Offline
Jr. Member
**
Karma: 0
Posts: 60
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

These examples look great. Can't wait to try them out.

Many thanks for sharing your code.
Logged

Denver
Offline Offline
God Member
*****
Karma: 19
Posts: 778
Inactive - PM
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Wow! Great job with this library.  smiley The RTTL reader is way cool and a lot of fun. I've only heard it with a piezo so far, but it literally rocks!

Thanks for contributing this. It's really a sound improvement for the Arduino.
« Last Edit: September 01, 2009, 03:33:36 pm by BroHogan » Logged

"Data is not information, information is not knowledge, knowledge is not understanding, understanding is not wisdom."
~ Clifford Stoll

0
Offline Offline
Newbie
*
Karma: 0
Posts: 17
I find your lack of faith disturbing.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

I was looking for just this kind of code library just yesterday. Absolutely brilliant! It works with a piezo transducer I picked up at Radio Shack too. Thanks!  smiley-grin
Logged

0
Offline Offline
Sr. Member
****
Karma: 3
Posts: 325
KC4MM
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Works well here too. Kudos.
Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 17
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

There is also a snippet in the daniweb library for windows machines, you can find it

Regards...

Rocky
Logged

/dev/null
Offline Offline
Newbie
*
Karma: 0
Posts: 16
Arduino rocks
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Cool stuff!
Thanks for sharing the code.
Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 8
Arduino rocks
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

nice one thanxxx
Logged

Argentina
Offline Offline
Full Member
***
Karma: 0
Posts: 186
Sé feliz
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Very cool! I will try it.
Thanks!
Julián
Logged

0
Offline Offline
Newbie
*
Karma: 0
Posts: 8
Arduino rocks
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

awesome work keep it up..........
Logged

Global Moderator
Dallas
Offline Offline
Shannon Member
*****
Karma: 176
Posts: 12283
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Does the Tone Library work with an ATmega328P running at 1MHz from the internal oscillator?  The tones seem way too low but I could easily be doing something wrong.

Is anyone else interested in the Tone Library working at 1MHz?
Logged

London
Offline Offline
Faraday Member
**
Karma: 8
Posts: 6240
Have fun!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Why not modify the play method in that library to multiply the given frequency by 16. You could use the F_CPU define or clockCyclesPerMicrosecond() to check the actual clock frequency assuming you are setting this in your boards.txt file

adding something like this at the top of the play method should work (although I have not tried it):
 frequency = frequency * (16 / clockCyclesPerMicrosecond());
« Last Edit: November 23, 2009, 03:07:46 am by mem » Logged

Global Moderator
Dallas
Offline Offline
Shannon Member
*****
Karma: 176
Posts: 12283
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Thank you for the reply.

Quote
Why not modify the play method in that library to multiply the given frequency by 16
Good thinking!  That will at least tell me if I'm doing somthing wrong or if there's a deficiency in the library.

Quote
You could use the F_CPU define
The library uses F_CPU to calculate the configuration values for the counter.  Unfortunately, I suspect the various frequency / divisor ranges are designed to only work for 16MHz and 8MHz clocks.

Quote
assuming you are setting this in your boards.txt file
I am.  And from some blink / delay testing I think I did it correctly.

Quote
adding something like this at the top of the play method should work (although I have not tried it):
 frequency = frequency * (16 / clockCyclesPerMicrosecond());
I think it will work for 16MHz and 1MHz but it will probably not work for 8MHz.  But, I'll certainly try it.
Logged

Toronto, ON
Offline Offline
Full Member
***
Karma: 10
Posts: 233
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

The prescalar selection for the timers were based on 16 MHz (and they we're OK for 8 MHz, but not great).

I changed the code to scan for the best prescalar based on the frequency and cpu clock.

I've uploaded a new version - I haven't tested it out on hardware just yet, but it does compile.  Please test it and let me know if it works for you.

http://code.google.com/p/arduino-tone/source/browse/trunk/Tone.cpp

b
Logged


Pages: [1] 2   Go Up
Jump to: