How do I make a PWM signal run once only.

Hi

I have code running a PWM signal synchronously on 2 channels and for the time frames i require. However, I need to use the signal to open an close switches so only want the signal to run once. At the moment the signal just continuously repeats.

The code is below. I've been testing it by entering a number on the serial monitor to jump to a function switching the PWM channels on. Ive tried implementing it and then disabling the channels but i get no signal at all. Same thing happens if I set all the duty cycles back 0.

Any help would be greatly appreciated!! :slight_smile:

int doSwitch = 0;
void setup() {
  
 /*************** PWM set-up on pins  D7 and D6 for channels 6 & 7 respectively*************************************/
  PMC->PMC_PCER1 |= PMC_PCER1_PID36;                                               // Enable PWM 
  
 
  PIOC->PIO_ABSR |= PIO_ABSR_P24 | PIO_ABSR_P23;                                    // Set the port C PWM pins to peripheral type B
  

  PIOC->PIO_PDR |= PIO_PDR_P24 | PIO_PDR_P23;                                       // Set the port C PWM pins to outputs
  
  PWM->PWM_CLK = PWM_CLK_PREA(0) | PWM_CLK_DIVA(16);                                // Set the PWM clock A rate to 5.25MHz (84MHz/16)
  
  PWM->PWM_SCM |= PWM_SCM_SYNC7 | PWM_SCM_SYNC6 | PWM_SCM_SYNC0;                    // Set the PWM channels as synchronous
                   
 
  PWM->PWM_CH_NUM[0].PWM_CMR = PWM_CMR_CPRE_CLKA;                                   // Enable single slope PWM and set the clock source as CLKA for all synchronous channels
  
  PWM->PWM_CH_NUM[0].PWM_CPRD = 37500;                                              // Set the PWM frequency 5.25MHz/(37500) = 140Hz for all synchronous channels
  
 
Serial.begin(9600);
}

void loop() {
Serial.println("press a number");
delay(200);
if (Serial.available() > 0)
{
doSwitch = Serial.read();
}
if (doSwitch > 0){
  Serial.print("Switching");
  doSwitches();
  doSwitch = 0;
}

}
/*******************FUNCTIONS****************************************/

void doSwitches(){
  
  PWM->PWM_CH_NUM[0].PWM_CDTY = 315;                                               // Set the PWM duty cycle to 0.84%
  PWM->PWM_CH_NUM[6].PWM_CDTY = 315; 
  PWM->PWM_CH_NUM[7].PWM_CDTY = 315;   
 
  
  PWM->PWM_CH_NUM[7].PWM_CMR = PWM_CMR_DTE | PWM_CMR_CPRE_CLKA;                   // Enable single slope PWM and set the clock source as CLKA for all synchronous channels
  PWM->PWM_CH_NUM[7].PWM_DT = PWM_DT_DTH(0) | PWM_DT_DTL(630);                    // Set the low and high dead-time for 120us delay (140Hz => 120us period)
  PWM->PWM_CH_NUM[7].PWM_CDTY = 3150 + 630;                                       // Set the PWM duty cycle to 8.4%
  PWM->PWM_ENA = PWM_ENA_CHID7 | PWM_ENA_CHID6 | PWM_ENA_CHID0;                   // Enable all PWM channels10
  // PWM->PWM_DIS = PWM_DIS_CHID7 | PWM_DIS_CHID6 | PWM_DIS_CHID0;
   
}

Here's a link to some code that uses the PWM controller's interrupt service routine to generate 8 pulses, however it could be easily modified to output a single pulse: generating 8 40KHz pulses - Arduino Due - Arduino Forum.

1 Like

Hi Martin Thanks for the help!

I have the pulse running once but Ive lost the dead time for some reason I'm not sure why? Ive attached a scope pic of the original signal that I had/require and another showing the single pulse signal I'm getting now that is overlapped. My code is also attached. I'm sure it is just the order the code is written in but I cant seem to get it right. Any help would be appreciated.

int doSwitch = 0;
int counter = 0;
 
