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.

TMS320F28027F: Interrupt-based hall sensor commutation

Part Number: TMS320F28027F
Other Parts Discussed in Thread: DRV8323, , MOTORWARE

Good morning TI community,

I would like to implement an interrupt-based hall sensor commutation to achieve very high RPM for my motor. I'm using an TMS320F28027F with the DRV8323 driver and hall sensor feedback. I've been able to configure lab11e for my setup and drive the motor using GPIO-based hall sensor feedback sampled in the mainISR. However, this approach fails at very high RPM, and I need to drive my motor at 120,000RPM. Looking at my scope, I can see the control falls apart when there is a delay between the hall sensor state change and the change in PWM output. To get around this limitation, I'd like to implement hardware interrupts for these pins and toggle the hall state in a new ISR (e.g. hall_ISR).

We've implemented changes to enable this hall_ISR based on a state change to the pin, but we found that there is a variable delay between the rising/falling edges and when the interrupt is triggered (based on triggering a GPIO output pin in the hall_ISR). This delay varies from a few microseconds to ~20 microseconds. What other interrupts may be running in lab11 that could delay the execute of my hall_ISR function? Why am I seeing a variable delay between a rising/falling edge and triggering this function?

Here's an example of the logic to configure the ISR. Thanks for your support!

/* Set this GPIO as TZ input so that the qualification mode can be Async */
GPIO_setMode(obj->gpioHandle,GPIO_Number_29,GPIO_29_Mode_TZ3_NOT);
GPIO_setExtInt(obj->gpioHandle, GPIO_Number_29, CPU_ExtIntNumber_1);
PIE_registerPieIntHandler(obj->pieHandle, PIE_GroupNumber_1, PIE_SubGroupNumber_4, &hallISR);

PIE_enable(obj->pieHandle);
PIE_enableExtInt(obj->pieHandle, CPU_ExtIntNumber_1);
CPU_enableInt(obj->cpuHandle, CPU_IntNumber_1);

GPIO_setQualification(obj->gpioHandle, GPIO_Number_29, GPIO_Qual_ASync);
GPIO_setQualificationPeriod(obj->gpioHandle, GPIO_Number_29, 0);
PIE_setExtIntPolarity(obj->pieHandle, CPU_ExtIntNumber_1, PIE_ExtIntPolarity_RisingAndFallingEdge);
PIE_enableInt(obj->pieHandle, PIE_GroupNumber_1, PIE_InterruptSource_XINT_1);

And here's my hall_ISR function:

//! \brief The Hall sensor based ISR that implements the motor control.
interrupt void hallISR(void)
{
  PIE_clearInt(halHandle->pieHandle, PIE_GroupNumber_1);
  GPIO_toggle(halHandle->gpioHandle,GPIO_Number_28);
}

Best regards,

