FTM dual edge capture for calculating HALL sensor velocity

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

FTM dual edge capture for calculating HALL sensor velocity

2,548 Views
Gouthambalraj
Contributor II

Hi,

 

     I am using NXP mkv30f64vlf10 for BLDC controller application. I used FTM module dual edge capture feature to capture the rising and falling edge of HALL sensor A (which is connected to FTM1 channel 0).

     Interrupts trigger for rise and fall in sensor once the motor rotates , but sometimes at motor start the program gets stuck inside the Hall interrupt loop.

     there are two if else conditions one for rising edge and one for falling edge , initially the logic got stuck inside the rising edge loop and never enters falling edge else if. So, I cleared the flag status for rising edge , then the loop exits and enters falling edge but never comes back to the rising edge in the next cycle.

    I am sharing the interrupt logic, if someone can take a look and offer a solution or any suggestion would be really helpful.

 

M1_HALL_TIMER is FTM1

 

static void InitHall(void)
{
    ftm_config_t hall_ftm_info;
    ftm_dual_edge_capture_param_t edge_param;

    FTM_GetDefaultConfig(&hall_ftm_info);

    // Set prescalar value
    hall_ftm_info.prescale = kFTM_Prescale_Divide_64;

    /* Initialize FTM module */
    FTM_Init(M1_HALL_TIMER, &hall_ftm_info);

    edge_param.mode = kFTM_Continuous;
    /* Set capture edges to calculate the pulse width of input signal */
    edge_param.currChanEdgeMode = kFTM_RisingEdge;
    edge_param.nextChanEdgeMode = kFTM_FallingEdge;

    /* Setup dual-edge capture on a FTM channel pair */
    // Filter Enabled - 4
    FTM_SetupDualEdgeCapture(M1_HALL_TIMER, M1_HALL_TIMER_INPUT_CAPTURE_CHANNEL_PAIR, &edge_param, 100);

    /* Set the timer to be in free-running mode */
    FTM_SetTimerPeriod(M1_HALL_TIMER, 0xFFFF);

    /* Enable first channel interrupt */
    FTM_EnableInterrupts(M1_HALL_TIMER, M1_HALL_TIMER_FIRST_CHANNEL_INTERRUPT_ENABLE);

    /* Enable second channel interrupt when the second edge is detected */
    FTM_EnableInterrupts(M1_HALL_TIMER, M1_HALL_TIMER_SECOND_CHANNEL_INTERRUPT_ENABLE);

    /* Enable overflow interrupt */
    FTM_EnableInterrupts(M1_HALL_TIMER, kFTM_TimeOverflowInterruptEnable);

    /* Enable at the NVIC */
    EnableIRQ(M1_HALL_IRQN);
    NVIC_SetPriority(M1_HALL_IRQN, 3);

    FTM_ClearStatusFlags(M1_HALL_TIMER, M1_HALL_TIMER_FIRST_CHANNEL_FLAG);
    FTM_ClearStatusFlags(M1_HALL_TIMER, M1_HALL_TIMER_SECOND_CHANNEL_FLAG);

    FTM_StartTimer(M1_HALL_TIMER, kFTM_SystemClock);
}