void setup() {
  
 /*************** PWM set-up on pins  D7 and D6 for channels 6 & 7 respectively*************************************/
  PMC->PMC_PCER1 |= PMC_PCER1_PID36;                                               // Enable PWM 
  
  PIOC->PIO_ABSR |= PIO_ABSR_P24 | PIO_ABSR_P23;                                    // Set the port C PWM pins to peripheral type B
  
  PIOC->PIO_PDR |= PIO_PDR_P24 | PIO_PDR_P23;                                       // Set the port C PWM pins to outputs
  
  PWM->PWM_CLK = PWM_CLK_PREA(0) | PWM_CLK_DIVA(16);                                // Set the PWM clock A rate to 5.25MHz (84MHz/16)
  
  PWM->PWM_SCM |= PWM_SCM_SYNC7 | PWM_SCM_SYNC6 | PWM_SCM_SYNC0;                    // Set the PWM channels as synchronous
                    
  PWM->PWM_CH_NUM[0].PWM_CMR = PWM_CMR_CPRE_CLKA;                                   // Enable single slope PWM and set the clock source as CLKA for all synchronous channels
  
  PWM->PWM_CH_NUM[0].PWM_CPRD = 37500;                                              // Set the PWM frequency 5.25MHz/(37500) = 140Hz for all synchronous channels
  
  PWM->PWM_CH_NUM[0].PWM_CDTY = 0;                                               // Set the PWM duty cycle to 0.84%
  PWM->PWM_CH_NUM[6].PWM_CDTY = 0; 
  PWM->PWM_CH_NUM[7].PWM_CDTY = 0;   
  
  NVIC_SetPriority(PWM_IRQn, 0);                                                  // Set the Nested Vector Interrupt Controller (NVIC) priority for the PWM controller to 0 (highest)
  NVIC_EnableIRQ(PWM_IRQn);                                                       // Connect PWM Controller to Nested Vector Interrupt Controller (NVIC)
  REG_PWM_IER1 = PWM_IER1_CHID0 ;                                                 // Enable interrupt on PWM channel 0 triggered at end of PWM period
  
  PWM->PWM_ENA = PWM_ENA_CHID7 | PWM_ENA_CHID6 | PWM_ENA_CHID0;                   // Enable all PWM 

Serial.begin(9600);
}

void loop() {
  // put your main code here, to run repeatedly:
Serial.println("press a number");
delay(200);
    if (Serial.available() < 2 )
      {
      doSwitch = Serial.read();
      }
      if (doSwitch > 0)
        {
          Serial.print("Stim");
          REG_PWM_IER1 = PWM_IER1_CHID0;    // Enable event interrupts 
          doSwitch = 0;
        }
    }

/*******************FUNCTIONS****************************************/

void PWM_Handler() {
  if (REG_PWM_ISR1 & PWM_ISR1_CHID0 )    // Check if an update condition has occured
  {   
    if (counter == 0)
    {
      counter++;
      PWM->PWM_CH_NUM[0].PWM_CDTY = 315;                                               // Set the PWM duty cycle to 0.84%
      PWM->PWM_CH_NUM[6].PWM_CDTY = 315; 
      PWM->PWM_CH_NUM[7].PWM_CDTY = 315;   

      PWM->PWM_CH_NUM[7].PWM_CMR = PWM_CMR_DTE | PWM_CMR_CPRE_CLKA;                   // Enable single slope PWM and set the clock source as CLKA for all synchronous channels
      PWM->PWM_CH_NUM[7].PWM_DT = PWM_DT_DTH(0) | PWM_DT_DTL(630);                    // Set the low and high dead-time for 120us delay (140Hz => 120us period)
      PWM->PWM_CH_NUM[7].PWM_CDTY = 3150 + 630;                                       // Set the PWM duty cycle to 8.4%
    }
    else
    {
      counter = 0;                      // Reset the counter
      PWM->PWM_CH_NUM[0].PWM_CDTY = 0;                                               // Set the PWM duty cycle to 0.84%
      PWM->PWM_CH_NUM[6].PWM_CDTY = 0; 
      PWM->PWM_CH_NUM[7].PWM_CDTY = 0;      
      REG_PWM_IDR1 = PWM_IDR1_CHID0;    // Disable interrupts     
    }
  }
}

Hi new_to_due,

I had a go at trying to get dead-time insertion together with synchronous PWM outputs and single pulse output, but it appears that doing so causes the Due to act strangely. I think that combining all three features is straying outside the bounds of what I'd call PWM controller's normal operation.

It appears that dead-time insertion only works if the PWM clock is not divided down, which isn't helpful if you require low frequency output. Also, the output PWM waveforms only work if the channel 0 duty-cycle update register is loaded with zero.

If your intention is to use dead-time insertion for a H-bridge, it might be better to use two asynchronous channels' high (PWMHx) and low side (PWMLx) complementary PWM outputs and adjust their high (DTH) and low (DTL) dead-time insertion accordingly. I'm not familiar with the H-bridge, but I imagine this is how the Due's PWM channels with dead-time insertion are intended to be used.

