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.

RM48L952ZWT HalCoGen 4.03.00 het.c pwm functions and math precision for float calculations

Other Parts Discussed in Thread: HALCOGEN

Hello. We are using your TI Hercules RM48L942ZWT processor with HalCoGen 4.03.00.  for the autogenerated het.c functions -- we had needed the pwmSetSignal and pwmGetSignal - we needed the duty cycle to allow for float (the default autogenerated from HalCoGen had the dutyCycle as uint and period as float). We changed the dutyCycle in both functions to be float32.  When we call the setSignal routine and pass it i.e., 62.0% duty cycle and period of 10000.00 for example. When we call the pwmGetSignal function immediately after calling the pwmSetSignal routine, dutyCycle is returned as =61.999... and period = 9999.36....

Why are the values not the same? Isn't the math the same, even when we change the uint type to float type?  Thank you.

  • Hi Tammy,

    The way you do the Type casting in below lines of setSignal routine might have some effect. Could you do the way it's done like below line. Perform all Float operations first before doing Typecasting.

    hetRAM->Instruction[(pwm << 1U) + 41U].Data = ((((uint32)(pwmPeriod * signal.duty)) / 100U) << 7U ) + 128U;

  • Hi Prathap, what do you mean? Below is the code with float instead of uint - can you explain using practical example from below on the functions?

    /** @typedef hetSIGNALFLOAT_t

    * @brief HET Signal Type Definition

    *

    * This type is used to access HET Signal Information.

    */

    typedef volatile struct hetSignalFloat

    {

       float32 duty; /**< Duty cycle in % of the period */

       float64 period; /**< Period in us */

    } hetSIGNALFLOAT_t;

     

    /** @fn void pwmSetSignalFloat(hetRAMBASE_t * hetRAM, uint32 pwm, hetSIGNALFLOAT_t signal)

    * @brief Set period

    * @param[in] hetRAM Pointer to HET RAM:

    * - hetRAM1: HET1 RAM pointer

    * - hetRAM2: HET2 RAM pointer

    * @param[in] pwm Pwm signal:

    * - pwm0: Pwm 0

    * - pwm1: Pwm 1

    * - pwm2: Pwm 2

    * - pwm3: Pwm 3

    * - pwm4: Pwm 4

    * - pwm5: Pwm 5

    * - pwm6: Pwm 6

    * - pwm7: Pwm 7

    * @param[in] signal signal

    - duty cycle in %.

    * - period period in us.

    *

    * Sets a new pwm signal

    */

    void pwmSetSignalFloat(hetRAMBASE_t * hetRAM, uint32 pwm, float32 dutyCycle, float64 period)

    {

       uint32 action;

       uint32 pwmPolarity = 0U;

       float64 pwmPeriod = 0.0F;

       if(hetRAM == hetRAM1)

      {

        pwmPeriod = (period * 1000.0F) / 1280.000F;

        pwmPolarity = s_het1pwmPolarity[pwm];

      }

       else

      {

        pwmPeriod = (period * 1000.0F) / 1280.000F;

        pwmPolarity = s_het2pwmPolarity[pwm];

      }

       if (dutyCycle == 0U)

      {

        action = (pwmPolarity == 3U) ? 0U : 2U;

      }

       else if (dutyCycle >= 100U)

      {

        action = (pwmPolarity == 3U) ? 2U : 0U;

      }

       else

      {

        action = pwmPolarity;

      }

         hetRAM->Instruction[(pwm << 1U) + 41U].Control = ((hetRAM->Instruction[(pwm << 1U) + 41U].Control) & (~(uint32)(0x00000018U))) | (action << 3U);

         hetRAM->Instruction[(pwm << 1U) + 41U].Data = (uint32)((((pwmPeriod * dutyCycle) / 100U) * 128U ) + 128U);

         hetRAM->Instruction[(pwm << 1U) + 42U].Data = ((uint32)pwmPeriod << 7U) - 128U;

    }

    /** @fn void pwmGetSignal(hetRAMBASE_t * hetRAM, uint32 pwm, hetSIGNAL_t signal)

    * @brief Get duty cycle

    * @param[in] hetRAM Pointer to HET RAM:

    * - hetRAM1: HET1 RAM pointer

    * - hetRAM2: HET2 RAM pointer

    * @param[in] pwm Pwm signal:

    * - pwm0: Pwm 0

    * - pwm1: Pwm 1

    * - pwm2: Pwm 2

    * - pwm3: Pwm 3

    * - pwm4: Pwm 4

    * - pwm5: Pwm 5

    * - pwm6: Pwm 6

    * - pwm7: Pwm 7

    * @param[in]

    * - duty cycle in %.

    * - period period in us.

    *

    * Gets current signal of the given pwm signal.

    */

    /* SourceId : HET_SourceId_006 */

    /* DesignId : HET_DesignId_006 */

    /* Requirements : HL_SR368 */

    void pwmGetSignalFloat(hetRAMBASE_t * hetRAM, uint32 pwm, hetSIGNALFLOAT_t *signal)

    {

       float32 pwmDuty = (hetRAM->Instruction[(pwm << 1U) + 41U].Data - 128U) >> 7U;

       float64 pwmPeriod = (hetRAM->Instruction[(pwm << 1U) + 42U].Data + 128U) >> 7U;

       signal->duty = (pwmDuty * 100U) / pwmPeriod;

       if(hetRAM == hetRAM1)

       {

         signal->period = ((float64)pwmPeriod * 1280.000F) / 1000.0F;

       }

       else

      {

         signal->period = ((float64)pwmPeriod * 1280.000F) / 1000.0F;

      }

    }

  • Hi,
    Remember that you are only using 32bit floating point, which has limited precision. What you are seeing is typical of the limited precision floating point values.

    If, for example, you had a f32 variable which equals 0.0. You then add 0.1 to it 10 times. you would expect the variable to equal 1.0. Indeed most of the time the answer will be 0.999998 due to the limited precision.

    There is plenty of info as to why this happens with f32's on google.

    Cheers
    Stomp!