Offline
Newbie
Karma: 0
Posts: 10
|
 |
« on: October 20, 2012, 09:16:38 pm » |
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?
|
|
|
|
|
Logged
|
|
|
|
|
Left Coast, CA (USA)
Online
Brattain Member
Karma: 279
Posts: 15316
Measurement changes behavior
|
 |
« Reply #1 on: October 20, 2012, 09:30:01 pm » |
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/PortManipulationLefty
|
|
|
|
« Last Edit: October 20, 2012, 09:32:11 pm by retrolefty »
|
Logged
|
|
|
|
|
Global Moderator
Melbourne, Australia
Online
Shannon Member
Karma: 219
Posts: 13896
Lua rocks!
|
 |
« Reply #2 on: October 20, 2012, 10:24:25 pm » |
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=11504If 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.
|
|
|
|
« Last Edit: October 20, 2012, 10:29:57 pm by Nick Gammon »
|
Logged
|
|
|
|
|
Global Moderator
Melbourne, Australia
Online
Shannon Member
Karma: 219
Posts: 13896
Lua rocks!
|
 |
« Reply #3 on: October 20, 2012, 10:36:30 pm » |
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.
|
|
|
|
|
Logged
|
|
|
|
|
Offline
Newbie
Karma: 0
Posts: 10
|
 |
« Reply #4 on: October 20, 2012, 10:37:37 pm » |
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)?
|
|
|
|
« Last Edit: October 20, 2012, 10:40:16 pm by PeekabuPi »
|
Logged
|
|
|
|
|
Global Moderator
Melbourne, Australia
Online
Shannon Member
Karma: 219
Posts: 13896
Lua rocks!
|
 |
« Reply #5 on: October 20, 2012, 10:50:45 pm » |
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
|
|
|
|
« Last Edit: October 20, 2012, 10:52:45 pm by Nick Gammon »
|
Logged
|
|
|
|
|
Offline
Newbie
Karma: 0
Posts: 10
|
 |
« Reply #6 on: October 20, 2012, 10:54:50 pm » |
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?
|
|
|
|
|
Logged
|
|
|
|
|
Global Moderator
Melbourne, Australia
Online
Shannon Member
Karma: 219
Posts: 13896
Lua rocks!
|
 |
« Reply #7 on: October 20, 2012, 10:59:45 pm » |
Install the library, restart the IDE. It should compile then.
|
|
|
|
|
Logged
|
|
|
|
|
Global Moderator
Melbourne, Australia
Online
Shannon Member
Karma: 219
Posts: 13896
Lua rocks!
|
 |
« Reply #8 on: October 20, 2012, 11:01:10 pm » |
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.
|
|
|
|
|
Logged
|
|
|
|
|
Offline
Newbie
Karma: 0
Posts: 10
|
 |
« Reply #9 on: October 20, 2012, 11:14:53 pm » |
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()?
|
|
|
|
« Last Edit: October 20, 2012, 11:23:06 pm by PeekabuPi »
|
Logged
|
|
|
|
|
Global Moderator
Melbourne, Australia
Online
Shannon Member
Karma: 219
Posts: 13896
Lua rocks!
|
 |
« Reply #10 on: October 21, 2012, 12:27:55 am » |
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.
|
|
|
|
|
Logged
|
|
|
|
|
Offline
Newbie
Karma: 0
Posts: 10
|
 |
« Reply #11 on: October 22, 2012, 03:08:24 am » |
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?
|
|
|
|
|
Logged
|
|
|
|
|
Global Moderator
Melbourne, Australia
Online
Shannon Member
Karma: 219
Posts: 13896
Lua rocks!
|
 |
« Reply #12 on: October 22, 2012, 03:46:33 am » |
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.
|
|
|
|
|
Logged
|
|
|
|
|
Offline
Edison Member
Karma: 114
Posts: 2205
|
 |
« Reply #13 on: October 22, 2012, 04:58:48 pm » |
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.
|
|
|
|
|
Logged
|
|
|
|
|
Offline
Newbie
Karma: 0
Posts: 10
|
 |
« Reply #14 on: November 03, 2012, 02:38:46 am » |
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.
|
|
|
|
|
Logged
|
|
|
|
|
|