I need to make sure that 2 PWM's dont overlap

I am trying to get pwm control over a step up transformer using a http://www.diodes.com/datasheets/ZXMC4A16DN8.pdf dual mosfet chip with an n-channel and a p-channel.

I had hoped that I could set one channel to say 50% and the other at 48% to insure that they never will pulse at the same time. If this happens my mosfets will short and die quickly. I actually need a small period of time where both are off before firing the next.

I have it working ok bitbanging, but would much rather fire and forget to take care of other business.

I am using a Mega and should have plenty of options here, but I am stuck.

Thanks

A good solution would be to go down to the chip level and use phase-correct PWM mode with complementary outputs. This is one of the supported timer modes, but you'll have to read the ATmega datasheet pretty carefully and do some experiments before committing to real MOSFET's.

See Section 16.9.4 of the ATmega1280 datasheet.

--
The Quick Shield: breakout all 28 pins to quick-connect terminals

You can go the hardware route this sheet has the circuit for a converter to generate two non overlapping clocks from a single clock input using two NAND gates and a few inverters. It's on page 5.

http://leyenda2.demon.co.uk/mike/Electronics/datasheets/crystal/cs7622design.pdf

Please consider the timing involved: the gate capcitor (around 1nF) of one transistor is discharged while the other is charged. The time constant to consider is around 1k (?) * 1n = 1us. This delay is in the order of software operations...

Thanks for the replies.

The timer thing is making me crazy. It looks to me like I need phase correct PWM with the second output inverted. If I then run a slightly smaller duty cycle on the inverted channel, I will have a small deadband between pulses.

Am I on the right track? I found these settings on Ken Shirriffs blog to set phase correct pwm. I added the com2b1 bit to invert.

pinMode(9, OUTPUT);
pinMode(10, OUTPUT);
COM2B1=3; // really unsure about this one.
TCCR2A = _BV(COM2A0) | _BV(COM2B1) | _BV(WGM20);
TCCR2B = _BV(WGM22) | _BV(CS22);
OCR2A = 180;
OCR2B = 50;

Well, how does it look like on the oscilloscope???

Yeah I hate AVR's docs sometimes.

I would like to set up "phase and freq correct" on timer 5
16 bit resolution is fine.
2khz is the goal for now with 2 outputs (one inverted)

I came up with this after hours of reading, but alas, no luck.

  ICR5 = 0x3E80;
  OCR5A = 0x7FFF;
  OCR5B = 0x7FFF;
  TCCR5A = B10110000;
  TCCR5B = B00011001;

the OCR5 settings are just randomly placed at the moment because no other values seem to work. Pins 44 and 45 are just staying high.

I am trying to use ICR5 to set the TOP because once I have what I want I will not be adjusting the freq. Supposedly this is best.

Well, how does it look like on the oscilloscope???

My scope won't let me see both at once in real time, but at the moment both pins just go high and stay there. I think I need another probe for the trigger. (actually I need a better scope)

Ok, I gave up on that method because it forces one pulse to be shorter than the other. I am on a new trail and for the life of me I can't figure out what is wrong.

#include <avr/interrupt.h>
#include <avr/io.h>
const int xformHV1 = 42; //;
const int xformHV2 = 43;

void setup()
{
  // initialize the serial communication:
  //Serial.begin(57600);
  //pinMode(pulsePoint, OUTPUT);
  pinMode(xformHV1, OUTPUT);
  pinMode(xformHV2, OUTPUT);
  digitalWrite(xformHV1, HIGH);
  delay(2);
    
  TCCR5B |= (1<<WGM52);  //timer5 CTC mode
  TIMSK5 |= (1 << OCIE5A); // Enable overflow interrupt 
  sei(); // enable global  interrupts
  OCR5A = 5264;  //sets CTC compare value
  TCCR5A &= (1<<COM5A1)|_BV(COM5B1)|_BV(COM5B0);
  TCCR5B = _BV(CS51) | _BV(CS50);  //start timer - prescale of 64?
}

