Generate PWM complementary signals with dead time

Hi To Everyone!

I am starting to work with Arduino for my project. I have to design the control loop including the PWM signals for an Half Bridge for Induction Cooking. At the first glance I would like to implement the two complementary signals for the high side and the low side plus the dead time and two interrupts for over voltage/current and over temperature.

I Start to work on the modulation and I am a little bit confuse. I am wondering if someone can give me some helpful advice.

Thank you

Vittorio

I've had to do this for a separate but similar project. However, the solution was not using an Arduino, but an XmegaA1. The AWEX unit on it will allow you to generate 2 complimentary signals with dead time as a peripheral unit, allowing you to do other things. Maybe the Arduino Mega2560 has this peripheral, but I'm not sure. Additionally, you need a fairly accurate crystal, as you never want your Half-bridge to shoot through, though with low enough frequencies you might be okay. You might be able to come up with an analog system that will take an input and generate the output with maybe some 555 timers. I think the Arduino Uno can handle this by basically writing your own code using delays and doing absolutely nothing else, which I'm not sure is useful.

Do you need it to be a half bridge? Can you not do it with a single transistor and drive it in a sort of Flyback mode?

Vittorio_ON: Hi To Everyone!

I am starting to work with Arduino for my project. I have to design the control loop including the PWM signals for an Half Bridge for Induction Cooking. At the first glance I would like to implement the two complementary signals for the high side and the low side plus the dead time and two interrupts for over voltage/current and over temperature.

I Start to work on the modulation and I am a little bit confuse. I am wondering if someone can give me some helpful advice.

Thank you

Vittorio

(Assuming an Uno)

If you use timer1 (pins 9 & 10) or timer2 (pins 11 and 3) you already have phase-correct PWM mode enabled, so all you have to do is set the two pins at slightly different values and invert one of them:

void setup ()
{
  TCCR1A = (TCCR1A & 0x0F) | 0xB0 ; // set pin 10 inverted
  int val = 100 ;
  int dead = 2 ;
  analogWrite (9, val) ;
  analogWrite (10, val+dead) ;
}
void loop ()
{}

Will give 8us deadtime with the PWM at its normal prescale of 1/64, since 16MHz/64 = 250kHz, or 4us steps, and dead=2 steps.

To get higher frequency PWM add

  TCCR1B = (TCCR1B & 0x0F8) | 0x01 ; // full speed 16MHz clock

larger values than 0x01 give different prescale dividers

MarkT:
(Assuming an Uno)

If you use timer1 (pins 9 & 10) or timer2 (pins 11 and 3) you already have
phase-correct PWM mode enabled, so all you have to do is set the two
pins at slightly different values and invert one of them:

void setup ()

{
  TCCR1A = (TCCR1A & 0x0F) | 0xB0 ; // set pin 10 inverted
  int val = 100 ;
  int dead = 2 ;
  analogWrite (9, val) ;
  analogWrite (10, val+dead) ;
}
void loop ()
{}



Will give 8us deadtime with the PWM at its normal prescale of 1/64,
since 16MHz/64 = 250kHz, or 4us steps, and dead=2 steps.

To get higher frequency PWM add


TCCR1B = (TCCR1B & 0x0F8) | 0x01 ; // full speed 16MHz clock



larger values than 0x01 give different prescale dividers

Hello, can explain me how i can use this code to do this:

i want a X= -1 * sin( 2pif) in pin 9 and a inverse in pin 3. i have tried but i can’t do it

void setup () { TCCR1A = (TCCR1A & 0x0F) | 0xB0 ; // set pin 10 inverted int val = 100 ; int dead = 2 ; analogWrite (9, val-dead) ; analogWrite (10, val+dead) ; } void loop () {}

to build Half Bridge deadtime must be between both signal edges. This line "analogWrite (9, val);" should be written like this: analogWrite (9, val-dead); Then we get a signal with the necessary pauses "dead time"

But that's twice the dead time! You only need one lot of dead time.

The subtlety that I did omit is that you should synchronize writing the values to the relevant timer interrupt so you don't catch the hardware just as its changing and accidentally overlap the two signals - no substitute for reading the datasheet in detail for this I'm afraid.

MarkT: But that's twice the dead time! You only need one lot of dead time.

The subtlety that I did omit is that you should synchronize writing the values to the relevant timer interrupt so you don't catch the hardware just as its changing and accidentally overlap the two signals - no substitute for reading the datasheet in detail for this I'm afraid.

Hi, how to make a "dead time"? Is the implementation described above not suitable for controlling power transistors?

ard_newbie:

I have done this.
PWM Dead Time

The part of the code below:

void PwmDutyPSetting()
{
#ifdef MOSFET_N_CHANNEL    
  int DutyCycleWithDeadTimeHighSideOutC;
  int DutyCycleWithDeadTimeHighSideOutA;

  if((ThermoelectricCoolingDuty <= 99) && (ThermoelectricCoolingDuty >= 0) && (PowerDirChange == 0))
  {
    DutyCycleWithDeadTimeHighSideOutC = ((int)DutyP((1-PowerDir) * ThermoelectricCoolingDuty)) - DeadTime;
    if(DutyCycleWithDeadTimeHighSideOutC < 0)
    {
      DutyCycleWithDeadTimeHighSideOutC = 0;
    }

    DutyCycleWithDeadTimeHighSideOutA = ((int)DutyP(PowerDir * ThermoelectricCoolingDuty)) - DeadTime;
    if(DutyCycleWithDeadTimeHighSideOutA < 0)
    {
      DutyCycleWithDeadTimeHighSideOutA = 0;
    }
    
    OCR1A = DutyCycleWithDeadTimeHighSideOutC;  //DutyP((1-PowerDir) * ThermoelectricCoolingDuty);//Pin9 OutC
    OCR1B = DutyP((1-PowerDir) * ThermoelectricCoolingDuty);//Pin10 OutD
    OCR0A = DutyCycleWithDeadTimeHighSideOutA;  //DutyP(PowerDir * ThermoelectricCoolingDuty);//Pin6 OutA
    OCR0B = DutyP(PowerDir * ThermoelectricCoolingDuty);//Pin5 OutB
  }
#else //MOSFET_P_CHANNEL
  int DutyCycleWithDeadTimeLowSideOutD;
  int DutyCycleWithDeadTimeLowSideOutB; 

  if((ThermoelectricCoolingDuty <= 100) && (ThermoelectricCoolingDuty >= 0) && (PowerDirChange == 0))
  {
    DutyCycleWithDeadTimeLowSideOutD = ((int)DutyP((1-PowerDir) * ThermoelectricCoolingDuty)) + DeadTime;
    if(DutyCycleWithDeadTimeLowSideOutD > 255)
    {
      DutyCycleWithDeadTimeLowSideOutD > 255;
    }

    DutyCycleWithDeadTimeLowSideOutB = ((int)DutyP(PowerDir * ThermoelectricCoolingDuty)) + DeadTime;
    if(DutyCycleWithDeadTimeLowSideOutB > 255)
    {
      DutyCycleWithDeadTimeLowSideOutB = 255;
    }    
    OCR1A = DutyP((1-PowerDir) * ThermoelectricCoolingDuty);//Pin9 OutC
    OCR1B = DutyCycleWithDeadTimeLowSideOutD; //DutyP((1-PowerDir) * ThermoelectricCoolingDuty);//Pin10 OutD
    OCR0A = DutyP(PowerDir * ThermoelectricCoolingDuty);//Pin6 OutA
    OCR0B = DutyCycleWithDeadTimeLowSideOutB; //DutyP(PowerDir * ThermoelectricCoolingDuty);//Pin5 OutB
  }
#endif
}