Problem with multiple timer input capture

Post here first, or if you can't find a relevant section!
Post Reply
audiruss
Posts: 2
Joined: Sat Mar 06, 2021 11:52 am

Problem with multiple timer input capture

Post by audiruss »

Hi,

I'm using the arudinostm32 core (v1.9.0) with platformIO on a Nucleo-F103RB board.

I'm having difficulty using more than one timer channels with input capture. In my example below, im using TIM2_CH1 and TIM2_CH2 on PA0 and PA1.

If i start with just TIM2_CH1 - it works fine. Once I add TIM2_CH2 - TIM2_CH1 stops working (returns 0), although TIM2_CH2 works correctly.

I'm sure it's something jacked up in the code i lifted from the examples - could anyone point in the right direction please.

thanks

Code: Select all


#include <Arduino.h>

const int rcCH1 = PA0;
const int rcCH2 = PA1;
//const int rcCH2 = PB6;

//Timer setup for rcCH1
volatile uint32_t rcCH1channel;
volatile int32_t rcCH1PulseWidth, rcCH1startTime, rcCH1endTime;
volatile TimerModes_t rcCH1currentMode;
HardwareTimer *ch1;

//Timer setup for rcCH2

volatile uint32_t rcCH2channel;
volatile int32_t rcCH2PulseWidth, rcCH2startTime, rcCH2endTime;
volatile TimerModes_t rcCH2currentMode;
HardwareTimer *ch2;

void rcCH1InputCapture_IT_callback(void)
{
     ch1->pause();
  rcCH1currentMode = ch1->getMode(rcCH1channel);
  if (rcCH1currentMode == TIMER_INPUT_CAPTURE_RISING){
    
    rcCH1startTime = ch1->getCaptureCompare(rcCH1channel);
    //ch1->pause();
    ch1->setMode(rcCH1channel, TIMER_INPUT_CAPTURE_FALLING, rcCH1);
    //ch1->resume();
  }
  if (rcCH1currentMode == TIMER_INPUT_CAPTURE_FALLING){
    rcCH1endTime = ch1->getCaptureCompare(rcCH1channel);
    //ch1->pause();
    ch1->setMode(rcCH1channel, TIMER_INPUT_CAPTURE_RISING, rcCH1);
    //ch1->resume();
    rcCH1PulseWidth = (rcCH1endTime - rcCH1startTime);
    if (rcCH1PulseWidth < 0)rcCH1PulseWidth += 0xFFFF;
}
ch1->resume();
}

void rcCH2InputCapture_IT_callback(void)
{
     ch2->pause();
  rcCH2currentMode = ch2->getMode(rcCH2channel);
  if (rcCH2currentMode == TIMER_INPUT_CAPTURE_RISING){
    rcCH2startTime = ch2->getCaptureCompare(rcCH2channel);
    //ch2->pause();
    ch2->setMode(rcCH2channel, TIMER_INPUT_CAPTURE_FALLING, rcCH2);
    //ch2->resume();
  }
  if (rcCH2currentMode == TIMER_INPUT_CAPTURE_FALLING){
    rcCH2endTime = ch2->getCaptureCompare(rcCH2channel);
    //ch2->pause();
    ch2->setMode(rcCH2channel, TIMER_INPUT_CAPTURE_RISING, rcCH2);
    //ch2->resume();
    rcCH2PulseWidth = (rcCH2endTime - rcCH2startTime);
    if (rcCH2PulseWidth < 0)rcCH2PulseWidth += 0xFFFF;
}
ch2->resume();
}


void setup()
{

//Timer setup for rcCH1
TIM_TypeDef *Instance = (TIM_TypeDef *)pinmap_peripheral(digitalPinToPinName(rcCH1), PinMap_PWM);
    rcCH1channel = STM_PIN_CHANNEL(pinmap_function(digitalPinToPinName(rcCH1), PinMap_PWM));
    ch1 = new HardwareTimer(Instance);
    ch1->setMode(rcCH1channel, TIMER_INPUT_CAPTURE_RISING, rcCH1);
    uint32_t PrescalerFactor =71;
    ch1->setPrescaleFactor(PrescalerFactor);
    ch1->setOverflow(0x10000); // Max Period value to have the largest possible time to detect rising edge and avoid timer rollover
    ch1->attachInterrupt(rcCH1channel, rcCH1InputCapture_IT_callback);
    ch1->resume();

//Timer setup for rcCH2
TIM_TypeDef *Instance2 = (TIM_TypeDef *)pinmap_peripheral(digitalPinToPinName(rcCH2), PinMap_PWM);
    rcCH2channel = STM_PIN_CHANNEL(pinmap_function(digitalPinToPinName(rcCH2), PinMap_PWM));
    ch2 = new HardwareTimer(Instance2);
    ch2->setMode(rcCH2channel, TIMER_INPUT_CAPTURE_RISING, rcCH2);
     uint32_t PrescalerFactor2 =71;
     ch2->setPrescaleFactor(PrescalerFactor2);
     ch2->setOverflow(0x10000); // Max Period value to have the largest possible time to detect rising edge and avoid timer rollover
    ch2->attachInterrupt(rcCH2channel, rcCH2InputCapture_IT_callback);
    ch2->resume();
    
    Serial2.begin(115200);
}


void loop()
{
  
 Serial2.print(rcCH1PulseWidth);
  Serial2.print(",");
  Serial2.println(rcCH2PulseWidth);
}

mlundin
Posts: 94
Joined: Wed Nov 04, 2020 1:20 pm
Answers: 6
Location: Sweden

Re: Problem with multiple timer input capture

Post by mlundin »

Since both inputs are on the same timer, TIM2, there should be only one HardwareTimer object, and both channels should be configured for this timer.
audiruss
Posts: 2
Joined: Sat Mar 06, 2021 11:52 am

Re: Problem with multiple timer input capture

Post by audiruss »

Ah, makes sense. Will try it out, thanks a lot for your help!
eltonwisk
Posts: 2
Joined: Mon Sep 13, 2021 7:21 pm

Re: Problem with multiple timer input capture

Post by eltonwisk »

Hello ,

I am using stm32f446re nucleo board . and i face some issue in timer input capture .

here i am using 2 timers TIM6 ( for time base generation ) and TIM2 (free running input capture purpose)

actually my code is working fine when i run the first timer(TIM6) at 10 micro or 100 micro second time base generation . I actually toggle the gpio in IRQ handler of TIM6 and that is input to the TIM2 input channel where i detect the gap between rising and falling edge of a gpio . TIM2 actually DMA the content of CCR1 to memory .

as i said this works fine when i use the TIM6 for 10 micro and 100 micro time base generation

but when i use the TIM6 for 1 mirco second time base generation , the TIM2 is not giving correct values for the gpio toggling . Can you please help me to understand what is going wrong ?

i am using AHB = 84Mhz, timer clock = 48Mhz.

Here is a code

int main(void)



{


/* USER CODE BEGIN 1 */


uint32_t diffCapture=0;


double frequency=0;


char msg[30];
/* USER CODE END 1 */

/* MCU Configuration----------------------------------------------------------*/

/* Reset of all peripherals, Initializes the Flash interface and the Systick. */



HAL_Init();
/* USER CODE BEGIN Init */

/* USER CODE END Init */

/* Configure the system clock */



SystemClock_Config();
/* USER CODE BEGIN SysInit */

/* USER CODE END SysInit */

/* Initialize all configured peripherals */



MX_GPIO_Init();


MX_DMA_Init();


MX_USART2_UART_Init();


MX_TIM6_Init();


MX_TIM2_Init();


/* USER CODE BEGIN 2 */


HAL_TIM_IC_Start_DMA(&htim2, TIM_CHANNEL_1, (uint32_t*) captures, 2);


HAL_TIM_Base_Start_IT(&htim6);
/* USER CODE END 2 */

/* Infinite loop */



/* USER CODE BEGIN WHILE */


while (1)


{
if (captureDone != 0) {



if (captures[1] >= captures[0])


diffCapture = captures[1] - captures[0];


else


diffCapture = (htim2.Instance->ARR - captures[0]) + captures[1];
frequency = HAL_RCC_GetPCLK1Freq() / (htim2.Instance->PSC + 1);



frequency = (float) frequency / diffCapture;
sprintf(msg, 'Input frequency: %.3f\r\n', frequency);



//HAL_UART_Transmit(&huart2, (uint8_t*) msg, strlen(msg), HAL_MAX_DELAY);


//while (1);


}
}

}

/* TIM2 init function */



static void MX_TIM2_Init(void)


{
TIM_MasterConfigTypeDef sMasterConfig;



TIM_IC_InitTypeDef sConfigIC;
htim2.Instance = TIM2;



htim2.Init.Prescaler = 0;


htim2.Init.CounterMode = TIM_COUNTERMODE_UP;


htim2.Init.Period = 65535;


htim2.Init.ClockDivision = TIM_CLOCKDIVISION_DIV1;


if (HAL_TIM_IC_Init(&htim2) != HAL_OK)


{


_Error_Handler(__FILE__, __LINE__);


}
sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;



sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;


if (HAL_TIMEx_MasterConfigSynchronization(&htim2, &sMasterConfig) != HAL_OK)


{


_Error_Handler(__FILE__, __LINE__);


}
sConfigIC.ICPolarity = TIM_INPUTCHANNELPOLARITY_RISING;



sConfigIC.ICSelection = TIM_ICSELECTION_DIRECTTI;


sConfigIC.ICPrescaler = TIM_ICPSC_DIV1;


sConfigIC.ICFilter = 0;


if (HAL_TIM_IC_ConfigChannel(&htim2, &sConfigIC, TIM_CHANNEL_1) != HAL_OK)


{


_Error_Handler(__FILE__, __LINE__);


}
}

/* TIM6 init function */



static void MX_TIM6_Init(void)


{
TIM_MasterConfigTypeDef sMasterConfig;

htim6.Instance = TIM6;



htim6.Init.Prescaler = 0;


htim6.Init.CounterMode = TIM_COUNTERMODE_UP;


htim6.Init.Period = 47;


if (HAL_TIM_Base_Init(&htim6) != HAL_OK)


{


_Error_Handler(__FILE__, __LINE__);


}
sMasterConfig.MasterOutputTrigger = TIM_TRGO_RESET;



sMasterConfig.MasterSlaveMode = TIM_MASTERSLAVEMODE_DISABLE;


if (HAL_TIMEx_MasterConfigSynchronization(&htim6, &sMasterConfig) != HAL_OK)


{


_Error_Handler(__FILE__, __LINE__);


}
}

/* USER CODE BEGIN 4 */

void HAL_TIM_IC_CaptureCallback(TIM_HandleTypeDef *htim) {



if (htim->Channel == HAL_TIM_ACTIVE_CHANNEL_1) {


captureDone = 1;




}


}
Post Reply

Return to “General discussion”