Simultaneous PWM on Kinetics

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

Simultaneous PWM on Kinetics

3,378 Views
aniketmarkande
Contributor III

Hi, I am working on kinetics K22 series controllers. I am using PWM of 36khz, ToF set for 3,1 for IR protocol bit banging.

Is it possible to use different channels of same FTM instance simultaneously, since i want two PWM siganls to work simultaneously.

Single channel is working fine, but with two channels problems are coming.

If any way possible please let me know.

Thank you :smileyhappy:

Labels (1)
0 Kudos
20 Replies

1,389 Views
aniketmarkande
Contributor III

Hi,

Can anyone please provide me the code for PWM initialization.

Requirements:

1. FTM3, CH6 and CH7, non-complementary PWM of 36KHz

2. 32 pulses on both channel at the same time whenever PWM is enabled. PWM shall stop after 32 pulses.

Thank you in advance.

Thanks,

Aniket

0 Kudos

1,389 Views
mjbcswitzerland
Specialist V

Hi

You need to specify on which pins the two PWM outputs are required.
Are you still having the problem to generate the two outputs at the same time or is this now a different topic to stop after a number of cycles?

Note that there is another post discussing stepper motor type control which allows the output to be changed/stopped after pre-defined pulse counts at https://community.nxp.com/message/888189?commentID=888189?sr=search&searchId=95a908bc-bf01-4d19-b6b2... 

Regards

Mark

0 Kudos

1,389 Views
aniketmarkande
Contributor III

Hi Mark,

PWM is generated on PTC10 and PTC11.

Output is coming, the problem is with stopping PWM after 32 pulses.

/*********************************** My Init Function ******************************************/

e_PWM_Error_t BANSHI_PWMcomp_NonInverting_Init( c_FlexPwm** this, uint32_t ftmId, uint8_t channelId)
{
    e_PWM_Error_t retVal = kPWMErrorFailed;
    uint32_t uFTMhz;
    uint16_t uMod = 0;
    uint8_t ftmParamIndex = INVALID_FTM_PARAM_INDEX;

    do
    {
        if((NULL == this)|| (MAX_FTM_INSTANCES <= ftmId) ||
                        (MAX_FTM_CHANNELS <= channelId))
        {
            break;
        }

        ftmParamIndex = BANSHI_PWM_getFtmFreeParamIndex( channelId );
        if (INVALID_FTM_PARAM_INDEX == ftmParamIndex)
        {
            break;
        }
        *this = &l_FlexPwm[channelId];
        (*this)->m_ftmId = ftmId;
        (*this)->m_channelId = channelId;
        (*this)->m_ftmParam = NULL;
        FTM_HAL_SetWriteProtectionCmd(g_ftmBase[(*this)->m_ftmId], false);

        (*this)->m_ftmParam = &ftmParamArray[ftmParamIndex];
        (*this)->m_ftmParam->mode = kFtmCenterAlignedPWM;

        switch (ftmId)
        {
            case 3:
            FTM3_SC = 0x00;
            FTM3_CONF = 0xC0;
            FTM3_POL = 0x0;
            FTM3_OUTMASK=0xFF;
            FTM3_SC =0x0;
            FTM3_MODE |= 0x5;
            break;

            default:
            continue;
        }

        FTM_HAL_SetDualChnCompCmd(g_ftmBase[(*this)->m_ftmId],
                        FTM_HAL_GetChnPairIndex(channelId), false);
        FTM_HAL_SetDualChnPwmSyncCmd(g_ftmBase[(*this)->m_ftmId],
                        FTM_HAL_GetChnPairIndex(channelId), true);
        FTM_HAL_SetChnEdgeLevel (g_ftmBase[(*this)->m_ftmId],channelId,ELSA);
        FTM_HAL_SetChnEdgeLevel (g_ftmBase[(*this)->m_ftmId],(channelId+1),
                        ELSA);
        FTM_HAL_SetChnMSnBAMode (g_ftmBase[(*this)->m_ftmId],channelId, MSB);
        FTM_HAL_SetChnMSnBAMode (g_ftmBase[(*this)->m_ftmId],(channelId+1),
                        MSB);
        FTM_HAL_SetChnCountVal (g_ftmBase[(*this)->m_ftmId],channelId,
                        COUNTER_INIT_VALUE);
        FTM_HAL_SetChnCountVal (g_ftmBase[(*this)->m_ftmId],(channelId+1),
                        COUNTER_INIT_VALUE);
        FTM_HAL_SetFaultInputCmd(g_ftmBase[(*this)->m_ftmId],channelId/2,true);

        switch (ftmId)
        {
            case 3:
            //set the FAULT bits as 11, automatically clearing the faults
            FTM3_MODE |= 0x60;
            FTM3_SYNC = 0x2;// set sync point at mayimum CNTMAX=1
            FTM3_SC = 0x8;
            FTM3_EXTTRIG |= FTM_EXTTRIG_INITTRIGEN_MASK;
            break;

            default:
            continue;
        }

        FTM_DRV_SetClock((*this)->m_ftmId, kClock_source_FTM_SystemClk,
                        kFtmDividedBy1);
        uFTMhz = FTM_DRV_GetClock((*this)->m_ftmId);

        if (0 == (*this)->m_ftmParam->uFrequencyHZ)
        {
            break;
        }

        uMod = uFTMhz / ((*this)->m_ftmParam->uFrequencyHZ) - 1;
        FTM_HAL_SetMod(g_ftmBase[(*this)->m_ftmId], uMod);
        (*this)->m_PwmState = kFlexPwmStateDisabled;

        retVal = kPWMErrorOK;
    }while(false);

    return retVal;
}

/***********************************************************************************/

Please let me know if any changes in register level values.

Regards,

Aniket

0 Kudos

1,389 Views
mjbcswitzerland
Specialist V

Hi

I didn't see where you are stopping the operation after counting pulses.

If I were doing it from scratch I would connect the PWM output that needs to be stopped after a certain number of pulses to another PWM module's clock input. Then program that module to use it to count the pulses and either interrupt after the count reaches 32 (the interrupt would disable further PWM output operation) or to trigger a DMA transfer (more accurate due to no latency) to stop the PWM operation.

Regards

Mark

0 Kudos

1,389 Views
aniketmarkande
Contributor III

Hi Mark,

Yes i dont have code to stop PWM after 32 pulses and hence i need init code for same, where using TOF(timer overflow count) feature PWM can be stopped after 32 pulses on non-complementary mode operation of FTM PWM.

No provision in hardware to connect to another pins to count number of pulses. So please help me.

Also is it possible to have (TOIE)interrupt in non-complentary PWM mode?

Thank you.

Aniket

0 Kudos

1,389 Views
mjbcswitzerland
Specialist V

Hi

Further possibilities that you have are:

- generate an interrupt on each PWM pulse and count 32 interrupts and stop the timer (this is the TOIE, which is possible at the same time as generating PWM output)
- start a second timer at the same time with an interrupt after a time that is equal to the 32 pulses that you will be generating (more efficient because only one interrupt).
- use the TOIE to trigger a DMA transfer and set up the DMA channel to generate an interrupt after 32 transfers.

Regards

Mark

0 Kudos

1,389 Views
aniketmarkande
Contributor III

Hi Mark,

I am trying for the first option you have suggested, i am getting interrupt before enabling the PWM continuosly.

But i want same interrupt in non-complementary PWM mode after enabling the PWM. Can you please tell register settings required in non complementary mode? (my init function is posted above).

If you provide code for register settings, it will be a great help.

Thank you,

Aniket

0 Kudos

1,389 Views
mjbcswitzerland
Specialist V

Hi

I have just build a project that runs on the FRDM-K22F and generates a 1kHz 20% PWM signal on PTA4 (FTM0_CH1) on J1-10. At the same time it generates a timer overflow interrupt which toggles the red LED (PTA1) on J2-4.

pastedImage_1.png

It is attached as binary and the registers can be viewed by using the memory display command on the UART command line interface.

The code I use is

     PWM_INTERRUPT_SETUP pwm_setup;
    pwm_setup.int_type = PWM_INTERRUPT;
    pwm_setup.pwm_mode = (PWM_SYS_CLK | PWM_PRESCALER_16 | PWM_EDGE_ALIGNED); // clock PWM timer from the system clock with /16 pre-scaler
    pwm_setup.int_handler = PWM_IRQ;
    pwm_setup.pwm_reference = (_TIMER_0 | 1);                            // timer module 0, channel 1
    pwm_setup.pwm_frequency = PWM_FREQUENCY(1000, 16);                   // generate 1000Hz on PWM output
    pwm_setup.pwm_value   = _PWM_PERCENT(20, pwm_setup.pwm_frequency);   // 20% PWM (high/low)
    fnConfigureInterrupt((void *)&pwm_setup);                            // enter configuration for PWM test

and the interrupt handler is

static void PWM_IRQ(void)
{
    _TOGGLE_PORT(A, PORTA_BIT1);
}

This is non-complimentary PWM mode (although I don't think this makes any difference).
To get the interrupt from the basic PWM operation it is only necessary to enter and enable the interrupt handler (in vector table and NVIC) and enable the interrupt with FTM_SC_TOIE in the FTMx_SC register.
To clear the interrupt each time it fires one does
FTMx_SC &= ~(FTM_SC_TOF);                                            // clear interrupt (read when set and write 0 to reset)

if your driver interface doesn't do it for you (the uTasker PWM driver interface does all work that otherwise requires detailed hardware knowledge).

Regards

Mark

0 Kudos

1,389 Views
aniketmarkande
Contributor III

which line of code put the PWM into non-complementary mode?

and i am using fsl functions :S, by chance can you provide the code using fsl layer?

regards,

Aniket

0 Kudos

1,386 Views
mjbcswitzerland
Specialist V

Hi

Non-complimentary mode is the default so doesn't need anything special.


If you load the binary you can also read all register configurations in the memory display interface (menu 3 - I/O) on VCOM interface at 115'200 Baud. Eg. "md 1000 l 4" to display 4 long words at address 0x1000 (just look at the timer registers to see all setup).
You can also get reference code from the uTasker project and use it as base for corrections or improvements to the one that you use.

I can't help with the fsl layer since I never used it - you will need to contact NXP and see whether you can arrange a support contract if you can't find help or a solution from fls users on the forum.

Regards

Mark

0 Kudos

1,389 Views
xiangjun_rong
NXP TechSupport
NXP TechSupport

Hi,

As Mark said that the FTM module can generate different PWM mark-space ratios, polarity with the same frequency for all FTM channels in the same FTM module. Of course, two FTM channels can generate the same waveform PWM signals synchroniously.

BR

Xiangjun Rong

0 Kudos

1,389 Views
aniketmarkande
Contributor III

Hi,

Thank you for your quick resonses. What mode i need to select for using two channels siultaneosly to generate PWM of same FTM instance? 

As of now i am enabling two PWM channels sequentially, and it is giving problem. (using SDK libraries).

Also since i need exact 32 pulses, i am using TOF overflow counter, which gives interrupt after specified TOF count. 

since two channels are of same FTM instance they have common initilaization. Will that have any issues?

if possible can u provide any code snippet?

Thank you :smileyhappy:

0 Kudos

1,389 Views
xiangjun_rong
NXP TechSupport
NXP TechSupport

Hi,

As you know all FTM channels in the same FTM instance are synchronized because of only one FTM_Mod register, can you draw a figure which shows the timing relationship between two FTM channels? or what is the issue you are facing now?

BR

Xiangjun Rong

0 Kudos

1,390 Views
aniketmarkande
Contributor III

pastedImage_1.png

The required output.

I am not able to get output on both channels simulataneosuly.

0 Kudos

1,390 Views
mjbcswitzerland
Specialist V

Hi

Maybe you are not configuring the output on the second pin?
The OpenSource project
http://www.utasker.com/forum/index.php?topic=1721.msg7086#msg7086
contains this solution http://www.utasker.com/docs/uTasker/uTaskerHWTimers.PDF which allows multiple PWM outputs to operate in case of issues with the present libraries.

Regards

Mark

0 Kudos

1,390 Views
aniketmarkande
Contributor III

When i am running only one channel(FTM3_CH7) it is working properly. Same settings i did for second channel(FTM3_CH6), then also its not working.

0 Kudos

1,390 Views
mjbcswitzerland
Specialist V

Don't forget that the PWM outputs can be mapped to multiple pins; is the output really connected to the pin that you are measuring?

Show your FlexTimer register configuration and the port configuration of the pins involved (eg. with a screen shot of the registers in the debugger).

Regards

Mark

0 Kudos

1,390 Views
egoodii
Senior Contributor III

Or, with interrupt firmware, each channel of one FTM can generate precisely-timed independent output sequences of any form, down to a certain minimum edge-to-edge timing.  The initial question mentioned IR-protocol bit-banging, and timer-banging is THE way to achieve such complex waveform generation.

0 Kudos

1,390 Views
egoodii
Senior Contributor III

For 'direct intervention in multiple FTM output events' (timer-banged sequence generation on multiple simultaneous channels) see also my info in:

https://community.nxp.com/message/874686?commentID=874686#comment-874686

What kind of 'problems' do you refer to?

0 Kudos

1,390 Views
mjbcswitzerland
Specialist V

Hi

Each FlexTimer has a base frequency that is shared between all of its channels, but each channel can generate different PWM mark-space ratios, polarity or alignment.
See http://www.utasker.com/docs/uTasker/uTaskerHWTimers.PDF (especially the appendix with extra Kinetis FlexTimer notes).

Regards

Mark

Kinetis help for professionals: http://www.utasker.com/services.html

0 Kudos