This is a mathematical artifact of the particular method that Arduino uses on the AVRs to generate the tone. One of the Timer peripherals (Usually Timer2 for these kinds of things) is used to create a periodic interrupt, and each time the interrupt occurs the output pin is toggled.
I assume you are using an Uno, Mega, Leonardo, or a derivative of one of those. Without going into the derivation, the formula for calculating the output frequency is this:
Tone = F_CPU / 2 / PRESCALER / (TOP+1)
The tone function goes through the trouble of calculating the Prescaler and Top values for you, so you never see this part of it. As I’ll show you though, you can’t ignore this part under the hood because it’s what’s causing what you see.
F_CPU on most AVR Arduino boards is 16 MHz. Some are clocked at 8 MHz, but those are usually specialty variants like a Pro Mini.
The prescaler is used to slow down the clock from the main 16 MHz frequency. On Timer2 it can only have a value of 1, 8, 32, 64, 128, 256, or 1024.
Top sets the period of the signal, and can be an integer value between 0 and 255 inclusive.
Because the Top and Prescaler values are in the denominator of the calculation instead of the numerator, the output frequencies are not distributed equally in the range. Reducing the Top value increases the frequency, and because it has such a small range there will obviously be gaps between the outputs for adjacent inputs. I ran the calculations in Excel for different Prescaler and Top values and this is what showed up in the /64 prescaler table:
TOP | Frequency
130 | 954.1984733
131 | 946.969697
132 | 939.8496241
133 | 932.8358209
134 | 925.9259259
135 | 919.1176471
136 | 912.4087591
That explains your gap. Because it’s not possible for Top to be between 132 and 133, it’s not possible for the tone() function, as it is currently written, to generate a frequency between 932 Hz and 939 Hz.
Also note that this has nothing to do with “high” or “low” frequencies. Due to the effect of the prescaler, this distribution will be repeated through a few octaves.
It could probably be improved by using the 16-bit Timer1, which would let it use a lower prescaler setting and thus have less spacing between the frequency outputs, but this would require writing a new library if one has not already been written. Not an impossible task, but one that would require some study.
The best method for precise frequency generation is to use a numerically controlled oscillator that uses the phase accumulation technique. The AD9833 is one such chip that can also do direct digital synthesis of square and sine waves with an integrated DAC. With a 25 MHz clock, it can generate any frequency between 0 - 12.5 MHz in 0.1 Hz increments. A 1 MHz clock lets you specify 0.004 Hz increments, a truly insane level of precision. With phase accumulation, the frequency output is directly proportional to the setting, not inversely proportional, so the frequency outputs are all evenly spaced.
If you just want to make beeps with a speaker, using an external NCO/DDS chip is way overkill. Stick with tone(), flaws and all, since its’ free. But if you’re trying to DIY a piece of test equipment (like a function generator), you probably want the extra precision of an NCO.
AD9833 - Programmable Waveform Generator.pdf (687 KB)