This thread has been locked.

If you have a related question, please click the "Ask a related question" button in the top right corner. The newly created question will be automatically linked to this question.

Wrong PWM Duty cycle generation

Other Parts Discussed in Thread: HALCOGEN

Hi,

I am using TMS570 to generate PWM . I am trying to change Duty cycle run time.

As  i change the Duty Cycle  to 10%, the duty cycle changes to 10% but after some time i get a single instance of 5% Duty cycle and then it automatically recovers to 10% Duty cycle.

I am also monitoring the "Program Overflow Flag" but it is not set.

Can you please help me in debugging this issue,

Request your help as soon as possible.

Thank you.

  • Hi Abhijeet,

    We'll need some clarifications.
    Are you using HaLCoGen or do you have N2HET code for this? 
    What N2HET instructions are you using to generate the PWM?
    How are you changing the duty cycle to 10%? It is adviced to use a MOV32 or MOV64 instruction to change the PWCNT or ECMP instruction and not to directly change them. You can take a look at the HALCoGen N2HET code and driver for ideas on this. This appnote may help.

    Thanks and Regards,
    Vineeth

  • Hi Vineeth ,

    I have generated a code using Halcogen .

    i am using the following instruction to generate and update the Duty cycle.


    /* CNT: Timebase
    * - Instruction = 0
    * - Next instruction = 1
    * - Conditional next instruction = na
    * - Interrupt = na
    * - Pin = na
    * - Reg = T
    */
    {
    /* Program */
    (ULONG)0x00002C80u,
    /* Control */
    (ULONG)0x01FFFFFFu,
    /* Data */
    (ULONG)0xFFFFFF80u,
    /* Reserved */
    (ULONG)0x00000000u
    }
    /* PWCNT: PWM 0 -> Duty Cycle
    * - Instruction = 1
    * - Next instruction = 2
    * - Conditional next instruction = 2
    * - Interrupt = 1
    * - Pin = 12
    */
    {
    /* Program : | NEXT-ADD | HrLr */
    ((ULONG)0x000014C0u | (2u << ZBSFT_13) | (1u << ZBSFT_08)),
    /* Control : | CON-NEXT-ADD | PIN-SELECT | PIN-ACTION */
    ((ULONG)0x00000006u
    | (2u << ZBSFT_13)
    | (12u << ZBSFT_08)
    | (3u << ZBSFT_03)),
    /* Data */
    (ULONG)0x00000000u,
    /* Reserved */
    (ULONG)0x00000000u
    },
    /* DJZ: PWM 0 -> Period
    * - Instruction = 2
    * - Next instruction = 3
    * - Conditional next instruction = 41
    * - Interrupt = 2
    * - Pin = na
    */
    {
    /* Program : | NEXT-ADD */
    ((ULONG)0x00001480u | (5u << ZBSFT_13)),
    /* Control : | CON-NEXT-ADD */
    ((ULONG)0x0000006u | (3u << ZBSFT_13)),
    /* Data */
    (ULONG)0x00000000u,
    /* Reserved */
    (ULONG)0x00000000u
    },

    /* MOV64: PWM 0 -> Duty Cycle Update
    * - Instruction = 41-3
    * - Next instruction = 42-4
    * - Conditional next instruction = 2
    * - Interrupt = 1
    * - Pin = 12
    */
    {
    /* Program : | NEXT-ADD | REMOTE-ADD */
    ((ULONG)0x00000200u | (4u << ZBSFT_13) | (1u << ZBSFT_00)),
    /* Control : | ENABLE-PIN | CON-NEXT-ADD | PIN-SELECT | PIN-ACTION */
    ((ULONG)0x00000007u
    | (1u << ZBSFT_22)
    | (2u << ZBSFT_13)
    | (12u << ZBSFT_08)
    | (3u << ZBSFT_03)),
    /* Data */
    160128u,
    /* Reserved */
    (ULONG)0x00000000u
    },
    /* MOV64: PWM 0 -> Period Update
    * - Instruction = 42-4
    * - Next instruction = 3-5
    * - Conditional next instruction = 41-3
    * - Interrupt = 2
    * - Pin = na
    */
    {
    /* Program : | Next Add | Reserved | Remote Add */
    ((ULONG)0x00000000u
    | (5u << ZBSFT_13)
    | (1u << ZBSFT_09)
    | (2u << ZBSFT_00) ),
    /* Control : | CON-NEXT-ADD */
    ((ULONG)0x00000007u | (3u << ZBSFT_13) ),
    /* Data */
    319872u,
    /* Reserved */
    (ULONG)0x00000000u
    }
    /* PCNT: Capture Duty 0 (count high pulse i.e.rise-to-fall pulse)
    * - Instruction = 5
    * - Next instruction = 6
    * - Conditional next instruction = na
    * - Interrupt = na
    * - Pin = 14
    */
    {
    /* Program :
    | Next Add
    | RESERVED
    | INT-ENABLE
    | TYPE-SELECT
    | Hr_Lr
    | PIN-SELECT */
    ((ULONG)0x00000000u
    | (6u << ZBSFT_13)
    | (7u << ZBSFT_09)
    | (0u << ZBSFT_08)
    | (1u << ZBSFT_06)
    | (0u << ZBSFT_05)
    | (14u << ZBSFT_00)),
    /* Control : | CONTROL */
    ((ULONG)0x00000000u | (1u << ZBSFT_26)),
    /* Data */
    (ULONG)0x00000000u,
    /* Reserved */
    (ULONG)0x00000000u
    },

    /* PCNT: Capture Period 0 (consecutive falling edges)
    * - Instruction = 6
    * - Next instruction = 0
    * - Conditional next instruction = na
    * - Interrupt = na
    * - Pin = 14 +1
    */
    {
    /* Program : Next Add
    | RESERVED
    | INT-ENABLE
    | TYPE-SELECT
    | Hr_Lr
    | PIN-SELECT */
    ((ULONG)0x00000000u
    | (0u << ZBSFT_13)
    | (7u << ZBSFT_09)
    | (0u << ZBSFT_08)
    | (2u << ZBSFT_06)
    | (1u << ZBSFT_05)
    | (15u << ZBSFT_00)),
    /* Control : | CONTROL */
    ((ULONG)0x00000000u | (1u << ZBSFT_26)),
    /* Data */
    (ULONG)0x00000000u,
    /* Reserved */
    (ULONG)0x00000000u
    }

    Following are the other details about the configuration .
    VCLK2 = 40Mhz
    HR Prescale -> 1 (Divide-by-2)
    LR Prescale -> 3 (Divide-by-8)
    Thus as per my calculation Loop resolution period is 400ns

    Questions :

    1) Is there a possibility that the instruction are taking more then 400ns to execute in a specific condition and the execution is jumping to the 1st instruction therefore causing the wrong Duty Cycle to generate ( Sometime 5% ... sometimes 3% but expected is 10%).

    2) If it is a Program Overflow and "Program Overflow Flag" is set , How long does the flag sustain its value .... i mean does this flag get cleared if the Next PWM duty cycle is generated properly ( Which is happening in my case ).

    3) What are the other possible reasons of generating a wrong PWM Duty cycle.
  • Hi Abhijeet,

    1,2) Program overflow flag will be reset only on a Register read. So we can probably rule out an overflow.

    Can you try using the pwmSetDuty() function provided in HALCoGen to update the period?
    But this will require CPU intervention. Are you trying to keep the N2HET independent of the CPU?

    Thanks and Regards,
    Vineeth

  • Hi Vineeth ,

    Sorry i forgot to mention you that i am using pwmSetDuty() generated by the halcogen .

    following is the code :
    VOID DRV_Set_PWM_Duty(TAG_HET_RAMBASE * het, ULONG pwm, USHORT pwmDuty,
    ULONG pwmPeriod)
    {
    ULONG ulACTION ;
    ULONG ulPWMPOLARITY = (ULONG)Z_ZERO;

    pwmPeriod = (ULONG)(((pwmPeriod * (ULONG)1000.0)
    / (ULONG) 400u) << ZBSFT_07);
    het->Instruction[(pwm << ZBSFT_01) + ZINSTRUCTION_IDX4].Data =
    pwmPeriod - T128;

    /* ULONG pwmPeriod = SHETRAM1->Instruction[(pwm << 1U) + 4].Data + 128U;*/
    if(SHETRAM1 == het)
    {
    ulPWMPOLARITY = tulSHET1PWMPOLARITY[pwm];
    }
    else
    {
    }
    if (pwmDuty == 0u)
    {
    if (ulPWMPOLARITY == ZPWM_POLARITY_3)
    {
    ulACTION = 0u;
    }
    else
    {
    ulACTION = ZPWM_ACTION_2;
    }
    }
    else if (pwmDuty >= ZPWM_DUTY_1000)
    {
    if (ulPWMPOLARITY == ZPWM_POLARITY_3)
    {
    ulACTION = ZPWM_ACTION_2;
    }
    else
    {
    ulACTION = 0u;
    }
    }
    else
    {
    ulACTION = ulPWMPOLARITY;
    }

    het->Instruction[(pwm << ZBSFT_01) + ZINSTRUCTION_IDX3].Control =((het->Instruction[(pwm << ZBSFT_01) + T3].Control)
    & (~(ZHET_DATA_ADD)))| (ulACTION << ZBSFT_03);
    het->Instruction[(pwm << ZBSFT_01) + ZINSTRUCTION_IDX3].Data = (ULONG)(((pwmPeriod * pwmDuty)/ (ULONG)T100)
    / (ULONG)T10) + (ULONG)T128;
    }