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;
}
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.
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.
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?
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.
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.