Chris

  • Hi Chris,

    A TI engineer has been assigned to help with your issue. The response may be delayed due to the holiday. Thanks for your patience.

    Best regards,
    Chen
  • Only one interrupt is enabled in lab11x which is trigged by ADC. For high speed running with hall sensor, you can't use this example to check the hall sensor input as lab11 which check GPIOs state of Hall input. There is a delay depends on ISR code executing time and ISR frequency which maybe about 20~30us. You should use add a additional interrupt for hall input to implement commutation immediately.
  • Hi Yanming,

    I've created a new ISR called hall_ISR which is triggered from XINT1, XINT2, or XINT3, but it looks like the main_ISR is a higher priority (as it is using ADCINT1). Can I move main_ISR to ADCINT9 so that XINT1 and XINT2 have a higher priority? Is the main_ISR the only interrupt configured in lab11?

    Thanks,

    Chris

  • Good morning Yanming,

    I've moved mainISR to ADCINT9, but it still appears to be a higher priority than XINT1 and XINT2. Looking at my scope, I can see that the XINT1 interrupt function does not get called until ADCINT9/mainISR() has finished. Can you provide some guidance on why I am not seeing the proper prioritization? I've copied the sections of hal.c where I implemented the change from ADCINT1 to ADCINT9. Do they need to be set in different CPU priorities or is it sufficient that they have different PIE group priorities?

    //! \brief      Initializes the interrupt vector table

    //! \details    Points the ISR to the function mainISR.

    //! \param[in]  handle  The hardware abstraction layer (HAL) handle

    static inline void HAL_initIntVectorTable(HAL_Handle handle)

    {

      HAL_Obj *obj = (HAL_Obj *)handle;

      PIE_Obj *pie = (PIE_Obj *)obj->pieHandle;

     

     

      ENABLE_PROTECTED_REGISTER_WRITE_MODE;

     

    /* JCMII */

    #ifndef USE_ADCINT9

      pie->ADCINT1 = &mainISR;

    #else

      pie->ADCINT9 = &mainISR;

    #endif

     

      DISABLE_PROTECTED_REGISTER_WRITE_MODE;

     

      return;

    } // end of HAL_initIntVectorTable() function

     

     

    void HAL_enableAdcInts(HAL_Handle handle)

    {

      HAL_Obj *obj = (HAL_Obj *)handle;

     

      // enable the PIE interrupts associated with the ADC interrupts

    /* JCMII */

    #ifndef USE_ADCINT9

      PIE_enableAdcInt(obj->pieHandle,ADC_IntNumber_1);

    #else

      PIE_enableAdcInt(obj->pieHandle,ADC_IntNumber_9);

    #endif

     

      // enable the ADC interrupts

    /* JCMII */

    #ifndef USE_ADCINT9

      ADC_enableInt(obj->adcHandle,ADC_IntNumber_1);

    #else

      ADC_enableInt(obj->adcHandle,ADC_IntNumber_9);

    #endif

     

      // enable the cpu interrupt for ADC interrupts

    /* JCMII */

    #ifndef USE_ADCINT9

      CPU_enableInt(obj->cpuHandle,CPU_IntNumber_10);

    #else

      CPU_enableInt(obj->cpuHandle,CPU_IntNumber_1);

    #endif

     

      return;

    } // end of HAL_enableAdcInts() function

     

     

     

    void HAL_setupAdcs(HAL_Handle handle)

    .

    .

    .

    .

    // configure the interrupt sources

    #ifndef USE_ADCINT9

      ADC_disableInt(obj->adcHandle,ADC_IntNumber_1);

      ADC_setIntMode(obj->adcHandle,ADC_IntNumber_1,ADC_IntMode_ClearFlag);

      ADC_setIntSrc(obj->adcHandle,ADC_IntNumber_1,ADC_IntSrc_EOC7);

    #else

      ADC_disableInt(obj->adcHandle,ADC_IntNumber_1);

      ADC_disableInt(obj->adcHandle,ADC_IntNumber_9);

      ADC_setIntMode(obj->adcHandle,ADC_IntNumber_9,ADC_IntMode_ClearFlag);

      ADC_setIntSrc(obj->adcHandle,ADC_IntNumber_9,ADC_IntSrc_EOC7);

    #endif

     

     

     

    interrupt void mainISR(void)

    .

    .

    .

    // acknowledge the ADC interrupt

    #ifndef USE_ADCINT9

      HAL_acqAdcInt(halHandle,ADC_IntNumber_1);

    #else

      HAL_acqAdcInt(halHandle,ADC_IntNumber_9);

    #endif

  • One very fundamental question I have is whether the interrupts can be interrupted by other interrupts (?). From my understanding, it was possible to interrupt the mainISR if that interrupt had a higher priority. For instance, if I'm using ADCINT8 and CPU interrupt 10 for the mainISR and XINT1 for my hallISR, am I able to interrupt the mainISR?

    Thanks,
    Chris
  • Hi Chris,

    By default, interrupt nesting is not done.  However, it is possible - but requires a few extra lines of code in the lower priority ISR.  Please see the following wiki article:
    http://processors.wiki.ti.com/index.php/Interrupt_Nesting_on_C28x

    This article utilizes the bit-field method of interfacing registers vs the motorware functions, but it should be possible to translate the idea into motorware-style code.

    You may also want to consider immediate mode for register updates in your PWM, if you're not.

    Hopefully this helps!


    Thank you,
    Brett

  • Hi Brett,

    Thank you. This is exactly what we needed to implement. We've made the changes and have the nested mainISR and hallISR working.

    Can you provide a reference or more details about immediate mode for register updates in your PWM? I'm not familiar with this approach.

    Best regards,

    Chris

  • Hi Brett,

    One other question for you, we're seeing an unusual event after setting the PWM duty cycle in our hallISR function. It seems that the duty cycle is properly set for two of the channels, with the third channel set to zero, however, after a variable period of time, the third channel also begins sending PWM data.

    The top signal on the scope, test pin, represents a hall transition state, and you can see the PWM duty cycle change properly at these transitions. The strange event is that many microseconds afterwards, it seems to revert back to its previous PWM state (before the next hall transition, and call to hallISR function). Any thoughts as to what may be re-setting the PWM outputs. We've traced the code very closely and can not find anywhere else in the project where the PWM outputs are set.

    Thanks for your feedback!

    Best regards,

    Chris

  • Hi Chris,

    I believe that what you are seeing is the result of using shadow mode instead of immediate mode for your ePWMs.  Using shadow mode will make writes to many of the ePWM registers only occur on a specific event, such as when the ePWM's counter reaches 0 - which likely isn't what you want here.  Shadow mode does have the benefit of making sure that all register writes take affect at one time (good for making sure shoot-through situations don't occur, etc) so you may now need to be a bit more conscious about the distance between writes in your code.

    These features are described in detail within the '02x/'03x ePWM User's Guide - as are the registers you'll need to touch:
    http://www.ti.com/product/TMS320F28027F/technicaldocuments#doctype6

    Hopefully this helps!


    Thank you,
    Brett

  • Hi Chris,

    I'm going to assume that the comment in my previous post helped to resolve the issue.  Feel free to respond back if not.


    Thank you,
    Brett

  • Hi Brett,

    There ended up being a line of code in the main loop where it was enabling the PWM, and stepping on our changes in the hallISR() function. Thanks for all of your help on this matter. Re-prioritizing the threads was a big help in improving our control method.

    Best regards,

    Chris