Go Down

### Topic: Generating a 20khz sine wave (Read 10262 times)previous topic - next topic

#### specialjack

##### Feb 04, 2014, 10:05 pm
Hi, I'm trying to generate a 20khz tone that could be picked up by speakers around a small room.

I have tried just using the tone function, but I seem to be getting a lot of subharmonics also and the sound it makes is really annoying. Ideally, the sound will be inaudible for most people.

However, I've also been just using some cheap computer speakers. I'm not really sure, but I think I may need to use something like a super horn tweeter or something instead.

So, (I know very little about all this) my questions are:

1. What is the best way to generate the sound with an arduino uno?
2. What type of speaker would be ideal to play the sound from?

Thanks!

#1
##### Feb 04, 2014, 10:26 pm
Use micros();
Code: [Select]
`// declare variables, pinMode, etc.void loop(){while(1){if ( (micros() - nextMicros) >=25){ // 20KHz = 50uS period  nextMicros = nextMicros + 25;  PIND = 0b00000100;  // output on PortD-2 (is D3?)  } }}`
Will measure 20.0004 to 20.0008 KHz or so on a frequency analyzer.  I have an Uno running this right now.
Designing & building electrical circuits for over 25 years.  Screw Shield for Mega/Due/Uno,  Bobuino with ATMega1284P, & other '328P & '1284P creations & offerings at  my website.

#### specialjack

#2
##### Feb 04, 2014, 10:33 pm
Could you post the full code? I don't really know how micros() works or much about arduino programming in general.

#### larryd

#3
##### Feb 05, 2014, 01:43 amLast Edit: Feb 05, 2014, 08:07 pm by LarryD Reason: 1
If you want a sine wave you will need to integrate the o/p signal seen on the Arduino as it is 0V 5V digital.
No technical PMs.
If you need clarification, ask for help.

#4
##### Feb 05, 2014, 05:40 am
Code: [Select]
`// declare variables, pinMode, etc.unsigned long nextMicros;void setup(){pinMode (3, OUTPUT);}void loop(){while(1){if ( (micros() - nextMicros) >=25){ // 20KHz = 50uS period  nextMicros = nextMicros + 25;  PIND = 0b00000100;  // output on PortD-2 (is D3?)  } }}`
I think that's all you need.
Designing & building electrical circuits for over 25 years.  Screw Shield for Mega/Due/Uno,  Bobuino with ATMega1284P, & other '328P & '1284P creations & offerings at  my website.

#### larryd

#5
##### Feb 05, 2014, 08:24 pm
For D3, on the UNO, rather than:
PIND = 0b00000100;  // output on PortD-2 (is D3?)
PIND = 0b00001000;  // output on PortD-3 (is D3)

Or use:
pinMode (2, OUTPUT);
. . .
PIND = 0b00000100;  // output on PortD-2 (is D2)
No technical PMs.
If you need clarification, ask for help.

#6
##### Feb 06, 2014, 03:30 am
Yeah, might have missed by one.
Designing & building electrical circuits for over 25 years.  Screw Shield for Mega/Due/Uno,  Bobuino with ATMega1284P, & other '328P & '1284P creations & offerings at  my website.

#7
##### Feb 06, 2014, 03:43 am
Here's the code I actually have running - was on a different PC than my original submittal:
Code: [Select]
`const byte triggerOut = 2;unsigned long nextMicros;//unsigned long duration = 200UL; // flip every 200uS = 2.5KHz pulseunsigned long duration = 25UL; // flip every 50uS = 20KHz pulsevoid setup(){  pinMode (triggerOut, OUTPUT);  digitalWrite(triggerOut, LOW);}void loop(){  while (1){    if ((micros() - nextMicros) >= duration){      nextMicros = nextMicros + duration;      PIND = 0b00000100; // toggle output by writing PINx register    }  }}`
Designing & building electrical circuits for over 25 years.  Screw Shield for Mega/Due/Uno,  Bobuino with ATMega1284P, & other '328P & '1284P creations & offerings at  my website.

#### specialjack

#8
##### Feb 11, 2014, 05:13 pm

Here's the code I actually have running - was on a different PC than my original submittal:
Code: [Select]
`const byte triggerOut = 2;unsigned long nextMicros;//unsigned long duration = 200UL; // flip every 200uS = 2.5KHz pulseunsigned long duration = 25UL; // flip every 50uS = 20KHz pulsevoid setup(){  pinMode (triggerOut, OUTPUT);  digitalWrite(triggerOut, LOW);}void loop(){  while (1){    if ((micros() - nextMicros) >= duration){      nextMicros = nextMicros + duration;      PIND = 0b00000100; // toggle output by writing PINx register    }  }}`

hmm so when I run this code, I'm still getting a lot of other frequencies playing which I assume are subharmonics. any idea how to stop this?

#### TRGT8

#9
##### Feb 11, 2014, 06:14 pm
My experience - you can't reach 20 kHz inside "loop" function.
You should modify the timer behavior of one of the timers and attache a interrupt function with your sampler code to this timer.

#10
##### Feb 12, 2014, 03:05 amLast Edit: Feb 12, 2014, 03:15 am by CrossRoads Reason: 1
Specialjack, the '328Ps only 0-5V outputs, so you need to filter out the high frequencies that make up the corners.

TRTG8 - the code I posted makes 20 KHz - I have posted oscilloscope shots of it.
Designing & building electrical circuits for over 25 years.  Screw Shield for Mega/Due/Uno,  Bobuino with ATMega1284P, & other '328P & '1284P creations & offerings at  my website.

#### visualxl

#11
##### Sep 10, 2014, 10:41 am
I don't quite understand your question. But if I understand correctly, you want to generate a sound in 20kHz using an Uno?

If so, you may refer to my code below. I used it to generate an inaudible sound using PKM34EW piezo speaker. However, the range is very short.  The piezo speaker has to be connected to pin 10, and 9 of the UNO.

Code: [Select]
`#include <toneAC.h>int frequency = 20000;void playFrequency() {  toneAC(frequency);}void setup() {}void loop() {  playFrequency();}`

#### DVDdoug

#12
##### Sep 11, 2014, 05:17 pm
The PWM output will usually have subharmonics, but a square wave from a digital output will only have regular (higher frequency) harmonics which are not audible at 20kHz.     However, non-linearity in your piezo or speaker might create audible subharmonics or resonances.

If you want a true sine wave, you'll need a DAC or audio shield (which has a DAC), or you can filter a square wave, but to filter-out all (or nearly all) of the harmonics, you'd need an active filter.

#### Grumpy_Mike

#13
##### Sep 16, 2014, 09:34 am
Is there any reasion why it has to be an arduino generating the tone? A simple hardware oscillator is so much eiser.

The extra sound you here are not sub harmonics but noise caused by jitter, caused by the interrupts going off that amongst other things update the millis and micros timers.

Go Up