void M1_HALL_IRQ_HANDLER(void){

	    static uint32_t g_timerOverflowInterruptCount = 0U;
		static uint32_t g_hallfirstChannelOverflowCount = 0U;

		if ((FTM_GetStatusFlags(M1_HALL_TIMER) & kFTM_TimeOverflowFlag) == kFTM_TimeOverflowFlag)
		{
			/* Clear overflow interrupt flag.*/
			FTM_ClearStatusFlags(M1_HALL_TIMER, kFTM_TimeOverflowFlag);
			g_timerOverflowInterruptCount++;
		}
		else if ((FTM_GetStatusFlags(M1_HALL_TIMER) & M1_HALL_TIMER_FIRST_CHANNEL_FLAG) == M1_HALL_TIMER_FIRST_CHANNEL_FLAG &&
				!((FTM_GetStatusFlags(M1_HALL_TIMER) & M1_HALL_TIMER_SECOND_CHANNEL_FLAG) == M1_HALL_TIMER_SECOND_CHANNEL_FLAG))
		{
			// Rising Edge
			g_sM1HallSensor.raising_edge_detected = true;
			g_hallfirstChannelOverflowCount  = g_timerOverflowInterruptCount;
			FTM_DisableInterrupts(M1_HALL_TIMER, M1_HALL_TIMER_FIRST_CHANNEL_INTERRUPT_ENABLE);

		}
		else if ((FTM_GetStatusFlags(M1_HALL_TIMER) & M1_HALL_TIMER_SECOND_CHANNEL_FLAG) == M1_HALL_TIMER_SECOND_CHANNEL_FLAG)
		{
			// Falling Edge
			g_sM1HallSensor.falling_edge_detected = true;

			/* Clear second channel interrupt flag.*/
			FTM_ClearStatusFlags(M1_HALL_TIMER, M1_HALL_TIMER_FIRST_CHANNEL_FLAG);
			FTM_ClearStatusFlags(M1_HALL_TIMER, M1_HALL_TIMER_SECOND_CHANNEL_FLAG);

			uint32_t raising_edge = M1_HALL_TIMER->CONTROLS[0].CnV;
			uint32_t falling_edge = M1_HALL_TIMER->CONTROLS[1].CnV;

			// 65536 = FTM1->MOD
			g_sM1HallSensor.pulse_width = (g_timerOverflowInterruptCount - g_hallfirstChannelOverflowCount) * 65536U
						+ (falling_edge - raising_edge) + 1U;

			// Reset counters
			g_timerOverflowInterruptCount = 0;
			g_hallfirstChannelOverflowCount = 0;
			FTM_DisableInterrupts(M1_HALL_TIMER, M1_HALL_TIMER_SECOND_CHANNEL_INTERRUPT_ENABLE);
		}
		else
		{
			__asm volatile ("nop");
		}
		// If no update in 0.5 seconds (MOD/ (40MHz/64)) * 5 set pluse diff to zero
		if (g_timerOverflowInterruptCount > 5){
			g_sM1HallSensor.pulse_width = 0U;

			// Reset counters
			g_timerOverflowInterruptCount = 0;
			g_hallfirstChannelOverflowCount = 0;
		}

		/* Add for ARM errata 838869, affects Cortex-M4, Cortex-M4F
		 Store immediate overlapping exception return operation might vector to incorrect interrupt. */
		#if defined __CORTEX_M && (__CORTEX_M == 4U)
			__DSB();
		#endif

}

 

 

thanks and regards,

Goutham

0 Kudos
Reply
7 Replies

1,139 Views
richardmensah
Contributor II

I have faced a similar challenge and unfortunately, these are some of the places the reference manual doesn't give a lot of information. The working solution is to do the following

1. Ungate the clocks to FTM1 and FTM2

2. configure the FTM2_CH0, FTM2_CH1, FTM1_CH1 to input capture with capture on both rising and falling edges

3. Enable interrupts only on channel 1 of FTM2 (FTM2_CH1).

4. Set the pin mux to ALT3 for the three input pins that have input capture capabilities.

5. Set the FTM2CH1SRC bit to 1 in the SIM_SOPT4

6. Start both timers FTM1 and FTM2

 

 

 

0 Kudos
Reply

2,526 Views
nxf77486
NXP TechSupport
NXP TechSupport

2,522 Views
Gouthambalraj
Contributor II

@nxf77486 thank you so much for your reply.

 

    These documents are useful in terms of understanding the logic of HALL sensor speed calculation. I have used the same in my code, used interrupts to capture the time between falling and rising edge and clear the capture flag. The problem is, it is not working reliably sometimes it works and sometimes it doesn't. I am probably doing some mistake in the code. So, a software implementation or any software example could help me more regarding this issue.

0 Kudos
Reply

2,496 Views
nxf77486
NXP TechSupport
NXP TechSupport

Hello @Gouthambalraj ,

I understand, we have some motor control examples in the SDK of the MKV31 I understand you are currently working with a KV30, but this examples might help you as a guide in order to obtain the examples please in the build SDK page select Motor Control Software. The examples will be inside the zip file under middleware folder. Please let me know if I can help you on anything else.

FRDM-KV31F 

0 Kudos
Reply

2,491 Views
Gouthambalraj
Contributor II

Hi @nxf77486  ,

 

    I have come across these examples before but the problem is the SDK examples are sensorless. They dont use Hall sensor for speed measurement. The Hall sensor examples are removed in the latest SDKs i think.

0 Kudos
Reply

2,472 Views
nxf77486
NXP TechSupport
NXP TechSupport

Hello @Gouthambalraj ,

I apologize beside the Application Notes I send previously we do not have a BLDC driver for Hall sensor examples. We apologize for the inconvenient this might cause.

2,468 Views
Gouthambalraj
Contributor II

Hi @nxf77486 ,

 

    No issues, will try to figure this out. But in the future it will nice if we have an example in this area, it will be really helpful for someone new to this controller. However, thank you for taking your time for replying to my queries and helping me in the most possible way you can.

0 Kudos
Reply