ISR(TIMER5_COMPA_vect)
{
  if(PORTL & 0x40) //check bit 6 - pin 42
  {
   PORTL ^= (0x01 << 6); //turn off hv2
   //delayMicroseconds(2); //delay DS
  }
  if(PORTL & 0x80) //check bit 7 - pin 43
  {
   PORTL ^= (0x80 << 7);
   //delayMicroseconds(2);
   //bitWrite(PORTL, 7, 1); //turn on hv1
  }

Any ideas? -- edited to correct check of pin 43.
I know that the code at the moment should just turn off the pin that is set high at startup. As you can see I am trying different methods of bit manipulation.

the line TCCR5A = _BV(COM5A1)|_BV(COM5B1)|_BV(COM5B0); is an artifact that should be removed.

It's a bit late for me to mention but I just noticed this while digging through the datasheet...

It looks like the ATtiny85 processor has exactly what you need. It supports an inverted PWM pin with "dead time". (plus a whole bunch of other PWM options)

Whew! Ok, I have stared at this too long. I now have activity!!! Just not toggling like I want.

#include <avr/interrupt.h>
#include <avr/io.h>

const int xformHV1 = 42; //;
const int xformHV2 = 43;

ISR(TIMER5_COMPA_vect)
{
  if(PORTL & (0x01 << 7)) //check bit 7 - pin 42
  {
    PORTL = (0x00 << 7); //turn off hv2 toggle
    PORTL = (0x01 << 6); //toggle on hv1
    //bitWrite(PORTL, 7, 1);
    //delayMicroseconds(2); //delay DS
  }
 else
 {
    if(PORTL & (0x01 << 6)) //check bit 6 - pin 43
    {
      PORTL = (0x00 << 6); //toggle
      PORTL = (0x01 << 7); //turn on hv2 toggle
      //bitWrite(PORTL, 6, 1); //turn on hv1
      //delayMicroseconds(2);
    }
  }
}

void setup()
{
  pinMode(xformHV1, OUTPUT);
  pinMode(xformHV2, OUTPUT);
  digitalWrite(xformHV1, HIGH);
  delay(2);
  TCCR5B = 0;
  TCCR5B = _BV(WGM52);  //timer5 CTC mode
  TIMSK5 = _BV(OCIE5A); // Enable compare a match interrupt 
  sei(); // enable global  interrupts
  OCR5A = 1264;  //sets CTC compare
  TCCR5B = _BV(CS51);// | _BV(CS50);  //prescale of 64?
}

void loop()
{

}

I know that it is something stupid, so I am heading for lunch.

Ok, Code that finally works! The logic in the ISR is actually improper for my purposes, but for some reason (I suspect the digitalWrite routine), the dead time between pulses does not match.

Look at the simple ISR logic, imagine the waveform you should get and then try it out.

#include <avr/interrupt.h>
#include <avr/io.h>

const int xformHV1 = 42; //;
const int xformHV2 = 43;
int state = 0;
int laststate = 0;


void setup()
{
  pinMode(xformHV1, OUTPUT);
  pinMode(xformHV2, OUTPUT);
  //digitalWrite(xformHV1, HIGH);
  delay(2);
  TCCR5B = 0;
  TCCR5B = _BV(WGM52);  //timer5 CTC mode
  TIMSK5 = _BV(OCIE5A); // Enable compare a match interrupt 
  sei(); // enable global  interrupts
  OCR5A = 9000;  //sets CTC compare
  TCCR5B = _BV(CS51) | _BV(CS50);  //prescale of Fcpu/64
}

void loop()
{

}

ISR(TIMER5_COMPA_vect)
{
  if(state == 0)
  {
    digitalWrite(xformHV1, HIGH);  //digitalwrites waste time
    laststate = 0;
    state = 2;
    return;
  }

  if(state == 1)
  {
    digitalWrite(xformHV2, HIGH);
    laststate = 1;
    state = 2;
    return;
  }
  if(state == 2)
  {
    digitalWrite(xformHV1, LOW);
    digitalWrite(xformHV2, LOW);
    if(laststate == 0){
      state = 1;
    }
    if(laststate == 1){ 
      state = 0; 
    }
  }
}