IMO PWM_SMMR (or TC_SMMR) is the register to be used for H-bridge control. You will find PWM waveforms outputs to provide a 2-bit gray count waveform on 2 outputs page 981 of Sam3x datasheet. Unfortunately, Figure 38-6 is wrong but you can find the correct figure (Figure 39_6) page 962 of Sam4S datasheet.

Whenever you have to code PWM waveforms, it's handy to draw the waveforms you need for a few periods, then look for the proper registers to program.

Hi ard _Newbie Thanks for the suggestion. Wondering if you have any example code in regards to this

ard_newbie:
IMO PWM_SMMR (or TC_SMMR) is the register to be used for H-bridge control. You will find PWM waveforms outputs to provide a 2-bit gray count waveform on 2 outputs page 981 of Sam3x datasheet. Unfortunately, Figure 38-6 is wrong but you can find the correct figure (Figure 39_6) page 962 of Sam4S datasheet.

Whenever you have to code PWM waveforms, it's handy to draw the waveforms you need for a few periods, then look for the proper registers to program.

Im ok with and are used to AVR but Im having real difficulty implementing this ARM seem a lot more difficult to understand and implement. Any help in implementing your suggestion would be great.

Begin by posting a drawing of the PWM outputs you need, one above the other.

Hi again ard_Newbie
Ive attached a sketch of the outputs I need for the PWM. Hopefully you can read them well enough if not let me know and Ill redo it.

As discussed in earlier posts I just need the waveforms to run once on command. I have tried a number of different ways using interupts but it seems to always give some strange behaviour when trying to combine the interupts with the dead time functionality. It works sometimes and sometimes it doesnt. Bit frustrating!

If you run your waveforms only once and then the 2 outputs are at a low level, what is the interest to program 2 PWM outputs ? You can obtain the 2 outputs with PIO_SODR and PIO_CODR instead.

Sorry Im not sure what you mean by that ard_Newbie. I probably wasnt clear in my explanation I need the waveforms to run once on command to control a Hbridge. The timing needs to be quite precise and accurate for the switching and I need them to run anytime a particular action happens. PWM is probably the best way to do this considering the precision and accuracy required?

MartinL:
Hi new_to_due,

I had a go at trying to get dead-time insertion together with synchronous PWM outputs and single pulse output, but it appears that doing so causes the Due to act strangely. I think that combining all three features is straying outside the bounds of what I'd call PWM controller's normal operation.

It appears that dead-time insertion only works if the PWM clock is not divided down, which isn't helpful if you require low frequency output. Also, the output PWM waveforms only work if the channel 0 duty-cycle update register is loaded with zero.

If your intention is to use dead-time insertion for a H-bridge, it might be better to use two asynchronous channels' high (PWMHx) and low side (PWMLx) complementary PWM outputs and adjust their high (DTH) and low (DTL) dead-time insertion accordingly. I'm not familiar with the H-bridge, but I imagine this is how the Due's PWM channels with dead-time insertion are intended to be used.

Hey Martin I have tried your suggestion but cant seem to get it give me the outputs I require using different complementary channels. Again the dead time doesnt seem to be working for complementary channels. ie when I set the PWMHx channel to 100% duty cycle I cant seem to get a dead time in the channel, but perhaps I am using the registers incorrectly to do it it in this particular instance.

