Low frequency tone issue

I'm having an issue with the tone function, where if I try to produce a tone of 30 Hz or lower, the output frequency is erroneously higher.

Nothing in setup, and the only thing in the loop is:

tone(8,25);
delay(1000);

Is there a lower limit to frequency generation, or am I doing something wrong here?

With the Tone library supplied with arduino-0018:

Tones are generated by setting up a timer in RTC mode and toggling an output pin (in an Interrupt Service Routine) when the timer reaches a value determined by the contents of its OCR register.

With the maximum prescalar value of 1024, any frequency less than 31 Hz would require a value of greater than 255 in the timer's OCR register.

Since Tone uses Timer2 and Timer2 is an eight bit timer, frequencies less than 31 Hz are not possible.

Regards,

Dave

Footnote:
I have downloaded, but not tested, arduino-0019. Some changes were made to Tone.cpp (disables Timer2 after the tone has ended), but they do not affect my answer to this question: Frequencies below 31 Hz do not compute.

http://www.arduino.cc/cgi-bin/yabb2/YaBB.pl?num=1281911346/1#1

Tones are generated by setting up a timer in RTC mode and toggling an output pin (in an Interrupt Service Routine) when the timer reaches a value determined by the contents of its OCR register.

With the maximum prescalar value of 1024, any frequency less than 31 Hz would require a value of greater than 255 in the timer's OCR register.

Since Tone uses Timer2 and Timer2 is an eight bit timer, frequencies less than 31 Hz are not possible.

Seems like this information or some summery of it should be included on the tone() reference page...

Thanks for the great info, guys. It really should be mentioned in the tone reference page.

I guess I'll just have to resort to the blink example to get the frequency I need. OH, THE HUMANITY! :stuck_out_tongue:

Any updates on this problem? I am currently trying to drive a Speedometer out of a Jeep with my Arduino using the Tone() function. I am running into the same problem, where the wrong frequency is put out if you go below 31Hz (16 MPH on this gauge). I only need a range of about 10Hz to 220Hz to drive this gauge. It sounds like that 16 bit timer Tone function would solve my problem, but I don't see any way of making use of it. Any suggestions?

Any help would be greatly appreciated.

BUMP!

I am making a program that needs to play a melody. It doesn't work. The biggest problem is this.[ch8593]

When it plays a rest (0 Hz tone), all tones after that are wrong. Sometimes garbled or very low. Has anybody written a proper bit of code to solve this? PLEASE SHARE! :slight_smile:

Instead of calling tone() with a 0 Hz frequency, you should probably generate your rests by calling noTone() and then calling delay() for the appropriate amount of time.

In other words, change this:

tone(SPK_PIN, 0, REST_LENGTH);

To this:

noTone(SPK_PIN);
delay(REST_LENGTH);

Keep in mind that delay() will stop the flow of your program until the delay is complete. If you need to continue execution while the rest is being handled, you will need to write an interrupt handler that keeps an eye on the value of millis(). I will leave this as a challenge for you if you decide to do it.

You could tie the PWM output to a decade counter IC (like a 4017), then use the divide-by-10 output; so the lowest then you could go would be approx 3.1 Hz...