Go Down

Topic: Highest PWM frequency output for the Uno/Nano (Read 5 times) previous topic - next topic

PeekabuPi

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:

Code: [Select]

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?

retrolefty

#1
Oct 21, 2012, 04:30 am Last Edit: Oct 21, 2012, 04:32 am by retrolefty Reason: 1
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

Nick Gammon

#2
Oct 21, 2012, 05:24 am Last Edit: Oct 21, 2012, 05:29 am by Nick Gammon Reason: 1
Code: [Select]

 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:

http://www.gammon.com.au/forum/?id=11504

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:

Code: [Select]

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

Nick Gammon

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.

PeekabuPi

#4
Oct 21, 2012, 05:37 am Last Edit: Oct 21, 2012, 05:40 am by PeekabuPi Reason: 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)?

Go Up