void setup () {

  // PWM Set-up on pins PC6 and PC9 (Arduino Pins 41(PWMH3)& Pins 39(PWMH2 )): see Datasheet chap. 38.5.1 page 973
  PMC->PMC_PCER1 |= PMC_PCER1_PID36;                    // PWM power ON
  
  PWM->PWM_DIS = PWM_DIS_CHID2 | PWM_DIS_CHID3;         // Disable PWM channel 2
 
  // Select Instance=PWM; Signal=PWML2 (channel 2); I/O Line=PC6 (P6, Arduino pin 38, see pinout diagram) ; Peripheral=B
  PIOC->PIO_PDR |= PIO_PDR_P6;                          // Set the pin to the peripheral PWM, not the GPIO

  PIOC->PIO_ABSR |= PIO_PC6B_PWML2;                     // Set PWM pin perhipheral type B
  
  // Select Instance=PWM; Signal=PWMH3 (channel 3); I/O Line=PC9 (P9, Arduino pin 41, see pinout diagram) ; Peripheral type =B
  PIOC->PIO_PDR |= PIO_PDR_P9;                          // Set the pin to the peripheral PWM, not the GPIO

  PIOC->PIO_ABSR |= PIO_PC9B_PWMH3;                     // Set PWM pin perhipheral type B

  PWM->PWM_CLK = PWM_CLK_PREA(0) | PWM_CLK_DIVA(16);    // Set the PWM clock rate to 2MHz (84MHz/42). Adjust DIVA for the resolution you are looking for

  PWM->PWM_CH_NUM[2].PWM_CMR = PWM_CMR_CPRE_CLKA;       // The period is left aligned, clock source as CLKA on channel 2
  PWM->PWM_CH_NUM[3].PWM_CMR = PWM_CMR_CPRE_CLKA;       // The period is left aligned, clock source as CLKA on channel 3

  PWM->PWM_CH_NUM[2].PWM_CPRD = 37500;                  // Channel 2 : Set the PWM frequency 2MHz/(2 * CPRD) = F ;
  PWM->PWM_CH_NUM[3].PWM_CPRD = 37500;                  // Channel 2 : Set the PWM frequency 2MHz/(2 * CPRD) = F ;
 
  PWM->PWM_CH_NUM[2].PWM_CDTY = 315;                    // Channel 2: Set the PWM duty cycle to x%= (CDTY/ CPRD)  * 100 % ;
  
  PWM->PWM_CH_NUM[3].PWM_CMR = PWM_CMR_DTE | PWM_CMR_CPRE_CLKA;        // Enable single slope PWM and set the clock source as CLKA for all synchronous channels
  PWM->PWM_CH_NUM[3].PWM_DT = PWM_DT_DTH(630) | PWM_DT_DTL(3780);      // Set the low and high dead-time to start at 120us to 720us (140Hz => 600us period)
  PWM->PWM_CH_NUM[3].PWM_CDTY = 37500;                                 // Set the PWM duty cycle to 100% for the high channel 
  
  PWM->PWM_ENA = PWM_ENA_CHID2 | PWM_ENA_CHID3;
}

void loop() {
  
}

Hi new_to_due,

Here's an example of complementary PWM outputs on digital pins D40 (PWM3L) and D41 (PWM3H).

The two outputs are complementary, or in other words the inverse of each other at a frequency of 100kHz (10us period).

A delay can be added to both the low and high side PWM output with the dead-time low (DTL) and dead-time high (DTH) respectively.

In this example the dead-time is set to 209 (839/4), or 2.5us, on both the low and high side outputs:

// Enable single-slope PWM at 100kHz on complementary channel 3 with dead-time insertion
void setup() {
  // PWM set-up on digital pins D40 (PWML3) and D41 (PWMH3)
  PMC->PMC_PCER1 |= PMC_PCER1_PID36;                              // Enable PWM 
  PIOC->PIO_ABSR |= PIO_ABSR_P9 | PIO_ABSR_P8;                    // Set the port C PWM pins to peripheral type B
  PIOC->PIO_PDR |=  PIO_PDR_P9 | PIO_PDR_P8;                      // Set the port C PWM pins to outputs
  PWM->PWM_CLK = PWM_CLK_PREA(0) | PWM_CLK_DIVA(1);               // Set the PWM clock A rate to 84MHz (84MHz/1)
  PWM->PWM_CH_NUM[3].PWM_CPRD = 839;                              // Set the PWM frequency 84MHz/(839 + 1) = 100kHz 
  PWM->PWM_CH_NUM[3].PWM_CMR = PWM_CMR_DTE | PWM_CMR_CPRE_CLKA;   // Enable single slope PWM and set the clock source as CLKA 
  PWM->PWM_CH_NUM[3].PWM_DT = PWM_DT_DTH(209) | PWM_DT_DTL(209);  // Set the dead-time for a 2.5us delay on both outputs
  PWM->PWM_CH_NUM[3].PWM_CDTY = 419;                              // Set the PWM duty cycle to 50%
  PWM->PWM_ENA = PWM_ENA_CHID3;                                   // Enable all PWM channels              
}

void loop() {}

DeadTimeInsertion.png

DeadTimeInsertion.png

Ive tried applying the complementry waveforms and dead time but i cant seem to get the two waveforms Im trying to get. I think Im stuggling with the principles of dead time could you please explain where actually DTH and DTL are applying the delays in each waveform?

Page 982:
Figure 38-7. Complementary Output Waveforms
E.g. with CPOL = 0, you see DTOH = PWMH output, and DTOL = PWML

