Inverted PWM: Problems at Extreme Duty Cycles

Hi, I'm trying to generate two complementary PWM signals for a custom DC/DC converter.

I am using an Arduino Mega2560.

The 2 PWM outputs are connected to pins 9 and 10, and I have inverted the signal on pin 10 by following
http://forum.arduino.cc/index.php?topic=48481.0
& Arduino PWM Solar Charge Controller #2 - Charge Pump - YouTube

The problem is at extreme duty cycles, the outputs are not correct.
When the duty cycle is 100% (255), both outputs are 1, instead of pin 9=1 and pin10=0.
Conversely, when the duty cycle is 0%, both outputs are 0, instead of pin 9=0 and pin10=1.

The intermediate values of 1-254 work fine.

May I know if this is normal and my code is correct?

To fix it, I can probably force it to the right values, e.g. if duty cycle=0, then force pin 10 to 255 & vice-versa

My code is

void setup() {
  // put your setup code here, to run once:
  // set the digital pin as output:
  pinMode(9, OUTPUT);
  pinMode(10, OUTPUT);


  TCCR2A = TCCR2A | B11000000; //invert OC2A pin 10 0xC0 0X30

}

void loop() {
 
  float duty = 0; //constant for testing

  analogWrite(9, duty);
  analogWrite(10, duty);

}

You will not be able to use analogWrite to change the values. You will have to directly access the registers. A quick perusal of the source code will reveal why.

I'm not sure what you mean. Where can I find the source code? Sorry, I'm a newbie using Arduino for the first time.

I'm following post #11 here, http://forum.arduino.cc/index.php?topic=48481.0, but modifying it slightly to use Timer2 so I can invert pin 10.

It works fine for intermediate values of duty=1 to 254 but not extreme values of 0 and 255.

I can get it to work if I force it by adding

  duty255_1 = duty;
  duty255_2 = duty;
  if (duty== 0)
  {
    duty255_2 = 255;
  }
  if (duty == 255)
  {
    duty255_2 = 0;
  }
  analogWrite(9, duty255_1);
  analogWrite(10, duty255_2);

So if I want to increase duty cycle by using a pot, after using the forced code above, essentially pin 9 runs from 0-255, while pin 10 runs from 255, 1-254, 0 during the same period. Is this normal?

boiledbeans:
Where can I find the source code?

On your computer.

Or here...
https://github.com/arduino/Arduino/blob/master/hardware/arduino/avr/cores/arduino/wiring_analog.c#L95

Arduino project is open source - so go and open the source and have a look...

analogWrite() configures the PWM outputs all the same, not in inverting/non-inverting
pairs, so you can't use it. Instead you just write the OCR register for that timer, perhaps here
OCR2A and OCR2B (double check, I haven't memorized the Mega timer pin assignments yet).

Hi, thanks for your replies.

I took a look at the source code in the previous post but I'm not sure what to look out for.

In my first post above, I do have a line which writes directly to the register to do the inverting.

TCCR2A = TCCR2A | B11000000;

This makes pin 10 opposite of pin 9.

As I increase the analogWrite output from 0 to 255 using a pot, pin 9 works fine. The duty cycle increases.

But for pin 10, as the analogWrite output increases from 0 to 255, the extremes don't work properly, i.e. 0 & 255. The centre portion 1-254 works fine, with the duty cycle decreasing because it is inverted.

So to fix pin 10, I wrote "if" statements in post #2 to swap 0 & 255 on pin 10. So analogWrite for pin 10 runs in this order to get the decreasing duty cycle: 255, 1-254, 0.

So my question is, is the 0 & 255 extremes getting swapped normal?

If this is not the right way to do it, then what should be the right way? Sorry, I am a newbie, could you provide a bit more detailed answers? Thanks. :slight_smile:

Other posters have tried to point you at the source code for analogWrite(). If you had looked at it, you would have seen that analogWrite(pin,0) actually calls digitalWrite(pin,LOW); and analogWrite(pin,255) calls digitalWrite(pin,HIGH). At the extremes, the timer settings are not used. This was done sometime in the past to fix a bug where analogWrite(pin,0) put out a short pulse of a single clock cycle.

Check the datasheet of the micro. I know the datasheet for the 328 has some information about special cases at the extremes (0 and 255); the behaviour is normal depending the timer and mode that you use.

Can't help further, unfortunately.

//Edit
I see that cattledog posted while I was typing so the above might not be applicable; interesting read none-the-less :wink:

Alright, thanks for pointing me in the right direction. Now I understand it! :smiley: