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
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
Hello @Gouthambalraj ,
We have some application notes with the Hall Sensors BLDC, please let me know if you find this information useful.
BLDC Motor Control with Hall Sensors
BLDC Motor Control with Hall Sensors Based on FRDM-KE02Z
BLDC Motor Control with Hall Effect Sensors Using MQX on Kinetis PMSM Field-Oriented Control on FRDM- KV31F with Hall and Encoder Sensors
@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.
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.
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.
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.