Forum Rule: Always post complete source code & details to reproduce any issue!
Results 1 to 14 of 14

Thread: phase correct PWM

  1. #1

    phase correct PWM

    In real life I'm a university lecturer. I was recently 'asked' to supervise some power electronics labs on behalf of an absent colleague. The students are required to build a class D audio amplifier using a dsPIC & Microchip's 'dsPICDEM MC1H 3 phase high voltage power module'

    In essence, they need to read an analogue input & generate PWM outputs.

    I thought it might be interesting to try this with a Teensy 3.1, it looks as though Paul has almost done this for me already - the 'PassThrough' example for the audio card comes very close to what I want!

    However, rather than one PWM output per channel, I need two. We use two phases of the power module as a H bridge to drive a speaker. So I'd also like to generate a phase correct PWM output for the 'other' side of the bridge. Ideally, I'd like to manipulate this too so that a guard band can be produced to avoid simultaneous conduction in the upper & lower limbs of the bridge.

    I'm aware that a phase correct PWM library exists for the Arduino but I don't expect this to work with Teensy.

    I don't really have time to figure this out for myself so if anyone has a quick fix I'm all ears!

    Cheers

    Ian

  2. #2
    Senior Member Constantin's Avatar
    Join Date
    Nov 2012
    Location
    In the yard with a 17' Dia. Ferris Wheel
    Posts
    1,408
    I'm not familiar with these designs, but it seems that the most common solution is to use a inverter chip on the output. See figure 8 and 9 on this page, for a conceptual and one implementation example.
    Last edited by Constantin; 01-29-2014 at 07:39 PM.

  3. #3
    Thanks Constantin,
    An inverter is likely to produce huge transients in a real circuit when the upper & lower limbs of the bridge conduct simultaneously.
    A very nice class D amp based on a ATTiny is here: http://rdimitrov.twistedsanity.net/b...0D%20Amplifier
    It biasses the transistors with LEDs but I can't do that.

    Ian

  4. #4
    Senior Member
    Join Date
    Nov 2012
    Location
    Boston, MA, USA
    Posts
    1,108
    Quote Originally Posted by ian View Post
    I'm aware that a phase correct PWM library exists for the Arduino but I don't expect this to work with Teensy.
    It might or might not. Got a link to that library?

  5. #5
    Senior Member
    Join Date
    Sep 2013
    Location
    Sonoma County, CA
    Posts
    141
    If you're interested in going deeper into the micro controller hardware than just using arduino libraries, the flex timer module that is used for PWM has built in dead-time insertion and a mode that allows you to set one channel as the complement of another channel. It looks like it would be as simple as setting the COMBINE, COMP, and DTEN bits in the FTMx_COMBINE register for whichever pair of channels you want to use, and setting the FTMx_DEADTIME register to however long you want the dead time to be. That way you can set a single PWM value, and both your normal and inverted PWM signals will be generated automatically.

    Full disclosure: although I'm planning on using something similar for a project, I haven't actually implemented the complementary PWM stuff yet, so you may have to play around with it a little to get it to work (it's all in chapter 35 of the reference manual).

    Good luck!
    Last edited by whollender; 01-30-2014 at 01:33 AM.

  6. #6
    Have you had any luck getting the complementary PWM working?

    I'm trying to setup a complementary output on channels 2 and 3 of FlexTimer0. This is my first try dabbling with the K20 hardware directly, so maybe I've missed something completely.

    From what I can tell, I only need to enable the FlexTimer features with FTMEN = 1, combine channels 2 & 3 with COMBINE1 = 1, and set CH3 as the compliment of CH2 with COMP1 = 1.

    The problem I'm having is when I set FTMEN=1, the PWM output stops completely. Even after initializing the COMBINE register, I get no output after setting FTMEN = 1. Has anyone done this and could give me some pointers?

    Code:
    Code:
    const int ledPin =  13;
    const int PWM_H = 9;     //  FTM0 - CH2
    const int PWM_L = 10;    //  FTM0 - CH3
    
    void setup()   {                
      pinMode(ledPin, OUTPUT);
      pinMode(PWM_H, OUTPUT);
      pinMode(PWM_L, OUTPUT);
    
      analogWriteFrequency(PWM_H, 6000); // PWM frequency is 6kHz
      analogWriteResolution(10);         // 10-bits of PWM resolution
    
      FTM0_MODE = 0x5;          // FTMEN = 1, enables FlexTimer features/registers
    //  FTM0_COMBINE = 0x0030;    // COMP1 = 1, ch3 is the inverse of ch2
                                // COMBINE1 = 1, combines ch2 & ch3
                                
      analogWrite(PWM_H, 500);
    }
    
    void loop()                     
    {
      digitalWrite(ledPin,!digitalRead(ledPin));
      delay(500);
    }

  7. #7
    I've managed to get the complementary output working. The code is crude and not very portable, but it's a good starting point
    Code:
    /*
      This program tests the initialization of complementary output.  
      FlexTimer0 hardware is configured by directly writing to the registers
      CH2 and CH3 of FTM0 are used, corresponding to pins 9 and 10 of the Teensy3.0 
      PWM Frequency can be set using the #define.
      Dead-time is set for 1uS
    */
    
    const int ledPin =  13;
    const int PWM_H = 9;     //  FTM0 - CH2
    const int PWM_L = 10;    //  FTM0 - CH3
    
    #define TPM_C 48000000            // core clock, for calculation only
    #define PWM_FREQ 6000            //  PWM frequency [Hz]
    #define MODULO (TPM_C / PWM_FREQ) // calculation the modulo for FTM0
    
    int PWMvalue =0;
    bool countDir =1;
    
    void setup()   {                
      pinMode(ledPin, OUTPUT);
      init_FTM0();
    }
    
    void loop()                     
    {
      ////////////////////////////////////////////
      //Loop will sweep the dutycycle up and down
      ////////////////////////////////////////////
      if(PWMvalue<MODULO && countDir)PWMvalue+=100;
      else if(countDir)countDir =0;
      if(PWMvalue>200 && !countDir)PWMvalue-=100;
      else if(!countDir)countDir =1;
    
      FTM0_C3V = PWMvalue; 
      FTM0_SYNC |= 0x80;             // set PWM value update
      
      digitalWrite(ledPin,!digitalRead(ledPin));
      delay(50);
    }
    
    void init_FTM0(){
      
     FTM0_POL = 0;                  // Positive Polarity 
     FTM0_OUTMASK = 0xFF;           // Use mask to disable outputs
     FTM0_SC = 0x08;                // set system clock as source for FTM0
     FTM0_MOD = MODULO;             // Period register
     FTM0_CNTIN = 0;                // Counter initial value
     FTM0_COMBINE = 0x00003300;     // COMBINE=1, COMP=1, DTEN=1, SYNCEN=1
     FTM0_MODE = 0x01;              // Enable FTM0
     FTM0_SYNC = 0x02;              // PWM sync @ max loading point enable
     FTM0_DEADTIME = 0x80;          // DeadTimer prescale systemClk/4
     FTM0_DEADTIME |= 12;           // 1uS DeadTime, max of 63 counts of 48Mhz clock
     FTM0_C2V = 0;                  // Combine mode, pulse-width controlled by...
     FTM0_C3V = MODULO/2;           //   odd channel.
     FTM0_SYNC |= 0x80;             // set PWM value update
     FTM0_C2SC = 0x28;              // PWM output, edge aligned, positive signal
     FTM0_C3SC = 0x28;              // PWM output, edge aligned, positive signal
     
     CORE_PIN9_CONFIG = PORT_PCR_MUX(4) | PORT_PCR_DSE | PORT_PCR_SRE;    //config teensy output port pins
     CORE_PIN10_CONFIG = PORT_PCR_MUX(4) | PORT_PCR_DSE | PORT_PCR_SRE;   //config teensy output port pins
     
     FTM0_OUTMASK = 0x0;            // Turns on PWM output
     
     /*  To update the PWM duty cycle, 
         write MODULO value to the FTM0_CnV of the odd combined channels.
         then use "FTM0_SYNC |= 0x80" to set the software trigger.
     */
    }

  8. #8
    Excellent!

    I spent an hour or so looking at the manual & came away with no more than a headache!
    I conceded that I wasn't going to solve this in my lunch hour...
    I've had a play with your code (as well as I could with only one working scope probe!) & it seems fine!

    It's ironic that this takes two lines of code on an Arduino!

    Ian
    Last edited by ian; 03-25-2014 at 11:17 PM.

  9. #9
    Junior Member
    Join Date
    Oct 2019
    Posts
    3

    complimentary pwm on multiple outputs

    Quote Originally Posted by jlewis184 View Post
    I've managed to get the complementary output working. The code is crude and not very portable, but it's a good starting point
    Code:
    /*
      This program tests the initialization of complementary output.  
      FlexTimer0 hardware is configured by directly writing to the registers
      CH2 and CH3 of FTM0 are used, corresponding to pins 9 and 10 of the Teensy3.0 
      PWM Frequency can be set using the #define.
      Dead-time is set for 1uS
    */
    
    const int ledPin =  13;
    const int PWM_H = 9;     //  FTM0 - CH2
    const int PWM_L = 10;    //  FTM0 - CH3
    
    #define TPM_C 48000000            // core clock, for calculation only
    #define PWM_FREQ 6000            //  PWM frequency [Hz]
    #define MODULO (TPM_C / PWM_FREQ) // calculation the modulo for FTM0
    
    int PWMvalue =0;
    bool countDir =1;
    
    void setup()   {                
      pinMode(ledPin, OUTPUT);
      init_FTM0();
    }
    
    void loop()                     
    {
      ////////////////////////////////////////////
      //Loop will sweep the dutycycle up and down
      ////////////////////////////////////////////
      if(PWMvalue<MODULO && countDir)PWMvalue+=100;
      else if(countDir)countDir =0;
      if(PWMvalue>200 && !countDir)PWMvalue-=100;
      else if(!countDir)countDir =1;
    
      FTM0_C3V = PWMvalue; 
      FTM0_SYNC |= 0x80;             // set PWM value update
      
      digitalWrite(ledPin,!digitalRead(ledPin));
      delay(50);
    }
    
    void init_FTM0(){
      
     FTM0_POL = 0;                  // Positive Polarity 
     FTM0_OUTMASK = 0xFF;           // Use mask to disable outputs
     FTM0_SC = 0x08;                // set system clock as source for FTM0
     FTM0_MOD = MODULO;             // Period register
     FTM0_CNTIN = 0;                // Counter initial value
     FTM0_COMBINE = 0x00003300;     // COMBINE=1, COMP=1, DTEN=1, SYNCEN=1
     FTM0_MODE = 0x01;              // Enable FTM0
     FTM0_SYNC = 0x02;              // PWM sync @ max loading point enable
     FTM0_DEADTIME = 0x80;          // DeadTimer prescale systemClk/4
     FTM0_DEADTIME |= 12;           // 1uS DeadTime, max of 63 counts of 48Mhz clock
     FTM0_C2V = 0;                  // Combine mode, pulse-width controlled by...
     FTM0_C3V = MODULO/2;           //   odd channel.
     FTM0_SYNC |= 0x80;             // set PWM value update
     FTM0_C2SC = 0x28;              // PWM output, edge aligned, positive signal
     FTM0_C3SC = 0x28;              // PWM output, edge aligned, positive signal
     
     CORE_PIN9_CONFIG = PORT_PCR_MUX(4) | PORT_PCR_DSE | PORT_PCR_SRE;    //config teensy output port pins
     CORE_PIN10_CONFIG = PORT_PCR_MUX(4) | PORT_PCR_DSE | PORT_PCR_SRE;   //config teensy output port pins
     
     FTM0_OUTMASK = 0x0;            // Turns on PWM output
     
     /*  To update the PWM duty cycle, 
         write MODULO value to the FTM0_CnV of the odd combined channels.
         then use "FTM0_SYNC |= 0x80" to set the software trigger.
     */
    }
    I'm using this excellent example code to generate a complimentary PWM signal!

    Now I'm trying to expand its functionality to change which output pins are driven as needed. This will ultimately be part of a simple commutation scheme.

    I don't understand how to best achieve this. The example above sets the output pins at "setup." I'd need to command the sets of pins in a sequence and also be able to to just set any pin HIGH or LOW.

    Any help is greatly appreciated. Thanks.

  10. #10
    You will need to configure the Teensy at the register level. Reference FlexTimerModule section of the reference manual for more details. Once you configure the additional pins, you can use the OUTMASK register to enable/disable their output.

  11. #11
    Junior Member
    Join Date
    Oct 2019
    Posts
    3
    Thanks for the quick replay.

    I'm not familiar with these pin commands...is it as simple as this? I've just copied the other section of the example code. :/

    Code:
    CORE_PIN9_CONFIG = PORT_PCR_MUX(4) | PORT_PCR_DSE | PORT_PCR_SRE;    //config teensy output port pins
    CORE_PIN10_CONFIG = PORT_PCR_MUX(4) | PORT_PCR_DSE | PORT_PCR_SRE;   //config teensy output port pins
    
    CORE_PIN20_CONFIG = PORT_PCR_MUX(4) | PORT_PCR_DSE | PORT_PCR_SRE;    //config teensy output port pins
    CORE_PIN21_CONFIG = PORT_PCR_MUX(4) | PORT_PCR_DSE | PORT_PCR_SRE;   //config teensy output port pins
    
    CORE_PIN22_CONFIG = PORT_PCR_MUX(4) | PORT_PCR_DSE | PORT_PCR_SRE;    //config teensy output port pins
    CORE_PIN23_CONFIG = PORT_PCR_MUX(4) | PORT_PCR_DSE | PORT_PCR_SRE;   //config teensy output port pins
    And then setting the mask like this for keeping channel 9 and 10 active?

    Code:
    FTM0_OUTMASK = 0x11001111;
    Do these mask locations align with the PWM pins in ascending order as shown on the PJRC website? So, 5, 6, 9, 10, 20, 21, 22, 23?

    Can I use the traditional digitalWrite concepts in conjunction with this? For example I need to write the pins HIGH at some points....can I do that as I normally would?
    Last edited by ajlapp; 10-01-2019 at 07:22 PM. Reason: adding

  12. #12
    Junior Member
    Join Date
    Mar 2015
    Posts
    18
    The programming manual for the chip actually breaks this down pretty well. It has a bunch of cases such as this and tells you to set this bit in this register and that bit in this other one step by step. The kind of frustrating thing is that the registers are all over the place not all in the timer section IIRC. Anyway if you look for the "cookbook" section of the programming manual (not the chip datasheet) it is in there. At the very least you can see which registers are used and then read the detailed descriptions for each bit.

  13. #13
    Junior Member
    Join Date
    Oct 2019
    Posts
    3
    Iíll have to look for this cookbook section...I reviewed the register section of the manual and made some progress. Iím still unclear how the channels are combined. The result I achieved was different than expected so I just swapped the lines physically until things worked...Iím generating the complimentary signals but theyíre not on the channels I expected. :/

    I copied the example above...turned on the other PWM pins, enabled them and then wrote the simplest possible code that walks around the six steps at a fixed frequency.

    Code:
    /*
      This program tests the initialization of complementary output.  
      FlexTimer0 hardware is configured by directly writing to the registers
      CH2 and CH3 of FTM0 are used, corresponding to pins 9 and 10 of the Teensy3.0 
      PWM Frequency can be set using the #define.
      Dead-time is set for 1uS
    */
    
    const int ledPin =  13;
    const int buttonPin = 27;
    const int NOT_RESET_AND_ENABLE = 8;
    const int PHASE1_PWM_H = 9;                   //  FTM0 - CH2
    const int PHASE1_PWM_L = 10;                  //  FTM0 - CH3
    const int PHASE2_PWM_H = 20;                   //  FTM0 - CH2
    const int PHASE2_PWM_L = 21;                  //  FTM0 - CH3
    const int PHASE3_PWM_H = 22;                   //  FTM0 - CH2
    const int PHASE3_PWM_L = 23;
    
    static int commStep = 0;
    
    // Change these to adjust PWM
    #define PWM_FREQ        20000                 //  PWM frequency [Hz]
    #define PWM_AMPLITUDE   1500
    
    #define TPM_C           60000000              // core clock, for calculation only
    #define MODULO          (TPM_C / PWM_FREQ)    // calculation the modulo for FTM0
    
    #define DEBUG_LOOP_SPEED_MICROSECONDS     5000//5000
    
    int PWMvalue = 0;
    bool countDir = 1;
    int buttonPressed = 0;
    int bounceTimer = 0;
    unsigned long previousMicros = 0;
    unsigned long pulseTimer = 0;
    unsigned long lastPressTime = 0;
    
    void setup()   
    {                
      pinMode(ledPin, OUTPUT);  
      pinMode(buttonPin, INPUT_PULLUP);
      pinMode(NOT_RESET_AND_ENABLE, OUTPUT);
    /*
      pinMode(PHASE1_PWM_H, OUTPUT);
      pinMode(PHASE1_PWM_L, OUTPUT);
      pinMode(PHASE2_PWM_H, OUTPUT);
      pinMode(PHASE2_PWM_L, OUTPUT);
      pinMode(PHASE3_PWM_H, OUTPUT);
      pinMode(PHASE3_PWM_L, OUTPUT);*/
        
      Serial.begin(9600);
      digitalWriteFast(NOT_RESET_AND_ENABLE, LOW);
      init_FTM0();
    }
    
    void loop()                     
    {
      unsigned long lastDebugLoopTime = micros();
    
      while(true)
      {    
        unsigned long debugLoopDiff = micros() - lastDebugLoopTime;
    
        //FTM0_C3V = PWMvalue; 
        FTM0_SYNC |= 0x80;    
    
        if (debugLoopDiff >= DEBUG_LOOP_SPEED_MICROSECONDS)
        {
          //FTM0_SYNC |= 0x80; 
          debugLoop();
          lastDebugLoopTime = micros();
        }     
      }
    }
    
    void init_FTM0()
    {
      FTM0_POL = 0;                  // Positive Polarity 
      FTM0_OUTMASK = 0b11111111;     // Use mask to disable outputs
      FTM0_SC = 0x08;                // set system clock as source for FTM0
      FTM0_MOD = MODULO;             // Period register
      FTM0_CNTIN = 0;                // Counter initial value
      //FTM0_COMBINE = 0x00003300;     // COMBINE=1, COMP=1, DTEN=1, SYNCEN=1
      FTM0_COMBINE = 0b00110011001100110011001100110011; 
      //FTM0_COMBINE = 0b11001100110011001100110011001100; 
      FTM0_MODE = 0x01;              // Enable FTM0
      FTM0_SYNC = 0x02;              // PWM sync @ max loading point enable
      FTM0_DEADTIME = 0x80;          // DeadTimer prescale systemClk/4
      FTM0_DEADTIME |= 12;           // 1uS DeadTime, max of 63 counts of 48Mhz clock
    
      /*
      FTM0_C0V = 0;                  // Combine mode, pulse-width controlled by...
      FTM0_C1V = 0;  
      FTM0_C2V = 0;                  // Combine mode, pulse-width controlled by...
      FTM0_C3V = 0;          //   odd channel.
      FTM0_C4V = 0;
      FTM0_C5V = 0;
      FTM0_C6V = 0;
      FTM0_C7V = 0;*/
      
      FTM0_SYNC |= 0x80;             // set PWM value 
    
      FTM0_C0SC = 0x28;              // PWM output, edge aligned, positive signal
      FTM0_C1SC = 0x28;              // PWM output, edge aligned, positive signal
      
      FTM0_C2SC = 0x28;              // PWM output, edge aligned, positive signal
      FTM0_C3SC = 0x28;              // PWM output, edge aligned, positive signal
    
      FTM0_C4SC = 0x28;              // PWM output, edge aligned, positive signal
      FTM0_C5SC = 0x28;              // PWM output, edge aligned, positive signal
    
      FTM0_C6SC = 0x28;              // PWM output, edge aligned, positive signal
      FTM0_C7SC = 0x28;              // PWM output, edge aligned, positive signal
    
      CORE_PIN5_CONFIG = PORT_PCR_MUX(4) | PORT_PCR_DSE | PORT_PCR_SRE;    //config teensy output port pins
      CORE_PIN6_CONFIG = PORT_PCR_MUX(4) | PORT_PCR_DSE | PORT_PCR_SRE;   //config teensy output port pins
     
      CORE_PIN9_CONFIG = PORT_PCR_MUX(4) | PORT_PCR_DSE | PORT_PCR_SRE;    //config teensy output port pins
      CORE_PIN10_CONFIG = PORT_PCR_MUX(4) | PORT_PCR_DSE | PORT_PCR_SRE;   //config teensy output port pins
    
      CORE_PIN20_CONFIG = PORT_PCR_MUX(4) | PORT_PCR_DSE | PORT_PCR_SRE;    //config teensy output port pins
      CORE_PIN21_CONFIG = PORT_PCR_MUX(4) | PORT_PCR_DSE | PORT_PCR_SRE;   //config teensy output port pins
    
      //CORE_PIN22_CONFIG = PORT_PCR_MUX(4) | PORT_PCR_DSE | PORT_PCR_SRE;    //config teensy output port pins
      //CORE_PIN23_CONFIG = PORT_PCR_MUX(4) | PORT_PCR_DSE | PORT_PCR_SRE;   //config teensy output port pins  
    
      FTM0_OUTMASK = 0b00000000;  // Turn on PWM all channels
    }
    
    void debugLoop()
    {
      // Read the user button
      buttonPressed = !digitalRead(buttonPin);
    
      if(buttonPressed) 
      {
        digitalWriteFast(ledPin, HIGH);
        digitalWriteFast(NOT_RESET_AND_ENABLE, HIGH);
        //PWMvalue = PWM_AMPLITUDE;
        
        commStep++;
    
        if(commStep > 5) commStep = 0;    
    
        if(commStep == 0)
        {
          //PWMvalue = PWM_AMPLITUDE;
          
          //FTM0_OUTMASK = 0b11001111; //channel 2, 3 PWM...channel 
    
          //FTM0_C2V = PWM_AMPLITUDE;
          FTM0_C3V = PWM_AMPLITUDE;
          //FTM0_C4V = 0;
          FTM0_C5V = 0;
          //FTM0_C0V = 0;
          FTM0_C1V = 0;
          FTM0_C7V = 0;      
        }
        else if(commStep == 1)
        {
          //PWMvalue = 222;
          //FTM0_OUTMASK = 0b11000011;
    
          //FTM0_C2V = PWM_AMPLITUDE;
          FTM0_C3V = PWM_AMPLITUDE/2;
          //FTM0_C4V = 4095;
          FTM0_C5V = PWM_AMPLITUDE/2;
          //FTM0_C6V = 0;
          FTM0_C1V = 0;    
          FTM0_C7V = 0;      
        }
        else if(commStep == 2)
        {
          //FTM0_OUTMASK = 0b11110011;            // Turns on PWM output
    
          //FTM0_C2V = 0;
          FTM0_C3V = 0;
          //FTM0_C4V = 4095;
          FTM0_C5V = PWM_AMPLITUDE;
          //FTM0_C6V = 0;
          FTM0_C1V = 0;
          FTM0_C7V = 0;
        }
        else if(commStep == 3)
        {
          //FTM0_OUTMASK = 0b11110000;            // Turns on PWM output
    
          //FTM0_C2V = 0;
          FTM0_C3V = 0;
          //FTM0_C4V = 4095;
          FTM0_C5V = PWM_AMPLITUDE/2;
          //FTM0_C6V = 4095;
          FTM0_C1V = PWM_AMPLITUDE/2;
          FTM0_C7V = PWM_AMPLITUDE/2;
        }
        else if(commStep == 4)
        {
          //FTM0_OUTMASK = 0b11111100;            // Turns on PWM output
    
          //FTM0_C2V = 0;
          FTM0_C3V = 0;
          //FTM0_C4V = 0;
          FTM0_C5V = 0;
          //FTM0_C6V = 4095;
          FTM0_C1V = PWM_AMPLITUDE;
          FTM0_C7V = PWM_AMPLITUDE;
        }
        else if(commStep == 5)
        {
          //FTM0_OUTMASK = 0b11001100;            // Turns on PWM output
          
          //FTM0_C2V = 0;
          FTM0_C3V = PWM_AMPLITUDE/2;
          //FTM0_C4V = 0;
          FTM0_C5V = 0;
          //FTM0_C6V = 4095;
          FTM0_C1V = PWM_AMPLITUDE/2;
          FTM0_C7V = PWM_AMPLITUDE/2;
        }
      }
      else 
      {
        digitalWriteFast(ledPin, LOW);
        digitalWriteFast(NOT_RESET_AND_ENABLE, LOW);
        
        //PWMvalue = 0;
        //FTM0_C2V = MODULO/2;
        FTM0_C3V = 0;
        //FTM0_C4V = MODULO/2;
        FTM0_C5V = 0;
        //FTM0_C6V = MODULO/2;
        FTM0_C7V = 0;
        FTM0_C1V = 0;
        
      }
    
      
          
      Serial.print(commStep);
      Serial.print(",");
      Serial.print(FTM0_C2V);
      Serial.print(",");
      Serial.print(FTM0_C3V);
      Serial.print(",");
      Serial.print(FTM0_C4V);
      Serial.print(",");
      Serial.print(FTM0_C5V);
      Serial.print(",");
      Serial.print(FTM0_C0V);
      Serial.print(",");
      Serial.println(FTM0_C1V);
    }

  14. #14
    Junior Member
    Join Date
    Mar 2015
    Posts
    18
    Here is what I did to get complimentary output on 2 channels of FTM2. It doesn't use the full capability of the timer but it works and is simple.

    Code:
    /*
     * Test complimentary PWM on FTM2 CH0/CH1 with deadtime
     */
    #define RND_PWM_A_PIN       32
    #define RND_PWM_B_PIN       25
    #define BUTTON_3_PIN        24      
    #define STATUS_LED_PIN      33
    
    
    void setup() {
      uint32_t reg_val=0;
    
      pinMode(BUTTON_3_PIN, INPUT_PULLUP);
      pinMode(STATUS_LED_PIN, OUTPUT);
      
      pinMode(RND_PWM_A_PIN, OUTPUT);
      pinMode(RND_PWM_B_PIN, OUTPUT);
      analogWrite(RND_PWM_A_PIN, 0);
      analogWrite(RND_PWM_B_PIN, 0);
      analogWriteFrequency(RND_PWM_A_PIN, 260000);  // 130kHz *2 for pins 25, 32 FTM2 - center aligned is 1/2 the freq
      FTM2_MODE=0x04;      // Timer Write protect disable WPDIS=1 - reset value
      
      reg_val = FTM2_SC;
      reg_val = reg_val | 0b100000;  // set CPWMS bit for center aligned
      FTM2_SC = reg_val;
      
      reg_val = FTM2_C1SC;
      reg_val = reg_val |  0b00000100;  // set ELSN1A bit for low-true PWM (Inverted) on FTM2-CH1
      FTM2_C1SC = reg_val;
    
      //analogWrite(RND_PWM_A_PIN, 128);
      //analogWrite(RND_PWM_B_PIN, 118);  // make PWM shorter for B for deadtime
    
      
      Serial.begin(115200);
      delay(2000);
      Serial.println("Hello from FC");
    //  Serial.println(FTM2_SC, BIN);
    //  Serial.println(FTM2_C1SC, BIN);
    
    
    
    }
    
    
    void loop() {
    
      if (digitalReadFast(BUTTON_3_PIN) == LOW) {
        analogWrite(RND_PWM_A_PIN, 128);
        analogWrite(RND_PWM_B_PIN, 118);  // make PWM shorter for B for manual deadtime   
        digitalWriteFast(STATUS_LED_PIN, LOW); 
      }
      else {
        analogWrite(RND_PWM_A_PIN, 0);
        analogWrite(RND_PWM_B_PIN, 0);  // make PWM shorter for B for deadtime    
        digitalWriteFast(STATUS_LED_PIN, HIGH);
      }
    
    }
    Note, tested on Teensy3.2 CPU chip. Not verified on other CPU chips.

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •