Highest PWM frequency output for the Uno/Nano

What is the highest PWM frequency that can be output by the Uno or Nano?

I cant remember exactly right now but I remember measuring around 70kHz output using an oscilloscope with the following program:

void loop ()
{
  digitalWrite(outPin, HIGH);
  digitalWrite(outPin, LOW);
}

That program above is essentially the fastest that it can generate a PWM pulse right? So is it capped at 70kHz then?

How do you get higher frequencies straight out of the digital I/O?

Direct port manipulations will allow you to toggle a output pin as fast as possible for a given clock rate.

http://www.arduino.cc/playground/Learning/PortManipulation

Lefty

  digitalWrite(outPin, HIGH);
  digitalWrite(outPin, LOW);

That's not really PWM. Use the internal timers to do that.

I have some examples near the bottom of this page:

If you use the "fast PWM mode, top at OCR0A" mode then you can get quite high frequencies, the trade-off being lower PWM resolution.

As an example:

#include <TimerHelpers.h>

// Timer 0

// output    OC0B   pin 11  (D5)

const byte timer0OutputB = 5;
  
void setup() {
   pinMode (timer0OutputB, OUTPUT); 
   TIMSK0 = 0;  // no interrupts
   Timer0::setMode (7, Timer0::PRESCALE_1, Timer0::CLEAR_B_ON_COMPARE);
   OCR0A = 3;   // count to 4, zero-relative
   OCR0B = 1;   // duty cycle
}  // end of setup

void loop() {}

Because OCR0A is small it counts up to 4, giving a frequency of 4 MHz (one quarter of the system clock). However the duty cycle can only be 0, 1 or 2, so basically you can have a 33% or 66% duty cycle.

The higher you make OCR0A the lower the frequency but the higher resolution of PWM duty cycle.

Screenshot of above test confirms results:

Note the frequency and the duty cycle. To get a duty cycle of 33.3% you need OCR0B to be 2 rather than 1.

Thanks. Looks like the default digitalWrite() has too much overhead. I just tried measuring the uno with the OP code and I topped at 116kHz. The nano that I measured before topped at 70kHz. But seeing there are many different timers I guess it depends on which pin too?

For the sample code you supplied using the TimersHelpers.h library, I downloaded it and tried the sample code. There was an error on debug saying TImer0 is not defined?

If I want to create 50% duty cycle signals at the highest frequency possible (essentially just a normal periodic square wave). Can that be done up to 4MHz (you mentioned 4MHz can only choose between 33% or 66% duty)?

For a normal square wave use a simpler timer mode like CTC. Example:

#include <TimerHelpers.h>

// Timer 0

// output    OC0A   pin 12  (D6)

const byte timer0OutputA = 6;
  
void setup() {
   pinMode (timer0OutputA, OUTPUT); 
   TIMSK0 = 0;  // no interrupts
   Timer0::setMode (2, Timer0::PRESCALE_1, Timer0::TOGGLE_A_ON_COMPARE);
   OCR0A = 1;  // count to 2
}  // end of setup

void loop() {}

That outputs a 4 MHz square wave.

If you change OCR0A to 0 you get a 8 MHz square wave.

If you are getting compile errors, that code was for the Uno. Did you install the timer helpers library?

http://gammon.com.au/Arduino/TimerHelpers.zip

I am using an Uno right now too. Yeah I saw the link from the site you linked to earlier.

It says Timer0 is not declared?

Install the library, restart the IDE. It should compile then.

Unzip that file, copy the folder TimerHelpers into the libraries folder (in your Arduino sketches folder) then restart the IDE. Copy the whole folder, not just the contents.

Thanks. I got it to work. The restart seemed to do it.

I also measure 4MHz square wave now too! Cheers!A few noob question:

Does it still source the maximum 50mA current?
Does this code also work for the nano?
Does the code work for all digital pins?

I just tried to move part of the code over to loop and the signal is no longer steady and 50% dutycycle i guess because there is some time lag with the restarting the loop? So this method only works under void setup()?

Does it still source the maximum 50mA current?

20 mA more like. 40 mA is the absolute maximum.

Does this code also work for the nano?

I imagine so.

Does the code work for all digital pins?

The timers have fixed output pins. Each timer has two pins dedicated to it which is why you have 6 PWM outputs on the Uno (3 timers x 2 pins each).

I just tried to move part of the code over to loop and the signal is no longer steady and 50% duty cycle i guess because there is some time lag with the restarting the loop? So this method only works under void setup()?

That doesn't make sense. Show your amended code please. Once you have the timer set up it doesn't matter what the code is doing. However if you put that code into loop it might be restarting the timer very rapidly. You don't want that.

The timer (that I showed) runs independently, so that is why I had it in setup. You don't have to keep calling the code. It's all done in hardware.

Hi I think I just tired this:

#include <TimerHelpers.h>

// Timer 0

// output    OC0A   pin 12  (D6)

const byte timer0OutputA = 6;
  
void setup() {
   pinMode (timer0OutputA, OUTPUT); 
}  // end of setup

void loop() {

   TIMSK0 = 0;  // no interrupts
   Timer0::setMode (2, Timer0::PRESCALE_1, Timer0::TOGGLE_A_ON_COMPARE);
   OCR0A = 1;  // count to 2
}

Also I tried it with the nano recently. I noticed that the uno produces better square waves than the nano. Are the pulses generated by the microcontroller (which are the same for the uno and nano)? Or the crystal?

I was wondering if there is any documentation on how to use the TimeHelper header file?

Don't do that in loop.

Quoting myself, who you have chosen to ignore:

However if you put that code into loop it might be restarting the timer very rapidly. You don't want that.

What is the highest PWM frequency that can be output by the Uno or Nano?

The hardware pwm module can be quite helpful here.

The spi / uart module can also be used to generate pwm in case that's needed.

Sorry didnt mean to ignore the advice. I just tried it for the sake of it. Actually the reason is I intend to be able to modulate the frequency so maybe Id want it in the loop instead.

If you were looking for frequency modulated RF @ 4 Mhz you might well consider an Analog Devices AD9851 DDS solution (Faster X2 to 60 MHz) or the readily available from Ebay AD9850 assemblies. they require a 40 bit serial load SPI I think and can operate from nearly DC to 30 MHZ, both sine and square wave outputs too. While NCO's aren't new this one is interesting and at about 7 to 9 dollars an inexpensive way to go. There are a couple of sketches I've found for mine but not yet the time to test them... Nor a good frequency counter either... Yet.

Bob

Dear Nick Gammon,

1.How and where Can I make such demo? (Good for presentation)

Very handy logic analyzer.

Thanks for the great sketch and information. I am having trouble understanding your sketch, maybe because I am fairly new to Arduino/C++. What I am trying to do is utilize the output from your sketch as a loop antenna that I can then detect by a secondary coil or loop. No need for accuracy, just detection of proximity. Can you advise where/how I get your output? Thanks very much.

Can you advise where/how I get your output?

I don't understand the question. My output is at my house.