DTH is the dead time applied to PWMH whereas DTL is applied to PWML

As you can see, DTH < CDTY and DTL < CPRD – CDTY (page 1051)

Hi new_to_due,

Ok, I had a go at solving your timing requirements.

You required a 60us pulse on one output, followed by a 600us pulse, 60us later on the other:

Here's the output I managed to generate on the Due. It matches your requirements with the exception of a tiny transient pulse on the high side output (PWMH3) at the beginning of the cycle:

DeadTimeInsertion2.png

The code uses two complementary outputs on a single PWM channel, employing the end of period interrupt service routine, dead-time insertion and output override. The pulses are triggered to occur every second:

// Enable single PWM pulses on complementary outputs on channel 3 with dead-time insertion and output override
void setup() {
  // PWM set-up on digital pins D40 (PWML3) and D41 (PWMH3)
  PMC->PMC_PCER1 |= PMC_PCER1_PID36;                              // Enable PWM 
  PIOC->PIO_ABSR |= PIO_ABSR_P9 | PIO_ABSR_P8;                    // Set the port C PWM pins to peripheral type B
  PIOC->PIO_PDR |=  PIO_PDR_P9 | PIO_PDR_P8;                      // Set the port C PWM pins to outputs
  PWM->PWM_CLK = PWM_CLK_PREA(0) | PWM_CLK_DIVA(84);              // Set the PWM clock A rate to 1MHz (84MHz/1)
  PWM->PWM_CH_NUM[3].PWM_CPRD = 719;                              // Set the PWM frequency 1MHz/(729 + 1) = 1389Hz 
  PWM->PWM_CH_NUM[3].PWM_CMR = PWM_CMR_DTE | PWM_CMR_CPRE_CLKA;   // Enable single slope PWM and set the clock source as CLKA 
  PWM->PWM_CH_NUM[3].PWM_DT = PWM_DT_DTH(59) | PWM_DT_DTL(0);     // Set the dead-time for a 60us delay on PWMH3
  PWM->PWM_CH_NUM[3].PWM_CDTY = 59;                               // Set the PWM duty cycle for a 60us pulse on PWML3
  NVIC_SetPriority(PWM_IRQn, 0);                                  // Set the Nested Vector Interrupt Controller (NVIC) priority for the PWM controller to 0 (highest) 
  NVIC_EnableIRQ(PWM_IRQn);                                       // Connect PWM Controller to Nested Vector Interrupt Controller (NVIC)
  PWM->PWM_IER1 = PWM_IER1_CHID3;                                 // Enable interrupt on PWM channel 3 triggered at end of PWM period
  PWM->PWM_ENA = PWM_ENA_CHID3;                                   // Enable all PWM channels              
}

void loop() {
  // Output PWM pulses every second 
  PWM->PWM_IER1 = PWM_IER1_CHID3;                                 // Enable end of period PWM interrupt on channels 3
  delay(1000);                                                    // Wait 1 second  
}

void PWM_Handler() {
  static uint8_t counter = 0;                                     // Initialise the counter
  
  if (PWM->PWM_ISR1 & PWM_ISR1_CHID3)                             // Check if an update condition has occured
  {   
    if (counter == 0)                                             // Initiate the output pulses
    {
      counter++;      
      PWM->PWM_CH_NUM[3].PWM_CDTYUPD = 59;                        // Set the PWM
      PWM->PWM_OSCUPD = PWM_OSCUPD_OSCUPH3;                       // Clear the PWMH3 output override
    }
    else                                                          // Clear the output pulses on subsequent periods
    {
      counter = 0;                                                // Reset the counter
      PWM->PWM_CH_NUM[3].PWM_CDTYUPD = 0;                         // Set the PWM duty cycle to 0% 
      PWM->PWM_OSSUPD = PWM_OSSUPD_OSSUPH3;                       // Override the PWMH3 output: set it to LOW (0v)
      PWM->PWM_IDR1 = PWM_IDR1_CHID3;                             // Disable update interrupts        
    }
  }
}

DeadTimeInsertion2.png

Thankyou guys. It is much appreciated!!

Here's a simplified version the produces the same pulses, but interleaves 2 synchronous PWM channels, by simply changing their duty-cycle and period every other cycle:

// Interleave two PWM pulses using different duty-cycles and periods on two synchronous PWM channels: 0 and 1 
void setup() {
  // PWM set-up on pins DAC1 and A8 for channels 0 and 1 respectively
  PMC->PMC_PCER1 |= PMC_PCER1_PID36;                   // Enable PWM 
  PIOB->PIO_ABSR |= PIO_ABSR_P17 | PIO_ABSR_P16;       // Set the port B PWM pins to peripheral type B
  PIOB->PIO_PDR |= PIO_PDR_P17 | PIO_PDR_P16;          // Set the port B PWM pins to outputs
  PWM->PWM_CLK = PWM_CLK_PREA(0) | PWM_CLK_DIVA(84);   // Set the PWM clock A rate to 1MHz (84MHz/84)
  PWM->PWM_SCM |= PWM_SCM_SYNC1 | PWM_SCM_SYNC0;       // Set the PWM channels as synchronous
  PWM->PWM_CH_NUM[0].PWM_CMR = PWM_CMR_CPRE_CLKA;      // Enable single slope PWM and set the clock source as CLKA for all synchronous channels
  PWM->PWM_CH_NUM[0].PWM_CPRD = 119;                   // Set the PWM frequency 84MHz/(839 + 1) = 100kHz for all synchronous channels
  PWM->PWM_CH_NUM[0].PWM_CDTY = 0;                     // Set the PWM duty cycle to 0%
  PWM->PWM_CH_NUM[1].PWM_CDTY = 0;                     // Set the PWM duty cycle to 0%
  NVIC_SetPriority(PWM_IRQn, 0);                       // Set the Nested Vector Interrupt Controller (NVIC) priority for the PWM controller to 0 (highest) 
  NVIC_EnableIRQ(PWM_IRQn);                            // Connect PWM Controller to Nested Vector Interrupt Controller (NVIC)  
  PWM->PWM_ENA = PWM_ENA_CHID1 | PWM_ENA_CHID0;        // Enable PWM channels 0 and 1
  PWM->PWM_SCUC = PWM_SCUC_UPDULOCK;                   // Set the update unlock bit to trigger an update at the end of the next PWM period         
}

void loop() {
  // Output PWM pulses every second 
  PWM->PWM_IER1 = PWM_IER1_CHID0;                      // Enable end of period PWM interrupt on channels 0 and 1
  delay(1000);                                         // Wait 1 second  
}

void PWM_Handler() {
  static uint8_t counter = 0;                          // Initialise the counter
  
  if (PWM->PWM_ISR1 & PWM_ISR1_CHID0)                  // Check if an update condition has occured
  {   
    if (counter == 0)                  // Initiate the output pulses
    {
      counter++;                                       // Increment the counter
      PWM->PWM_CH_NUM[0].PWM_CDTYUPD = 59;             // Set the first PWM duty-cycle for 60us pulse and period of 120us
      PWM->PWM_CH_NUM[1].PWM_CDTYUPD = 0;
      PWM->PWM_CH_NUM[0].PWM_CPRDUPD = 119;       
    }
    else if (counter == 1)
    {
      counter++;                                       // Increment the counter
      PWM->PWM_CH_NUM[0].PWM_CDTYUPD = 0;              // Set the second PWM duty-cycle for 600us pulse and period of 7030us
      PWM->PWM_CH_NUM[1].PWM_CDTYUPD = 599;
      PWM->PWM_CH_NUM[0].PWM_CPRDUPD = 7029;        
    }
    else
    {
      counter = 0;                                     // Reset the counter
      PWM->PWM_CH_NUM[0].PWM_CDTYUPD = 0;              // Reset the duty-cycle to 0 and set the period
      PWM->PWM_CH_NUM[1].PWM_CDTYUPD = 0;
      PWM->PWM_CH_NUM[0].PWM_CPRDUPD = 119;      
      PWM->PWM_IDR1 = PWM_IDR1_CHID0;                  // Disable update interrupts    
    }
    PWM->PWM_SCUC = PWM_SCUC_UPDULOCK;                 // Set the update unlock bit to trigger an update at the end of the next PWM period  
  }
}

It's somewhat simpler than using the dead-time insertion and complementary outputs method that I suggested above.

Hi MartinL,

There is also another way to output these 2 waveforms, that's with 2 synchro channels and an automatic update of Duty Cycles with the PDC DMA.

140 Hz = 84 MHz / 84(DIVA)/1(CPRD)/7142(Size of Buffers). Declare 2 Buffers: Wave_Duty0 for PWMH0 and Wave_Duty1 for PWMH1 of 7142 Half Words. Fill these 2 Buffers according to the wave forms you want. Enable PDC DMA. That should work.

Thanks ard_newbie,

The PDC DMA is something I intend to try out on the Arduino Due in the near future.