Go Down

Topic: Generating 40kHz square wave (Read 3244 times) previous topic - next topic

sirch

Hi, new here and probably being a bit dim but I've Googled and done all the obvious stuff and I cannot figure out how to program the PWM to get a 40kHz signal to drive an ultrasonic sender for a distance measurement device.

I've got the example below running an giving me 8kHz but how do I scale this to get 40kHz. Also on my ATMega1280 the output is on pin 13, not pin 6 which this example code suggests (I guess the code is for a different processor). I've read the datasheet but it just went in and fell straight out again. Any help appreciated.

Code: [Select]

#include <avr/io.h>

int main(void)
{
    DDRD |= (1 << DDD6);
    // PD6 is now an output

    OCR0A = 128;
    // set PWM for 50% duty cycle


    TCCR0A |= (1 << COM0A1);
    // set none-inverting mode

    TCCR0A |= (1 << WGM01) | (1 << WGM00);
    // set fast PWM Mode

    TCCR0B |= (1 << CS01);
    // set prescaler to 8 and starts PWM


    while (1);
    {
        // we have a working Fast PWM
    }
}

dhenry

You need a pwm mode that allows you to set the top.

AWOL

Quote
You need a pwm mode that allows you to set the top.

Was the any more to your post, dhenry?
"Pete, it's a fool looks for logic in the chambers of the human heart." Ulysses Everett McGill.
Do not send technical questions via personal messaging - they will be ignored.

PeterH

You need to carefully read Nick Gammon's web site, I'd suggest starting here:

Nick Gammon's description of Timers and Counters
I only provide help via the forum - please do not contact me for private consultancy.

GoForSmoke

PWM frequency on the Playground:
http://playground.arduino.cc//Code/PwmFrequency

Quote
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).



Nick Gammon on multitasking Arduinos:
1) http://gammon.com.au/blink
2) http://gammon.com.au/serial
3) http://gammon.com.au/interrupts

Nick Gammon


You need a pwm mode that allows you to set the top.


Which mode is that?
Please post technical questions on the forum, not by personal message. Thanks!

More info:
http://www.gammon.com.au/electronics

Nick Gammon

One of my sketches on the page below generates 50 KHz:

http://www.gammon.com.au/forum/?id=11504&reply=6#reply6

By changing this line you should be able to get 40 KHz:

Code: [Select]

const long frequency = 50000L;  // Hz


Please post technical questions on the forum, not by personal message. Thanks!

More info:
http://www.gammon.com.au/electronics

Nick Gammon

Yep, it does, looks pretty accurate too:



Sketch:

Code: [Select]

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() { }
Please post technical questions on the forum, not by personal message. Thanks!

More info:
http://www.gammon.com.au/electronics

sirch

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

sirch

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?

Nick Gammon

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):

Code: [Select]

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


So the above line starts it. This would stop it:
Code: [Select]

  TCCR2B = _BV (WGM22) ;         // fast PWM, timer off
Please post technical questions on the forum, not by personal message. Thanks!

More info:
http://www.gammon.com.au/electronics

GoForSmoke

Nick Gammon on multitasking Arduinos:
1) http://gammon.com.au/blink
2) http://gammon.com.au/serial
3) http://gammon.com.au/interrupts

sirch


sirch

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.

GoForSmoke

Why use PWM at all? Just set up a timer and interrupt to change the pin state.
Nick Gammon on multitasking Arduinos:
1) http://gammon.com.au/blink
2) http://gammon.com.au/serial
3) http://gammon.com.au/interrupts

Go Up