Pages: 1 [2]   Go Down
Author Topic: Tone generation library  (Read 10075 times)
0 Members and 1 Guest are viewing this topic.
London
Offline Offline
Tesla Member
***
Karma: 10
Posts: 6255
Have fun!
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

It works well for higher frequencies but a tone that should be 100Hz is 555Hz on one of the pins.

I tested using this sketch on an a standard 16mhz ATmega168 :
Code:
#include <Tone.h>

int notes[] = { 20,50, 100, 1000, 5000, 10000, 15000, 20000};
Tone notePlayer[2];

void setup(void)
{
  Serial.begin(9600);
  notePlayer[0].begin(11);
  notePlayer[1].begin(12);
}

void loop(void)
{
  char c;

  if(Serial.available())
  {
    c = Serial.read();
    
    switch(c)
    {
      case 'a' ... 'h':

        notePlayer[0].play(notes[c - 'a']);
        Serial.print("pin 11:");
        Serial.println(notes[c - 'a']);
        break;
      case 's':
        notePlayer[0].stop();
        break;

      case 'A'...'H':  
        notePlayer[1].play(notes[c - 'A']);
        Serial.print("pin 12:");
        Serial.println(notes[c - 'A']);
        break;
      case 'S':
        notePlayer[1].stop();
        break;

      default:
        notePlayer[1].stop();
        break;
    }
  }
}
Setting both outputs to 100Hz, I measured a period of just over 1.8ms on pin12. The period onr pin 11 was spot on (9.982ms).
« Last Edit: November 23, 2009, 08:01:46 am by mem » Logged

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

The original code was never intended to produce frequencies below 123 Hz, because @16MHz, the 16 bit timers (set at ck/1) could not kill enough time to produce tones lower than that.

Thus, I've rewritten the code to accommodate almost all frequencies now on the 16 bit timers (2 -> 65535 Hz).  8 Bit timers will still choke, but now at 31 Hz.

http://code.google.com/p/arduino-tone/source/browse/#svn/trunk

(note: you'll have to get Tone.h as well now, because of the declaration change).

Coding Badly: Test it at 1MHz - let me know how it goes.

b
Logged


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

Thanks bhagman and mem!  I should have time tonight for some testing.

[edit]The results seem to be the same.  At 8MHz NOTE_B2 is lower than at 16MHz.  At 1MHz NOTE_B2 is even lower.  I suspect I need to sleep on it... Good night to all! (or morning or afternoon to those not in America)[/edit]
« Last Edit: November 24, 2009, 02:52:19 am by bcook » Logged

Montreal
Offline Offline
Full Member
***
Karma: 0
Posts: 185
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Hi, i try, this and it seems that i can only have 2 tone?
the third one does not run?
i have a atmega 328 and it should give me 3 tone (at least this is what i anderstand in the .cpp and .h
am i wrong?
Thanks
Patgadget
Code:
#include <Tone.h>
Tone tone1;
Tone tone2;
Tone tone3;
void setup()
{
  tone1.begin(13);
  tone2.begin(12);
  tone3.begin(6);
  tone3.play(100);
  tone1.play(35);
  tone2.play(35);
}
void loop()
{
}
Logged

Patgadget
Montreal

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

Patgadget: Silly boundary conditions.  Amazing what a difference >= makes compared to >.  Fixed.  Get the latest version from Google Code SVN.  Thanks for finding it.

Coding Badly: hmmm... methinks you have something else going on.  Are you compiling the sketches against F_CPU set to 1MHz?  Or are you just compiling based on an Duemilanove w/ATmega32 (@16 MHz) and putting it into a chip running at 1MHz?  I'm betting dollars to donuts that you're doing the latter.

b
Logged


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

Quote
Coding Badly: hmmm... methinks you have something else going on
That's what I suspect but I cannot figure out what.

Quote
Are you compiling the sketches against F_CPU set to 1MHz?
That part seems to be working.  I've tried simple delay and beep Sketches (e.g. blink an LED every second then count the blinks in one minute) and they seem to work well.  As expected, the uncalibrated internal oscillator is a bit off (~3% fast).

Quote
Or are you just compiling based on an Duemilanove w/ATmega32 (@16 MHz) and putting it into a chip running at 1MHz?
This is the entry in boards.txt I'm using...

Code:
rdbare328a1MHz.name=Bare / Breadboard ATmega328 @ 1MHz
rdbare328a1MHz.upload.using=pololu
rdbare328a1MHz.upload.maximum_size=32768
rdbare328a1MHz.build.mcu=atmega328p
rdbare328a1MHz.build.f_cpu=1000000L
rdbare328a1MHz.build.core=arduino

I left out the bootloader entries because I'm not using a bootloader.

Quote
I'm betting dollars to donuts that you're doing the latter
I'll take that bet!  But I do suspect the problem lies with me.

For what it's worth, I built an Excel spreadsheet to calculate the ocr and prescaler values.  The frequencies are all within 2% so it doesn't appear to be a problem with the math.

Unfortunately, I don't think I'll have time to work on it for a few days and possibly for a week.  I'll report back when I can...
Logged

Montreal
Offline Offline
Full Member
***
Karma: 0
Posts: 185
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Thanks that fixed the 3 tone problem, now i got another one?
if i write this should not i get a different tone at every 2 seconds??
i even try to add a tone1.stop just after the delay and it still give me always the same tone?
Any clues. (BTW i was running arduino 13)

Code:
#include <Tone.h>
Tone tone1;
Tone tone2;
Tone tone3;
void setup()
{
  tone1.begin(13);
  tone2.begin(12);
  tone3.begin(6);
  tone3.play(100);
  tone2.play(35);
}
void loop()
{
tone1.play(random(35,55));
delay(2000);
}
 
« Last Edit: November 25, 2009, 12:19:16 pm by patgadget » Logged

Patgadget
Montreal

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

[glow]Coding Badly[/glow]: ok, so how many donuts do you have on you right now? smiley-wink How far out are the frequencies?  Are they close to the RC oscillator error?  (i.e. ~3%).  Gimme some actual figures and I can help out.

[glow]Patgadget[/glow]: Ah yes... Remember: delay() is broken when you use the third (on the '328) timer to produce tones.  (delay() sits in an infinite loop because the timer has been reallocated)

Quote
Also, although it's the last timer to be allocated, timer 0 (which is used for millis() among other things) will be affected if used.

you could try this:

Code:
void loop()
{
  tone1.play(random(35,55), 2000);
  while (tone1.isPlaying());
}

Note: it won't matter which Tone instance you use.  If you've allocated 3 Tones, delay() and anything else that depends on millis() will be broken.
Logged


Montreal
Offline Offline
Full Member
***
Karma: 0
Posts: 185
Arduino rocks
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Perfect that fix all my problem.
Patgadget
Logged

Patgadget
Montreal

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

Sweet.  Moving to V0005.

b
Logged


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

I finally figured out what's wrong.  Tone.o is not being rebuilt when I switch "boards".  Because of various warnings, I know at least some of the other libraries are rebuilt when I switch.  I don't have the patience to figure out why the Tone library is orphaned and deleting Tone.o after a switch is an easy work-around so I'm moving on to the next hurdle.

Thank you mem and  bhagman for your help!
Logged

Pages: 1 [2]   Go Up
Jump to: