simple PWMC example

Hi everyone!

I am new to Arduino Due, and I chose it to control a half-bridge of IGBTs with it. So dead time generation is crucial in my case. This is why I chose pin 34(PWML0) and pin35(PWMH0) for this task, because they use the same channel, unlike PWM pins 6-9. The pinout diagram can be found here: http://forum.arduino.cc/index.php?topic=132130.0

Unfortunately I don't have an oscilloscope. May I ask someone to check the result (the two signals and the dead time) of my code? Please feel free to make some corrections in my code if needed. Thanks in advance for your help.

#define MASTER_CLOCK 84000000

uint32_t clock_a = 42000000; // Sampling frequency in Hz

void setup() 
{
  SetPin(34); // PWML0
  SetPin(35); // PWMH0
  
  pmc_enable_periph_clk(PWM_INTERFACE_ID);
  PWMC_ConfigureClocks(clock_a, 0, MASTER_CLOCK); // clock_b = 0
  PWMC_ConfigureChannelExt(PWM,
                           0, // Channel: 0          
                           PWM_CMR_CPRE_CLKA, // Prescaler: use CLOCK_A
                           0, // Aligment: period is left aligned
                           0, // Polarity: output waveform starts at a low level
                           0, // Counter event: occurs at the end of the period
                           PWM_CMR_DTE, // Dead time generator is enabled
                           0, // Dead time PWMH output is not inverted    
                           0);  // Dead time PWML output is not inverted
  PWMC_SetPeriod(PWM, 0, 1200); // Channel: 0, Period: 1/(1200/42 Mhz) = ~35 kHz
  PWMC_SetDutyCycle(PWM, 0, 600); // Channel: 0, Duty cycle: 50 %
  PWMC_SetDeadTime(PWM, 0, 42, 42); // Channel: 0, Rising and falling edge dead time: 42/42 Mhz = 1 us
  PWMC_EnableChannel(PWM, 0); // Channel: 0
}

void loop()
{
  // put your main code here, to run repeatedly:

}

void SetPin(uint8_t pin)
{
  PIO_Configure(g_APinDescription[pin].pPort,
                PIO_PERIPH_B, 
                g_APinDescription[pin].ulPin,
                g_APinDescription[pin].ulPinConfiguration);

}

Looks ok to me, see attached scope dump. Cursers are placed so you can check frequency. Also looks your deadtime of 1us is ok.

Sorry couldn’t upload attachement in that format. Here is another

Doc1.doc (208 KB)

Thank you very much for your help. I appreciate it, and it is also good to know that it works as intended.

I am glad I could help. One thing I noticed: You specified a duty cycle of 50%. If you look carefully at my scope dump you will notice that the duty cycle is slightly lower than 50% - due to the deadtime specified. You can’t have both so I guess this is as expected.

hi - is this set for a 33,3 kHz frequency, and if yes can I adapt this for a frequency of 150 kHz without dead-time. because I want to control a bridgedrive IC with integrated deadtime. So I need a synchronous ~150 kHz PWM. In optimal case I can adjust the duty cycle too.

if you find and install the DueTimer you can create different tasks with interrupt handle . I'm just now to try this library for TB6660 stepper driver , and I can change the interrupt time on fly That's a very powerfull library and usefull

Yes Nottelmann, you are correct. Basically this is the way how you can create dead time if you don't have a dead time generator by adjusting the two duty cycles with respect to each other, but that method is not too reliable.

Anyway I am planning to create a frequency correct PWM library for the Due. So I need to know which code generates the most accurate frequency. This new code, or the previous one, or both. You will have the option to use or not to use dead time in the final implementation. Thanks in advance.

#define MASTER_CLOCK 84000000

uint32_t clock_a = 42000000; // Sampling frequency in Hz

void setup() 
{
  SetPin(34); // PWML0
  SetPin(35); // PWMH0
  
  pmc_enable_periph_clk(PWM_INTERFACE_ID); // Turn on PWM clock
  PWMC_ConfigureClocks(clock_a, 0, MASTER_CLOCK); // clock_b = 0
  PWMC_ConfigureChannelExt(PWM,
                           0, // Channel: 0          
                           PWM_CMR_CPRE_CLKA, // Prescaler: use CLOCK_A
                           PWM_CMR_CALG, // Alignment: period is center aligned
                           0, // Polarity: output waveform starts at a low level
                           PWM_CMR_CES, // Counter event: occurs at the end and middle of the period
                           PWM_CMR_DTE, // Dead time generator is enabled
                           0, // Dead time PWMH output is not inverted    
                           0);  // Dead time PWML output is not inverted
  PWMC_SetPeriod(PWM, 0, 600); // Channel: 0, Period: 1/(1200/42 Mhz) = ~35 kHz
  PWMC_SetDutyCycle(PWM, 0, 300); // Channel: 0, Duty cycle: 50 %
  PWMC_SetDeadTime(PWM, 0, 42, 42); // Channel: 0, Rising and falling edge dead time: 42/42 Mhz = 1 us
  PWMC_EnableChannel(PWM, 0); // Channel: 0
}

void loop()
{
  // put your main code here, to run repeatedly:

}

void SetPin(uint8_t pin)
{
  PIO_Configure(g_APinDescription[pin].pPort, // Port
                PIO_PERIPH_B, // Peripheral
                g_APinDescription[pin].ulPin,
                g_APinDescription[pin].ulPinConfiguration);

}