Arduino Mega 2560 - inverting PWM

D10S:
Yes, exactly. For the initial 0.5 s, the pwm is still HIGH

I switched to 1 Hz for simplicity, however the idea is the same.

Switch your oscilloscope to trigger on a falling edge rather than a rising edge. Your first half second will then be LOW.

johnwasser:
Switch your oscilloscope to trigger on a falling edge rather than a rising edge. Your first half second will then be LOW.

Thanks! I did it and now first half second is actually LOW. However, is this just a visual thing?! my pwm output from arduino is still the opposite, isn't it?

D10S:
Thanks! I did it and now first half second is actually LOW. However, is this just a visual thing?! my pwm output from arduino is still the opposite, isn't it?

Yes, it's a visual thing. Without some other reference there is no way to know if the first half cycle of the wave is HIGH or LOW. It looks like your oscilloscope is a digital storage scope. You can put a short glitch on the output pin just before enabling the PWM to get a feel for which half cycle you are starting on. You need to set the trigger to trigger once on a rising edge and freeze the trace.

  digitalWrite(OutputPin, LOW);
  delay(1);
  digitalWrite(OutputPin, HIGH);
  delay(1);
  digitalWrite(OutputPin, LOW);
  delay(1);

The time between this glitch and the first rising edge of your PWM will give you an idea of your PWM phase. If the 1ms HIGH pulse is followed by 501ms of LOW then you are starting on the LOW phase. If the 1ms HIGH pulse is followed by 1 ot 2 ms of LOW before going HIGH for 500ms, you are starting on the HIGH phase.

I was testing using two indicator leds with visually apparent pwm timing. One led was turned on at the exit from setup.

The led controlled by the compare match at TOP was interesting. When TCNT4 was set to 0 at the start, the led turned immediately on.

What I later found with starting TCNT4 =1 , the timer would go through one complete cycle to the 16bit max value, and then start the periodic 50% output.

There is a "hack" which actualy has the pin low for the first half cycle, and that is to start with TCNT4 at the compare match value less than the 16 bit top.

For example in this case if TCNT4 is initialized to 65535-7815 = 57720 there is a half second dead band before the output goes high.

//// set up Timer 4
int myEraserDir = 7;             // this is 111 in binary and is used as an eraser
TCCR4B &= ~myEraserDir;   // this operation (AND plus NOT),  set the three bits in TCCR4B to 0

TCCR4A = _BV(COM4A0)| _BV(WGM41) | _BV(WGM40); // fast PWM
TCCR4B = _BV(WGM43) | _BV(WGM42); // 16MHz/1024=15625Hz
OCR4A =  7815;          // 15625Hz/1Hz=15625 (50% duty--> 7812.5)
TCNT4 = 57720;
TCCR4B |= _BV(CS42)| _BV(CS40); //start timer

cattledog:
I was testing using two indicator leds with visually apparent pwm timing. One led was turned on at the exit from setup.

The led controlled by the compare match at TOP was interesting. When TCNT4 was set to 0 at the start, the led turned immediately on.

What I later found with starting TCNT4 =1 , the timer would go through one complete cycle to the 16bit max value, and then start the periodic 50% output.

There is a "hack" which actualy has the pin low for the first half cycle, and that is to start with TCNT4 at the compare match value less than the 16 bit top.

For example in this case if TCNT4 is initialized to 65535-7815 = 57720 there is a half second dead band before the output goes high.

//// set up Timer 4

int myEraserDir = 7;             // this is 111 in binary and is used as an eraser
TCCR4B &= ~myEraserDir;   // this operation (AND plus NOT),  set the three bits in TCCR4B to 0

TCCR4A = _BV(COM4A0)| _BV(WGM41) | _BV(WGM40); // fast PWM
TCCR4B = _BV(WGM43) | _BV(WGM42); // 16MHz/1024=15625Hz
OCR4A =  7815;          // 15625Hz/1Hz=15625 (50% duty--> 7812.5)
TCNT4 = 57720;
TCCR4B |= _BV(CS42)| _BV(CS40); //start timer

Can I ask you why 7815? If I am getting it correctly is because 15625-->1 Hz so 15625/2 is 30 seconds. But then, why 7815 and not 7813?
In case it's 2Hz and I want to keep the pin low for the first quarter cycle should I replace 7813 with 3907?

Can I ask you why 7815? If I am getting it correctly is because 15625-->1 Hz so 15625/2 is 30 seconds. But then, why 7815 and not 7813?
In case it's 2Hz and I want to keep the pin low for the first quarter cycle should I replace 7813 with 3907?

The 7815 value came from your post #15 when you switched to 1 Hz for simplicity and I carried on using it.

Use whatever values give the best result on the scope. The processor clock is not highly accurate and if you need very specific periods it is best to set it experimentally for the processor used.

I still believe that you issues with "inversion" and the need for the unusual procedure used to create the leading LOW is related to your use of fast pwm to OCR4A with a toggle on compare match.

You may be better off using fast pwm to ICR4 which allows you to set an inverting mode at a compare match halfway to the ICR4 top value. Using the compare match at OCR4A TOP with a toggle at 2X the frequency is creating issues.

Furthermore, since you are trying to control the direction change of a stepper at 2Hz, there I'm not sure I see the need for a hardware timer. With a software timer using millis or micros you might have more control over the pattern.

cattledog:
The 7815 value came from your post #15 when you switched to 1 Hz for simplicity and I carried on using it.

Use whatever values give the best result on the scope. The processor clock is not highly accurate and if you need very specific periods it is best to set it experimentally for the processor used.

I still believe that you issues with "inversion" and the need for the unusual procedure used to create the leading LOW is related to your use of fast pwm to OCR4A with a toggle on compare match.

You may be better off using fast pwm to ICR4 which allows you to set an inverting mode at a compare match halfway to the ICR4 top value. Using the compare match at OCR4A TOP with a toggle at 2X the frequency is creating issues.

Furthermore, since you are trying to control the direction change of a stepper at 2Hz, there I'm not sure I see the need for a hardware timer. With a software timer using millis or micros you might have more control over the pattern.

Hi cattledog, many thanks for your prompt reply. Always appreciate your advices.
I have replaced OCR4A with 3907 (2Hz) and TCNT4 with 61630 and it works perfectly. The square wave of 2Hz generated is initially LOW.
I have now another issue. I am using the following code to generate a 27kHz--> STEP Pin and 2 Hz --> DIR Pin of a stepper motor:

const byte PULSES = 5;  // Timer 3 "A" output: OC3A --> 27 kHz                                                                                                                                                                                                       
const byte DIR = 6;  // Timer 4 "A" output: OC4A --> 2 Hz
boolean a=false;
boolean b=false;
boolean c=false;

void setup() {
  pinMode (PULSES, OUTPUT);
  pinMode (DIR, OUTPUT);
  Serial.begin(9600);

  //  et up Timer 3
  int myEraserPulses = 7;             // this is 111 in binary and is used as an eraser
  TCCR3B &= ~myEraserPulses;   // this operation (AND plus NOT),  set the three bits in TCCR2B to 0
  TCCR3A = _BV(COM3A0) | _BV(WGM31) | _BV(WGM30); // fast PWM
  TCCR3B = _BV(WGM33) | _BV(WGM32); // 16MHz/8=2MHz
  OCR3A =  36;          // 2MHz/22kHz=90.90 (50% duty--> 45)   11kHz=89;  16kHz=61;  22kHz=44; 27 kHz=36;  32kHz=30; 37kHz=26
  TCNT3 = 0;
  TCCR3B |= _BV(CS31); //start timer

  // set up Timer 4
  int myEraserDir = 7;             // this is 111 in binary and is used as an eraser
  TCCR4B &= ~myEraserDir;   // this operation (AND plus NOT),  set the three bits in TCCR4B to 0
  TCCR4A = _BV(COM4A0) | _BV(WGM41) | _BV(WGM40); // fast PWM
  TCCR4B = _BV(WGM43) | _BV(WGM42); // 16MHz/1024=15625Hz
  OCR4A =  3907 ;          // 15625Hz/1Hz=15625 (50% duty--> 7812.5) 1Hz=7812 ; 1.5Hz=5208 ; 2Hz=3907 ; 3Hz = 2604
  TCNT4 = 61630;
  TCCR4B |= _BV(CS42) | _BV(CS40); //start timer

}  // end of setup

void loop() {
//
if (millis()>4660 && a==false && b==false){
   TCCR3A &= ~(_BV(COM3A0));  // Turn off PWM output
   TCCR4A &= ~(_BV(COM4A0));  // Turn off PWM output
   slowDownSTEPPER();
   a=true;
    }
if (millis()>15555 && b==false){
   TCCR3A &= ~(_BV(COM3A0));  // Turn off PWM output
   TCCR4A &= ~(_BV(COM4A0));  // Turn off Dir output
   b=true;
    }
if (millis()>25445 && c==false){
  STEPPER2Hz27kHz();
  c=true;
}

}
void slowDownSTEPPER() {

  int myEraserDir = 7;             // this is 111 in binary and is used as an eraser
  TCCR4B &= ~myEraserDir;   // this operation (AND plus NOT),  set the three bits in TCCR4B to 0
  TCCR4A = _BV(COM4A0) | _BV(WGM41) | _BV(WGM40); // fast PWM
  TCCR4B = _BV(WGM43) | _BV(WGM42); // 16MHz/1024=15625Hz
  OCR4A =  7810 ;          // 15625Hz/1Hz=15625 (50% duty--> 7812.5) 1Hz=7812 ; 1.5Hz=5208 ; 2Hz=3907 ; 3Hz = 2604
  TCNT4 = 57726;
  TCCR4B |= _BV(CS42) | _BV(CS40); //start timer
  delay(250);
  int myEraserPulses = 7;             // this is 111 in binary and is used as an eraser
  TCCR3B &= ~myEraserPulses;   // this operation (AND plus NOT),  set the three bits in TCCR2B to 0
  TCCR3A = _BV(COM3A0) | _BV(WGM31) | _BV(WGM30); // fast PWM
  TCCR3B = _BV(WGM33) | _BV(WGM32); // 16MHz/8=2MHz
  OCR3A =  210;          // 2MHz/22kHz=90.90 (50% duty--> 45)   11kHz=89;  16kHz=61;  22kHz=44; 27 kHz=36;  32kHz=30; 37kHz=26
  TCNT3 = 0;
  TCCR3B |= _BV(CS31); //start timer

}

void STEPPER2Hz27kHz() {

  int myEraserDir = 7;             // this is 111 in binary and is used as an eraser
  TCCR4B &= ~myEraserDir;   // this operation (AND plus NOT),  set the three bits in TCCR4B to 0
  TCCR4A = _BV(COM4A0) | _BV(WGM41) | _BV(WGM40); // fast PWM
  TCCR4B = _BV(WGM43) | _BV(WGM42); // 16MHz/1024=15625Hz
  TCNT4 = 61630;
  OCR4A =  3907 ;          // 15625Hz/1Hz=15625 (50% duty--> 7812.5) 1Hz=7812 ; 1.5Hz=5208 ; 2Hz=3907 ; 3Hz = 2604
  TCCR4B |= _BV(CS42) | _BV(CS40); //start timer
  
  int myEraserPulses = 7;             // this is 111 in binary and is used as an eraser
  TCCR3B &= ~myEraserPulses;   // this operation (AND plus NOT),  set the three bits in TCCR2B to 0
  TCCR3A = _BV(COM3A0) | _BV(WGM31) | _BV(WGM30); // fast PWM
  TCCR3B = _BV(WGM33) | _BV(WGM32); // 16MHz/8=2MHz
  OCR3A =  36;          // 2MHz/22kHz=90.90 (50% duty--> 45)   11kHz=89;  16kHz=61;  22kHz=44; 27 kHz=36;  32kHz=30; 37kHz=26
  TCNT3 = 0;
  TCCR3B |= _BV(CS31); //start timer

}

After generating 27kHz-2Hz in the void setup, I want to slow down the motor after more or less 5 seconds. Then my goal is to stop the motor and restarting it after 15 seconds with the initial 27kHz-2Hz.
I am successfully performing the initial start and the slowing down but not the restart. Indeed when the motor restarts (even if the code to generate the 27kHz-2Hz restart is equal to the initial start), the 2 signals I got in output on STEP and DIR pins are different. The 2Hz is initially HIGH for 750 ms, whereas with the initial start is LOW for 250 ms.
I need the signal to be initially LOW as it is during the initial start.

I suspect this happens because I stop the motor while is running and TCNTx has some value saved inside while in the beginning it starts from the default value.

Slow down attached

Restart (not working).

I suspect this happens because I stop the motor while is running and TCNTx has some value saved inside while in the beginning it starts from the default value.

No I don't think this is the root cause, because in all cases you set TCNT4 to a specific value with the timer stopped, and this should be where the count starts from.

I must confess I am not very clear on what is going on.

One possibility is that the output pin states are not controlled for the restart in the same manner as in setup where they are default LOW from the initial pinMode. The output may be HIGH when you disconnect the pins from the timer outputs after they have been running.

Try to set the outputs LOW, when you turn them off.

TCCR3A &= ~(_BV(COM3A0));  // Turn off PWM output
digitalWrite(PULSES, LOW);//ensure output is LOW
TCCR4A &= ~(_BV(COM4A0));  // Turn off Dir output
digitalWrite(DIR, LOW);//ensure output is LOW

I also notice is that there is a difference between the set up and the restart case involving the order of the timers. Try to make the restart exactly like the setup with Timer3 setup before Timer4.

Are you trying to synchronize the two timers? You don't seem to be using the GTCCR which has some synchronization function.

cattledog:
Try to set the outputs LOW, when you turn them off.

TCCR3A &= ~(_BV(COM3A0));  // Turn off PWM output

digitalWrite(PULSES, LOW);//ensure output is LOW
TCCR4A &= ~(_BV(COM4A0));  // Turn off Dir output
digitalWrite(DIR, LOW);//ensure output is LOW




I also notice is that there is a difference between the set up and the restart case involving the order of the timers. Try to make the restart exactly like the setup with Timer3 setup before Timer4.

I have implemented those changes in my code but still getting an error on the next PWM generated.
What I notice is that there is a correlation between the last status of the PWM "Slowing Down" and the first status of the PWM " Restart". If you look at the figures attached, when the "Slowing Down" PWM ends in HIGH status, the "Restart" PWM will start in HIGH status. No matter if I digitalwrite the DIR pin to LOW

I honestly don't understand why this happen.

Same happens if the "Slowing Down" PWM ends in LOW status: the "Restart" PWM will start in LOW status.

johnwasser:
Are you trying to synchronize the two timers? You don't seem to be using the GTCCR which has some synchronization function.

Yes, I am trying to synchronize the two timers.
I wasn't aware of GTCCR! Thanks a lot. I will definitely take a look and let you know.

cattledog:
No I don't think this is the root cause, because in all cases you set TCNT4 to a specific value with the timer stopped, and this should be where the count starts from.

I must confess I am not very clear on what is going on.

Found this online and I think is the issue I am facing:
(ATmega Timer Syncrhonization | Open Music Labs)
There are many more possible issues one might encounter when changing the timer states mid-application. For example, if one timer is running, and another has just started, but not made its first compare match, and is using OCRA as TOP, there will be no way to synchronize the timers. One work-around in this case is to delay until the timer makes a compare match, and then sync the timers. There may be other solutions to this problem, but it seems obscure enough to not worry about at the moment. And remember, a compare-match will always fail 1 clock cycle after TCNT is changed!

I do not think that you have a synchronization issue as you are not looking a few ticks difference between timer counts. I believe that the cause is that the timer hardware output pin initial state remains in its previous state until the compare match toggle. The timer output is distinct from the digital i/o mode and we are not resetting it with the digitalWrite() command.

I'm not clear about how to gain control over the timer output pin initial state before the compare match event and some deep review of the data sheet is in order. There may be something like the Force Output Compare (only valid for non pwm modes), which can be used in the pwm modes.

You may have a faster path to a solution by placing the 2Hz direction change timer in software with digital pin output.

