Pages: [1] 2   Go Down
Author Topic: Generating 40kHz square wave  (Read 2871 times)
0 Members and 1 Guest are viewing this topic.
Offline Offline
Full Member
***
Karma: 1
Posts: 186
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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:
#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
    }
}
Logged

Offline Offline
Edison Member
*
Karma: 116
Posts: 2205
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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

Global Moderator
UK
Offline Offline
Brattain Member
*****
Karma: 309
Posts: 26538
I don't think you connected the grounds, Dave.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Quote
You need a pwm mode that allows you to set the top.
Was the any more to your post, dhenry?
Logged

"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.

UK
Offline Offline
Shannon Member
****
Karma: 223
Posts: 12630
-
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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

Nick Gammon's description of Timers and Counters
Logged

I only provide help via the forum - please do not contact me for private consultancy.

Pittsburgh, PA, USA
Offline Offline
Faraday Member
**
Karma: 99
Posts: 4820
I learn a bit every time I visit the forum.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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


Logged

I find it harder to express logic in English than in Code.
Sometimes an example says more than many times as many words.

Global Moderator
Melbourne, Australia
Online Online
Brattain Member
*****
Karma: 506
Posts: 19131
Lua rocks!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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

Which mode is that?
Logged

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

Please post technical questions on the forum - not to me by personal message. Thanks very muc

Global Moderator
Melbourne, Australia
Online Online
Brattain Member
*****
Karma: 506
Posts: 19131
Lua rocks!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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:
const long frequency = 50000L;  // Hz

Logged

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

Please post technical questions on the forum - not to me by personal message. Thanks very muc

Global Moderator
Melbourne, Australia
Online Online
Brattain Member
*****
Karma: 506
Posts: 19131
Lua rocks!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

Yep, it does, looks pretty accurate too:



Sketch:

Code:
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() { }
Logged

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

Please post technical questions on the forum - not to me by personal message. Thanks very muc

Offline Offline
Full Member
***
Karma: 1
Posts: 186
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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

Offline Offline
Full Member
***
Karma: 1
Posts: 186
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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?
Logged

Global Moderator
Melbourne, Australia
Online Online
Brattain Member
*****
Karma: 506
Posts: 19131
Lua rocks!
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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:
  TCCR2B = _BV (WGM22) | _BV (CS21);         // fast PWM, prescaler of 8

So the above line starts it. This would stop it:
Code:
  TCCR2B = _BV (WGM22) ;         // fast PWM, timer off
Logged

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

Please post technical questions on the forum - not to me by personal message. Thanks very muc

Pittsburgh, PA, USA
Offline Offline
Faraday Member
**
Karma: 99
Posts: 4820
I learn a bit every time I visit the forum.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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

http://www.atmel.com/search.aspx?q=+ATMEGA328P&as_q=inmeta%3Aasset_type~Datasheets%2Binmeta%3Aproduct_family%3DAtmel%2520AVR%25208%252D%2520and%252032%252Dbit&dnavs=inmeta%3Aasset_type~Datasheets%2Binmeta%3Aproduct_family%3DAtmel%2520AVR%25208%252D%2520and%252032%252Dbit&filter=0&btnG=Search&client=support_frontend&proxystylesheet=support_frontend&output=xml_no_dtd&getfields=*&oe=UTF-8&ie=UTF-8&ud=1&num=1000&sort=date%3AD%3AL%3Ad1&lr=lang_en&exclude_apps=1&site=en_collection

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


« Last Edit: February 01, 2013, 04:31:12 pm by GoForSmoke » Logged

I find it harder to express logic in English than in Code.
Sometimes an example says more than many times as many words.

Offline Offline
Full Member
***
Karma: 1
Posts: 186
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

Thanks for the replies
Logged

Offline Offline
Full Member
***
Karma: 1
Posts: 186
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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.
Logged

Pittsburgh, PA, USA
Offline Offline
Faraday Member
**
Karma: 99
Posts: 4820
I learn a bit every time I visit the forum.
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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

I find it harder to express logic in English than in Code.
Sometimes an example says more than many times as many words.

Pages: [1] 2   Go Up
Jump to: