measurement during PWM off time

cancel
Showing results for 
Show  only  | Search instead for 
Did you mean: 

measurement during PWM off time

998 Views
vinkar
Contributor III

Hello,

I am using the KL04 chip.

Some of the pins are being used in the PWM mode.

But, I need to make measurements during the PWM off time.

How can I monitor or do that.

How can I make sure that the measurements are being made during the

off time and not the on time.

One way is to monitor the TPM0_CNt. But this will keep adding latencies.

Page 511 of the datasheet says this -

30.4.6 Edge-Aligned PWM (EPWM) Mode

The edge-aligned mode is selected when (CPWMS = 0), and (MSnB:MSnA = 1:0). The

EPWM period is determined by (MOD + 0x0001) and the pulse width (duty cycle) is

determined by CnV.

The CHnF bit is set and the channel (n) interrupt is generated (if CHnIE = 1) at the

channel (n) match (TPM counter = CnV), that is, at the end of the pulse width.

This type of PWM signal is called edge-aligned because the leading edges of all PWM

signals are aligned with the beginning of the period, which is the same for all channels

within an TPM.



But this is not working fine. The reason being -

I have configured the interrupt to be at 50uSecs. Also , CHnIE = 1.

So as per this text it should go to the ISR twice - once for the end of the

PWM on time(i.e - end of the pulse width) and then at the end of the period.

So, if its 50% duty cycle it will go to the ISR at 25uSecs and the at 50uSecs.


But, it is entering it only once. Hence, we can say that the interrupt is done only at the end of the period.

So, how to find if the pwm on time is over.



Vinod.

Labels (1)
0 Kudos
5 Replies

624 Views
chris_brown
NXP Employee
NXP Employee

Hi Vinod,

I have some concerns regarding your setup and I would like to get some more information from you. 

Firstly, you mention that you are trying to get an edge-aligned PWM.  However, I see in your initialization code that you have set the CPWMS bit (with the instruction TPM0_SC |= TPM_SC_CPWMS_MASK;).  This configures your PWMs for center alignment. 

Secondly, I see in your setPWMDutyCycle function that you are disabling the clock to the TPM to update the channel value.  I would recommend not doing that.  It is not necessary.  The channel value can be updated with the clock to the TPM still running.  This may have something to do with some erratic operation that you are seeing. 

Third, I want to make sure that we can get a PWM going, so can you try to setup your PWM with MOD / 2 as the channel value?  This should produce a 50% PWM on your scope.  Are you trying to get low-true pulses or high-true pulses?  I see in your initialization you have both configurations and one will override the other. 

Thanks,

Chris

0 Kudos

624 Views
jeremyzhou
NXP Employee
NXP Employee

Hello Vinod,

I'm a little bit confused with your issue, so I was wondering if you could states your issue simply and upload your whole demo.

I'm looking forward to your reply.
Have a great day,
Ping

-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------

0 Kudos

624 Views
Jorge_Gonzalez
NXP Employee
NXP Employee

Hello Vinod:

I think you misunderstood the reference manual:


The CHnF bit is set and the channel (n) interrupt is generated (if CHnIE = 1) at the

channel (n) match (TPM counter = CnV), that is, at the end of the pulse width.

This means that only one interrupt should be generated, but not at the end of the period, but at the end of the Pulse Width (channel match with CnV). So if you have a 50 us period with 50% duty cycle, then interrupt should trigger at 25 us, then 75 us, 125 us and so on.


Regards!,
Jorge Gonzalez

-----------------------------------------------------------------------------------------------------------------------
Note: If this post answers your question, please click the Correct Answer button. Thank you!
-----------------------------------------------------------------------------------------------------------------------

0 Kudos

624 Views
vinkar
Contributor III

Hello Jorge,

I did a small expt. The code is as stated below -

static void setPWMDutyCycle(uint16_t dutyCycle,uint8_t channel)

                {

                        float roughVal;

                        uint8_t xRough = 0; // comment later //

                        uint8_t result0A = 0; // comment later //

                        TPM0_SC &= ~(TPM_SC_CMOD_MASK);                  

                        // timer off //

                        TPM0_CNT = 0;                                // counter value. NOTE :- when debug is aactive

                        TPM0_CONF |= 192;                        // counter runs in debug mode as well //

                        switch(channel){

                        // '-' or low drivers are pulled high without PWMs as they don't make a difference //

                        case 0:

                                TPM0_C0V = dutyCycle;                  

                                // U1+ turned ON // uncomment

                                TPM0_C2V = 0;                    // V1+ turned OFF // uncomment

                                TPM0_C4V = 0;                    // W1+

                                 //turned OFF // uncomment

                        break;

                        case 2:

                                TPM0_C2V = dutyCycle;                  

                                // V1+ turned ON // uncomment

                                TPM0_C0V = 0;                    // U1+ turned OFF // uncomment

                                TPM0_C4V = 0;                    // W1+ turned OFF // uncomment

                        break;

                        case 4:

                                TPM0_C4V = dutyCycle;             // W1+ turned ON // uncomment

                                TPM0_C2V = 0;                    // V1+ turned OFF // uncomment

                                TPM0_C0V = 0;                    // U1+ turned OFF // uncomment

                        break;

                        }

                        TPM0_SC |= TPM_SC_CMOD(1); // timer started //                       

                }

In either of the 3 cases (0,2 and 4) one of the channels is given PWM. The other 2 are fed '0' to not give out any PWM from them. For e.g - in case 4 -> PWM is given out via C4V, while C2V and C0V are disabled as PWMs. Now, when the TPM0_CxSC  registered is manipulated as -

TPM0_C0SC |= (TPM_CnSC_MSB_MASK | TPM_CnSC_ELSB_MASK); // PWM - edge ,...etc for centre alligned mode //

TPM0_C2SC |= (TPM_CnSC_MSB_MASK | TPM_CnSC_ELSB_MASK); // PWM - edge ,...etc for centre alligned mode //

TPM0_C4SC |= (TPM_CnSC_MSB_MASK | TPM_CnSC_ELSB_MASK);

it works fine.

But when I make it as -

TPM0_C0SC |= 0x24;

TPM0_C2SC |= 0x24;

TPM0_C4SC |= 0x24;  

It fails. I get PWM on one channel, while the others also give out PWMs with very large dutycycles. Why this behaviour.

Vinod.

0 Kudos

624 Views
vinkar
Contributor III

Hello Jorge,

I get your point.

In the conventional PWM, with a 50% duty cycle. There is a high for 25uSecs,interrupt, PWM low for 25uSecs,PWM high for 25uSecs,interrupt and so on and so forth.

So, measuring the relevant data during the low part of the PWM should not be a problem as the pwm low starts after the interrupt.

This is true if I select the following -

1) Edge-aligned PWM.

2)  High-true pulses (clear Output on match, set Output on reload).

Hope this is clear.

I added this code -

TPM0_C0SC |= (TPM_CnSC_MSB_MASK | TPM_CnSC_ELSA_MASK); // PWM - edge ,...etc for centre alligned mode //

TPM0_C2SC |= (TPM_CnSC_MSB_MASK | TPM_CnSC_ELSA_MASK); // PWM - edge ,...etc for centre alligned mode //

TPM0_C4SC |= (TPM_CnSC_MSB_MASK | TPM_CnSC_ELSA_MASK);

SO it should give me the needed thingy. But the pin is always high.

But this code -

TPM0_C0SC |= (TPM_CnSC_MSB_MASK | TPM_CnSC_ELSB_MASK); // PWM - edge ,...etc for centre alligned mode //

TPM0_C2SC |= (TPM_CnSC_MSB_MASK | TPM_CnSC_ELSB_MASK); // PWM - edge ,...etc for centre alligned mode //

TPM0_C4SC |= (TPM_CnSC_MSB_MASK | TPM_CnSC_ELSB_MASK);

works with PWM

The ISR is -

void FTM0_IRQHandler(void){

            uint8_t rough = 0;

            // added for wait of ADC //

          //  GPIOB_PSOR |= 0x00000018;

            counterAdc++;

            TPM0_SC &= ~TPM_SC_CMOD_MASK;

        

            if((TPM0_SC & TPM_SC_TOF_MASK) == TPM_SC_TOF_MASK){

                    TPM0_SC |= TPM_SC_TOF_MASK;

            }

        

            adcFlag = 1;

            TPM0_SC |= 8;

        

            //adcChannel = "W";

         //  pitStart(2); //issue - probably 5 is not 5 us.

          //  commutationFlag = 1;

            //pitStart(2);

    }

tek0051.bmp

Consider the above image.
The blue is the PWM. At each interrupt of the TPM0 I am making a pin high and low(the yellow pin).

TPM0_C0SC |= 0x28;

TPM0_C2SC |= 0x28;

TPM0_C4SC |= 0x28;

The code is for " Edge-aligned PWM High-true pulses (clear Output on match, set Output on reload)"

This is as per the datasheet and correct to my understanding. But the yellow toggle is done done properly. It

should rather be done at the end of the PWM on (so its a delay of 25uSecs). How is this so.


But, in case I change the code to

TPM0_C0SC |= 0x24;

TPM0_C2SC |= 0x24;

TPM0_C4SC |= 0x24;

I get the following image. The PWM never has a low period. Though it does do the interrupt action . Pls see the image below.

tek0052.bmp

The blue is always high. The yellow (diagnostic) is manipulated in the ISR as expected. Strange behavior :smileyhappy:

The pwm initialisation code is as stated-

static void pwmInit(void)

                {

                        // PWM //

                        //timer0 - PWM //

                        SIM_SOPT2 |= SIM_SOPT2_TPMSRC(1);   // clk source for TPM0 and TPM1 as well

                        SIM_SCGC6 |= SIM_SCGC6_TPM0_MASK;   // clk gated for TPM0

                        SIM_SCGC5 |= SIM_SCGC5_PORTA_MASK;  // clk gated for PORTA

                        SIM_SCGC5 |= SIM_SCGC5_PORTB_MASK;  // clk gated for PORTB

                        TPM0_SC |= 3;                   // 8 prescale factor

                        SIM_SCGC5  |= 0x00000400;      // gating of clock for PORTA/B //

                        // port settings //

                        PORTB_PCR7         &= PORT_PCR_MUX_MASK;    // U1+

                        PORTA_PCR6         &= PORT_PCR_MUX_MASK;    // V1+

                        PORTB_PCR11        &= PORT_PCR_MUX_MASK;    // W1+

                        PORTB_PCR7         |= PORT_PCR_MUX(2);   // U1+

                        PORTA_PCR6         |= PORT_PCR_MUX(2);   // V1+

                        PORTB_PCR11        |= PORT_PCR_MUX(2);   // W1+

                        // added 040412014 //

                        TPM0_SC &= ~(TPM_SC_CMOD_MASK);              // timer off //

                        TPM0_CNT = 0;                                // counter value. NOTE :- when debug is aactive

                        TPM0_CNT = 0;                                // counter value. NOTE :- when debug is aactive

                        TPM0_CONF |= 192;                            // counter runs in debug mode as well //

                        TPM0_MOD = 131;

                        TPM0_SC |= TPM_SC_TOIE_MASK;                 // INTERRUPT ENABLED //

                        // -- add ends -- //

                        //timer0//

                        TPM0_CNT = 0;          // counter value. NOTE :- when debug is aactive

                        TPM0_CONF |= 192;      // counter runs in debug mode as well //

                        //Pins of PWM //

                        //--- alternate selection (all PWM are ALT2)---//

//                         TPM0_SC   |= TPM_SC_CPWMS_MASK;        // edge/centre alligned mode //

//                      TPM0_C0SC |= (TPM_CnSC_MSB_MASK | TPM_CnSC_ELSB_MASK); // PWM - edge ,...etc for centre alligned mode //

//                      TPM0_C2SC |= (TPM_CnSC_MSB_MASK | TPM_CnSC_ELSB_MASK); // PWM - edge ,...etc for centre alligned mode //

//                      TPM0_C4SC |= (TPM_CnSC_MSB_MASK | TPM_CnSC_ELSB_MASK);

                        TPM0_C0SC |= 0x24;

                        TPM0_C2SC |= 0x24;

                        TPM0_C4SC |= 0x24;       

//                         TPM0_C0SC |= (TPM_CnSC_MSB_MASK | TPM_CnSC_ELSA_MASK); // PWM - edge ,...etc for centre alligned mode //

//                         TPM0_C2SC |= (TPM_CnSC_MSB_MASK | TPM_CnSC_ELSA_MASK); // PWM - edge ,...etc for centre alligned mode //

//                         TPM0_C4SC |= (TPM_CnSC_MSB_MASK | TPM_CnSC_ELSA_MASK);

                        // TPM0_SC -- turn on timer //

                }

Vinod.

0 Kudos