Set the Dir pin low when the Timer3 is off. Set a flag when you start the high frequency Timer3 output, and use that flag to control the delayed start for the toggle of the DIR pin.

cattledog:
You may have a faster path to a solution by placing the 2Hz direction change timer in software with digital pin output.

Set the Dir pin low when the Timer3 is off. Set a flag when you start the high frequency Timer3 output, and use that flag to control the delayed start for the toggle of the DIR pin.

Agree, this will definitely be the faster solution but I am not a huge fan of software with digital pin output. I like my current PWM generation using timers. Anyway I will implement also the synchronization since also if it's about few ticks, it will make my system more accurate.
When I stop the "initial start" or the "slowing down" I need to bring the OCRxA to the compare match toggle, otherwise the new PWM wave will start according to the last HIGH/LOW PWM status

When I stop the "initial start" or the "slowing down" I need to bring the OCRxA to the compare match toggle, otherwise the new PWM wave will start according to the last HIGH/LOW PWM status

I think that you need to bring the TCNT value to the compare match toggle point.

Maybe you can force the toggle, but how will you know if the next start will be high or low? How you will know what the output value is when you make the change.

If you insist on using the hardware timer for the 2Hz, and you need to force a low start, I would look at using Fast pwm to a top value set with ICR4 instead of OCR4A. That way you can eliminate the toggle for a known state.
That is, use Mode14 instead of Mode15. For the same frequency, make the ICR4 2x the value used for the toggle point.

Then set OCR4A compare match to ICR4/2 and use the inverted mode. The first half of the timer run (from TCNT 0 to OCR4A) the timer pin output will be LOW and the second half (from OCR4A to TOP) pin will be HIGH after the compare match point at 50%.

I think that you need to bring the TCNT value to the compare match toggle point. --> YOU ARE RIGHT. Forcing the toggle didn't help either.

Do you mean something like this?

  GTCCR = _BV(TSM) | _BV(PSRSYNC); 
  //  Set up Timer 3
  int myEraserPulses = 7;             // this is 111 in binary and is used as an eraser
  TCCR3B &= ~myEraserPulses;   // this operation (AND plus NOT),  set the three bits in TCCR2B to 0
  TCCR3A = _BV(COM3A0) | _BV(WGM31) | _BV(WGM30); // fast PWM
  TCCR3B = _BV(WGM33) | _BV(WGM32); // 16MHz/8=2MHz
  OCR3A =  36;          // 2MHz/22kHz=90.90 (50% duty--> 45)   11kHz=89;  16kHz=61;  22kHz=44; 27 kHz=36;  32kHz=30; 37kHz=26
  TCNT3 = 0;
  TCCR3B |= _BV(CS31); //start timer

  // set up Timer 4
  int myEraserDir = 7;             // this is 111 in binary and is used as an eraser
  TCCR4B &= ~myEraserDir;   // this operation (AND plus NOT),  set the three bits in TCCR4B to 0
  TCCR4A = _BV(COM4A0) | _BV(COM4A1) |_BV(WGM41) ; // fast PWM
  TCCR4B = _BV(WGM43) | _BV(WGM42); // 16MHz/1024=15625Hz
  ICR4 =  7814 ;          // 15625Hz/1Hz=15625 (50% duty--> 7812.5) 1Hz=7812 ; 1.5Hz=5208 ; 2Hz=3907 ; 3Hz = 2604
  OCR4A = 3907;
  TCNT4 = 61630;
  TCCR4B |= _BV(CS42) | _BV(CS40); //start timer

  GTCCR = 0;

However, for Timer 4 after the first 250 ms LOW, I am getting an unexpected 500 ms HIGH and then it goes back to 250 ms period PWM.

Also, it doesn't seem to solve the issue of unpairing the last pwm status with the new pwm generation.

The setup for Timer4 looks like what I had in mind for changing the mode.

TCNT4 = 61630;

This method of starting near the timer's max count to produce a dead band was found to work with the ongoing toggle at a lower compare match value in the running state.

With fast pwm to ICR4 with inverted output it may not be doing the same thing.

Try to start the Timer with TCNT4 = 0. I that does not give the first half cycle at LOW, try to start with TCNT4 = 1.