Generating 40kHz square wave

Yep, it does, looks pretty accurate too:

Sketch:

const byte LED = 3;  // Timer 2 "B" output: OC2B

const long frequency = 40000L;  // Hz

void setup() 
 {
  pinMode (LED, OUTPUT);

  TCCR2A = _BV (WGM20) | _BV (WGM21) | _BV (COM2B1); // fast PWM, clear OC2B on compare
  TCCR2B = _BV (WGM22) | _BV (CS21);         // fast PWM, prescaler of 8
  OCR2A =  ((F_CPU / 8) / frequency) - 1;    // zero relative  
  OCR2B = ((OCR2A + 1) / 2) - 1;             // 50% duty cycle
  }  // end of setup

void loop() { }

Thanks for the replies, I'll give that a go

Sorry to resurrect an old(ish) thread but what is the best way to stop and start this timer? I am using it for ultrasonic distance measurement so I need to send out a short ping and then listen for the echo. The ping needs to be short - is it best to just set the pin to input from output or do I need to stop the PWM, if so how?

Turning the pin to input is probably the simple way to stop it.

The thing that actually starts the timer is the CS21 part of this line (the clock source):

  TCCR2B = _BV (WGM22) | _BV (CS21);         // fast PWM, prescaler of 8

So the above line starts it. This would stop it:

  TCCR2B = _BV (WGM22) ;         // fast PWM, timer off

The full doc gives all the registers and commands, 55 pages of answers for those who ain'ts gots:

BTW that's in thanks to your code in reply #7 Nick.

Thanks for the replies

Apologies for reviving this thread again, but I am now trying to use a similar bit of code to generate a 1kHz signal, however it is fine down to about 8kHz but it won't go below that. I suspect that it is due to the fast PWM but I have read the datasheet and I haven't got a clue how to stop using the Fast PWM.

Any help greatly appreciated.

Why use PWM at all? Just set up a timer and interrupt to change the pin state.

I'd like to use PWM because this is not all that the Arduino is doing and accuracy could be compromised if a bit-banging approach got interrupted.

PWM uses a timer that if you change PWM speed will affect some other operations.
OTOH if you use a timer to drive a very short interrupt, the effect will be less to none.
Worst case, your square wave edge will be off a few usecs but that is the case with PWM.
Best case, you make it work both ways just to see which is more accurate.

I'm still not clear on what you are suggesting? Suppose in the main loop I want to do a Serial.print would this not affect the timing of the timer interrupt? Would the Serial.print complete or would it be interrupted by the timer?

Are you using the arrival of serial data sent from Arduino to time anything? I hope not!

You do a print command and what happens? This is as much as I can piece together, there are others on the board that can take it right down to the code and the metal:

With UNO there is the 328P that you program and the 8U2 to get to USB. Your text goes to the 8U2 via the serial RX pin at maximum 115200 bits per second (including start and stop bits) until that buffer is full when Serial fills its own buffer on the 328P. The 8U2 may empty faster than it can fill, or the PC may be busy now and then in which case hello Serial buffer. If you print long strings then you have more chance to find out and have serial output hang your sketch up, likely a fraction of a millisecond.

So let's suppose that we manage to not overload serial. Our timer interrupt will always run and flip the state of our output pin on time. Our ISR will not print. It may set a flag that the sketch can use to eventually print (do you plan on printing once every millisecond? then eventually is right then instead) but serial i/o should be down near the lowest priority of your sketch.

IMO the high priority is getting that square wave. And I would do it the same way at 50 kHz.

Of course if I'm wrong about any of this I would like to know soonest!

Ok, thanks, I'll may be give it a try.

No I'm not triggering on serial data. More the other way round, generate the square wave, wait for a response and then record the time between signal and response. It's useful to be able to Serial.print after the start of the square wave to provide feed back that things are running.

sirch:
Ok, thanks, I'll may be give it a try.

No I'm not triggering on serial data. More the other way round, generate the square wave, wait for a response and then record the time between signal and response. It's useful to be able to Serial.print after the start of the square wave to provide feed back that things are running.

How exact does the square wave and time between signal and response have to be? Will the response happen in less than or 900 ms? Micros has a 4 usec accuracy. With a tight while loop you can beat that but only by blocking which if it can be done between critical events is okay. Timing for ultrasonic range sensors is done that way.

Something to get a good handle on is what the speed of the OS-free processor really means. I find that many people seem to feel it's 1000 times or more slower than it is. Yeah, "feel" because they either don't work the numbers or have trouble relating to them. It's nothing personal, my taste in fashion would get me life in prison if some people had their way. We all have different strengths.

sirch:
I'm still not clear on what you are suggesting? Suppose in the main loop I want to do a Serial.print would this not affect the timing of the timer interrupt? Would the Serial.print complete or would it be interrupted by the timer?

Serial output is done by interrupts. Once one interrupts starts the next one has to wait for it to finish.

Looking into the USART0 section of the 328P I see that interrupts are not required for 2-wire serial I/O... it just makes a load of sense to use them as the Arduino Serial class does.

It's -possible- to get around but I think way more work than for example using an external clock source to generate the square waves, or not generating the square waves all the time or tolerating a rising or falling wave edge not being within a few usecs of 1 ms from the last one.

IF the critical part is wave edge to return AND return will be soon (I am guessing less than 1 ms?) THEN you could turn interrupts off, generate the wave edge and use a timing loop instead of a timer to watch for the return then turn interrupts back on. (I wonder if pulseIn does that?) That would make Serial wait for the return timing with no chance of the reverse.

How did this thread wander away from using the hardware time as described on page 1? The PWM output is not affected by interrupts.

What does changing PWM frequency affect?

What do you mean? I'm not sure where this question is going, or if it is even addressed at me. :slight_smile:

Yes Nick. But my reason to avoid messing with PWM frequency may not make as much difference as I thought.

http://playground.arduino.cc/Code/PwmFrequency

Please keep in mind that changing the PWM frequency changes the Atmega's timers and disrupts the normal operation of many functions that rely on time (delay(), millis(), Servo library).

I was thinking it'd disrupt micros() as well but even if it does he can use a timing loop for return time so my reason not to is probably less than moot.