References to Study:
- Secrets of Arduino PWM, by Ken Shirriff
- ATmega328 Datasheet (660 pg version from 11/2015)
- ATmega168/328-Arduino Pin Mapping
Here's some oscilloscope screenshots of the output on Pin 3 produced by an Arduino Nano running the code below.
Rising edge to rising edge: Δx = 100us |
Zoomed-in view of high pulse. Rising edge to falling edge = 1us |
ADVERTISEMENT:
Here's the code. Don't be put off by it. Literally, it's only 5 key lines of code, surrounded by a little fluff and lots of comments. The 5 key lines are setting the pinMode, TCCR2A, TCCR2B, OCR2A, and OCR2B. Take a look:
/* pulse_1us_100us - use timer2 to make a 1us HIGH pulse followed by 99us LOW, for a duty cycle of 1us/(99+1)us = 1us/100us = 1%, and a period of 100us By Gabriel Staples - for my email address, click "Contact Me" link at top of my website here: http://www.ElectricRCAircraftGuy.com/ References: - Secrets of Arduino PWM: http://www.righto.com/2009/07/secrets-of-arduino-pwm.html - ATmega328 Datasheet (660 pg version from 11/2015): http://www.atmel.com/images/Atmel-8271-8-bit-AVR-Microcontroller-ATmega48A-48PA-88A-88PA-168A-168PA-328-328P_datasheet_Complete.pdf - https://www.arduino.cc/en/Hacking/PinMapping168 */ void setup() { //set 1us HIGH pulse followed by 99us LOW pulse (1% duty cycle) on pin 3 pinMode(3, OUTPUT); //Note: pin 3 is OC2B <--so use port B, not A; see https://www.arduino.cc/en/Hacking/PinMapping168 //Set timer2 clock with prescaler 8 (0.5us per count, so 256 counts --> 128us); datasheet pg. 157: CS22/CS21/CS20 = 0/1/0 //Set to Fast PWM with Top==OCRA; datasheet p. 155: Mode 7; WGM22/WGM21/WGM20 = 1/1/1 //Set OC2B to non-inverting mode; Table 18-6, pg. 154: COM2B1/COM2B0 = 1/0 //TCCR2A: pg. 153; TCCR2B: pg. 156 TCCR2A = _BV(COM2B1) | _BV(WGM21) | _BV(WGM20); TCCR2B = _BV(WGM22) | _BV(CS21); //Set period to 100us and high pulse time to 1us //-Note that the high time you set here is OCR2B + 1 clock cycles, so OCR2B + 1 in this case // is 2, which is 1us, since each clock count is 0.5us //-To get clock cycles we must multiply desired microseconds x 2 (again, with a prescaler // of 8 and a 16MHz clock, each clock count is 0.5us) //-For this Fast PWM mode, note that the period is OCR2A + 1 also //-For reasons for the above, see "off-by-one" here: http://www.righto.com/2009/07/secrets-of-arduino-pwm.html //--Ex: Notice where Output B duty cycle is calculated in his example here: // "Output B duty cycle: (50+1) / (180+1) = 28.2%" //--So, for the reasons above, we must subtract 1 below to get the right period and duty cycles byte pd = 100; //us; period byte highPulseTime = 1; //us OCR2A = pd*2 - 1; //set period OCR2B = highPulseTime*2 - 1; //set high time } void loop() { }By Gabriel Staples
Written: 31 Mar 2017
Last Updated: 1 Apr 2017
History (newest on top):
20170401 - minor wording additions for clarity and emphasis that the code is only 5 key lines
Other Articles:
- Arduino micros() function with 0.5us precision - using my Timer2_Counter Library
- Arduino-like millisecond (ms) and microsecond (us)-resolution timestamps in Python: millis(), micros(), delay(), & delayMicroseconds()
- BattleBots Season 2 "Buzz" Fire Drone for Team Caustic Creations, with Team Interviews & fire-shooting Videos
- The Power of Arduino
- Restoring/Recharging Over-discharged LiPo (Lithium Polymer) Batteries!
- Parallel Charging Your LiPo Batteries
- Using the Arduino Uno’s built-in 10-bit to 16+-bit ADC (Analog to Digital Converter)--an Article on Oversampling
- Beginner RC Airplane Setup
No comments:
Post a Comment
Thanks for your comment or question! If it is a question, I will try to get back to you quickly. Notice to spammers: I personally remove all spam promptly and report spammers to Google, so please don't do it.
Note: some HTML tags are allowed in your comments. To learn how to add bold (<b>...</b>), italics (<i>...</i>), or hyperlinks (<a href="URL">NAME</a>) to your comments, read here.
~Sincerely, Gabriel Staples.
P.S. Yo hablo español también. Je parle français aussi. (I speak Spanish & French too).