Generating 18kHz signal

Hello, I’m trying to generate 18kHz high-frequency audio sound in several ways, and tested them with a FFT analyser.

tone(pin, 18000);
I can see clear peak at 18kHz.

I tried to manually send signal HIGH and LOW alternatevely, which is one of example in Arduino.

void playTone(int pitch, long len)
{
long elapse = 0;
int u = 1000000L/2/pitch;

while(elapse<len)
{
digitalWrite(pin, HIGH);
delayMicroseconds(u);
digitalWrite(pin,LOW);
delayMicroseconds(u);
elapse += u*2;
}
}

I can see the peak, but at 16kHz, not 18kHz, also it has other small peaks around.

I used TimerOne library instead of delayMicroseconds().

void playTone2(int pitch, long len)
{
Timer1.setPeriod(1000000L / 2 / pitch);
Timer1.attachInterrupt(isr);
delay(len);
Timer1.detachInterrupt();
}

It shows a clear peak but at 16kHz, not 18kHz.

  • Does delayMicroseconds() conflict with something? what are those peaks around in (2)?
  • Why I’m getting 16kHz, not 18kHz? (it’s a simple transducer)

This is one way:

const byte LED = 10;  // Timer 1 "B" output: OC1B

// 16 MHz clock divided by 18 KHz frequency desired
const long timer1_OCR1A_Setting = 16000000L / 18000L;

void setup() 
 {
  pinMode (LED, OUTPUT);
  // set up Timer 1 - gives us 18 KHz 
  // Fast PWM top at OCR1A
  TCCR1A = _BV (WGM10) | _BV (WGM11) | _BV (COM1B1); // fast PWM, clear OC1B on compare
  TCCR1B = _BV (WGM12) | _BV (WGM13) | _BV (CS10);   // fast PWM, no prescaler
  OCR1A =  timer1_OCR1A_Setting - 1;                 // zero relative  
  OCR1B =  (timer1_OCR1A_Setting / 2) - 1;           // 50% duty cycle
  }  // end of setup

void loop() {}

Output is 18 KHz:

Frequency analysis (there are harmonics, which you expect with a square wave):