I could reproduce the problem with the posted code. This will be caused by the fact that the tone library uses interrupts and has to manually toggle pins, which will always have a bit of jitter. You are better off setting up a hardware timer to generate the tones, this does not require interrupts.
For example:
#include <TonePlayer.h>
TonePlayer tone1 (TCCR1A, TCCR1B, OCR1AH, OCR1AL, TCNT1H, TCNT1L); // pin D9 (Uno), D11 (Mega)
void setup()
{
pinMode (9, OUTPUT); // output pin is fixed (OC1A)
tone1.tone (10000); // 10 kHz
}
void loop() { }
This uses a fairly small library I wrote, which you can download from http://www.gammon.com.au/Arduino/TonePlayer.zip
Library code
If you don't want to trust some zip file from a random web site, here is TonePlayer.h:
/*
Play tones with hardware timers
Author: Nick Gammon
Date: 1 April 2013
*/
#include <Arduino.h>
class TonePlayer
{
// addresses of output ports - NULL if not applicable
volatile byte * const timerRegA_;
volatile byte * const timerRegB_;
volatile byte * const timerOCRH_;
volatile byte * const timerOCRL_;
volatile byte * const timerTCNTH_;
volatile byte * const timerTCNTL_;
public:
// constructor
TonePlayer (
// ports
volatile byte & timerRegA,
volatile byte & timerRegB,
volatile byte & timerOCRH,
volatile byte & timerOCRL,
volatile byte & timerTCNTH,
volatile byte & timerTCNTL)
:
timerRegA_ (&timerRegA),
timerRegB_ (&timerRegB),
timerOCRH_ (&timerOCRH),
timerOCRL_ (&timerOCRL),
timerTCNTH_ (&timerTCNTH),
timerTCNTL_ (&timerTCNTH)
{ }
void tone (const unsigned int Hz);
void noTone ();
}; // end of TonePlayer
/*
PERMISSION TO DISTRIBUTE
Permission is hereby granted, free of charge, to any person obtaining a copy of this software
and associated documentation files (the "Software"), to deal in the Software without restriction,
including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
LIMITATION OF LIABILITY
The software is provided "as is", without warranty of any kind, express or implied,
including but not limited to the warranties of merchantability, fitness for a particular
purpose and noninfringement. In no event shall the authors or copyright holders be liable
for any claim, damages or other liability, whether in an action of contract,
tort or otherwise, arising from, out of or in connection with the software
or the use or other dealings in the software.
*/
And here is TonePlayer.cpp:
/*
Play tones with hardware timers
Author: Nick Gammon
Date: 1 April 2013
*/
#include <TonePlayer.h>
void TonePlayer::tone (const unsigned int Hz)
{
// it takes two toggles for one "cycle"
unsigned long ocr = F_CPU / Hz / 2;
byte prescaler = _BV (CS10); // start with prescaler of 1 (bits are the same for all timers)
// too large? prescale it
if (ocr > 0xFFFF)
{
prescaler |= _BV (CS11); // now prescaler of 64
ocr /= 64;
}
// stop timer
*timerRegA_ = 0;
*timerRegB_ = 0;
// reset counter
*timerTCNTH_ = 0;
*timerTCNTL_ = 0;
// what to count up to
*timerOCRH_ = highByte (ocr);
*timerOCRL_ = lowByte (ocr);
*timerRegA_ = _BV (COM1A0); // toggle output pin
*timerRegB_ = _BV (WGM12) | prescaler; // CTC
} // end of TonePlayer::tone
void TonePlayer::noTone ()
{
// stop timer
*timerRegA_ = 0;
*timerRegB_ = 0;
} // end of TonePlayer::noTone
/*
PERMISSION TO DISTRIBUTE
Permission is hereby granted, free of charge, to any person obtaining a copy of this software
and associated documentation files (the "Software"), to deal in the Software without restriction,
including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense,
and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so,
subject to the following conditions:
The above copyright notice and this permission notice shall be included in
all copies or substantial portions of the Software.
LIMITATION OF LIABILITY
The software is provided "as is", without warranty of any kind, express or implied,
including but not limited to the warranties of merchantability, fitness for a particular
purpose and noninfringement. In no event shall the authors or copyright holders be liable
for any claim, damages or other liability, whether in an action of contract,
tort or otherwise, arising from, out of or in connection with the software
or the use or other dealings in the software.
Example of use:
#include <TonePlayer.h>
...
TonePlayer tone1 (TCCR1A, TCCR1B, OCR1AH, OCR1AL, TCNT1H, TCNT1L); // pin D9 (Uno), D11 (Mega)
or, on the Mega 2560:
TonePlayer tone3 (TCCR3A, TCCR3B, OCR3AH, OCR3AL, TCNT3H, TCNT3L); // pin D5
TonePlayer tone4 (TCCR4A, TCCR4B, OCR4AH, OCR4AL, TCNT4H, TCNT4L); // pin D6
TonePlayer tone5 (TCCR5A, TCCR5B, OCR5AH, OCR5AL, TCNT5H, TCNT5L); // pin D46
...
pinMode (9, OUTPUT); // D9 on Uno, D11 on Mega 2560
tone1.tone (440); // play 440 Hz
delay (500); // wait half a second
tone1.noTone (); // stop playing
or, on the Mega 2560:
pinMode (46, OUTPUT);
tone5.tone (440);
*/
Just put those two files inside a folder "TonePlayer" inside the libraries
folder inside your sketches folder, and it should all work.
The library is written for the 16-bit timers, and supports Timer 1 on the Atmega328, and Timers 1, 3, 4, 5 on the Atmega2560. Comments inside the library show how to set up the other timers.