Enabling PWM slows down entire void loop() considerably

Hello,

I’m running a Nano (ATmega328), and noticed that enabling pwm on a single pin in the setup() section slows down the loop() section considerably.

The code below takes ~12 seconds to complete the while loop if lines starting TCCR0B and analogWrite are commented out, ~20 seconds if they’re left in.

My understanding is that pwm on the ATmega328 is implemented in hardware, so I’m at a loss to understand why the loop() section is interrupted if pwm is enabled.

Is this normal behaviour for the ATmega328, and is there anything that can be done to reduce the increased execution time while pwm is active?

The code below will compile for a Nano. The program has no practical use other than to demonstrate the phenomenon I’m seeing. I would like to use pwm in another real-time program I’m writing, but the hit on speed is a problem with pwm enabled. Pwm is set to 62.5 KHz because the default arduino frequencies are too low for my application.

I’ve searched all the documentation I can find on the analogWrite call but I’ve not found anything on its impact to main program execution.

Regards,

#include <avr/pgmspace.h>

long i;

void setup() {
     Serial.begin(4800);
     pinMode(6, OUTPUT); 
     pinMode(7, OUTPUT); 
     //TCCR0B = (TCCR0B & 0b11111000) | 0x01;; // pin 6 PWM frequency 62500 Hz (62500/1)
     //analogWrite(6, 0);
}

//loop takes 12 seconds without pwm, 20 seconds with pwm
void loop() {
      i=0;
      while (i<5000000) {
                PORTD = PORTD | B10000000; //pin 7 HIGH
                PORTD = PORTD & B01111111; //pin 7 LOW
                i++;
      }
      Serial.print("Done ");
}

Have you tried the two lines separately? I'd worry about mucking with the millis() timer (TIMER0).

If you are going to use non-default PWM timing I would recommend using Timer1 or Timer2.

You have changed the frequency of timer0, but the overflow interrupt, used for millis() timing is still in place. There is interrupt latency to enter and leave the interrupt. The while loop is not executed during the interrupt. If you turn of the Timer0 overflow interrupt, the timings are similar.

cattledog:
You have changed the frequency of timer0, but the overflow interrupt, used for millis() timing is still in place. There is interrupt latency to enter and leave the interrupt. The while loop is not executed during the interrupt. If you turn of the Timer0 overflow interrupt, the timings are similar.

Disabling the timer0 overflow interrupt in setup() did the trick:

TIMSK0 &= ~_BV(TOIE0);

johnwasser:
Have you tried the two lines separately? I'd worry about mucking with the millis() timer (TIMER0).
If you are going to use non-default PWM timing I would recommend using Timer1 or Timer2.

I'll see if I can get that working. Not a problem for me at the moment as I'm not using the millis() function.

Thanks for the replies,