Unstable signal when generating PWM with timer 2 on Nano

Hello, i'm using the code below to generate two PWM signal on pin 4 and an inverted signal on pin 7.
I'm using the compare A interrupt to toggle the pins. This work fine expect that sometimes the timing is off (this is very quick however, on real speed on the scope this look likes a jitter).

Here's the code :

void setup() {
  pinMode(4, OUTPUT); 
  digitalWrite(4, HIGH);
  pinMode(7, OUTPUT); 
  digitalWrite(7, LOW);
  // WGM20 + WGM21 + WGM22 = FAST PWM, OCRx TOP 
  TCCR2A = _BV(WGM21) | _BV(WGM20);
  TCCR2B = _BV(CS20) | _BV(WGM22);
  OCR2A = 120;
  TIMSK2 = _BV(OCIE2A); // interrupt sur COMA   
}

void loop() {
  // put your main code here, to run repeatedly:

}

ISR(TIMER2_COMPA_vect){
  // Toggle pin 4 et 7 
  PORTD = PORTD ^ 0b10010000;
}

Most of the time this look as expected :

When the timing is wrong:

It looks like the chip is busy doing something else, but i have nothing in the loop and the interrupt is as simple as it get.

The board is a nano powered from a 1.8A amps power supply with nothing connected except the scope probes.

Yes it is. There is also the millis() interrupt, which may sometimes interfere with your interrupt and cause a little delay. If you want it absolutely stable you must use the HW feature of the timer to create the signal.

1 Like

If you use a timer, why don't you use the timer functions to produce the signals without using software interrupts?

Indeed i should have mentioned this in the original post : the code is a simple test, my goal is to have the inverted PWM signal (let's say the yellow one) slightly shorter than what it is right now (so there will be a short time when the too signal are 0, just after the red signal has fallen, and before it rise).

The next test is reducing OCROA to greatly increase the frequency of the interupt calls and be able to slightly reduce the inverted signal duration.
I tried to do it without interrupt but failed to do so (this may not be feasable at all, this is why i'm doing thoses tests).

To be thorough the non inverted signal will drive an high side switch, and the inverted one a low side switch, so i don't want them to be on at the same time. The off time is to account for mofset rise/fall time.

This is the reason i used timer2, i thought that timer1 was already used by millis so it would be safer to use timer2.
Turn out i was wrong, i switched to timer0 and the two signals are perfect, no more delay. I don't really understand why but i'm fine with using timer 0.

millis() uses timer 0. If you use timer 0, you switch off millis() what is not really a solution.

The reason for the delay is not a timer conflict, but an ISR conflict. The millis() function uses a timer IRQ of timer 0. If the ISR of millis() is running, when your timer2 ISR should start, it has to wait until the millis() ISR is finished. That causes the delay.

Ok thanks for the clarification. If i dont use millis(), is there any other downside of using timer0 ?

This has often been discussed. Simply use the timer hardware to produce spaced pulses for driving H-bridges.

is there any other downside of using timer0 ?

It's only 8 bits, timer1 is 16.

Timer/Counter 2 (TC2) delivers PWM signals on DPin-3 and DPin-11 (Fig-1) and NOT on DPin-4/7. The frequency is fixed if you use analogWrite(arg1, arg2) function; else, you can manipulate registers (as you have done in your sketch) to generate varying frequencies.

What is your frequency of the PWM signal? Are they same for both channels?
pwm328x
Figure-1:

Even delay() will not work, because it uses millis(). If you will use libraries, they also may rely on millis(). It is a very basic functionality of Arduino.

It's much more safe to do that by HW. If you use an integrated ( half) H-bridge this is already implemented.

Initially i was doing this with the integrated waveform generation of the timer 2 , but i could not figure out a way to reduce the duration of one of the signal.

I managed to get what i want by switching pins "manually" :

However the frequency is greatly reduced and i must admit this feels kind of hacky.

Following your advice i will try to do it through the timer's waveform generation.
I don't think one timer is enough, i found this thread where someone is trying to generate some waveforms using multiple timer, i will study it when i have some time.

Thanks everyone for the help.

Using Timer1 to produce the complementary signals with a small gap is covered in this thread.

https://forum.arduino.cc/t/two-200khz-complementary-pwm-signals/421885/10

Thank you very much ! It's exactly what i needed

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.