2021-08-06 05:22 PM
Hi!
I have a STM32F373 processor and I have 2 Encoders and 3 Input Captures.
I have enabled DMA for input capture.
Timer 4:
Timer 19:
And I have this code.
My questions are:
static TIM_HandleTypeDef* tim4_handle;
static TIM_HandleTypeDef* tim19_handle;
volatile static uint32_t input_capture0[2] = {0};
volatile static uint32_t input_capture1[2] = {0};
volatile static uint32_t input_capture2[2] = {0};
static uint32_t pulse_count[4] = {0};
void STM32_PLC_Start_Counters(TIM_HandleTypeDef* htim4, TIM_HandleTypeDef* htim19) {
/* Encoder - Prescaler does not effect encoder */
if(HAL_TIM_Encoder_Start(htim4, TIM_CHANNEL_ALL) != HAL_OK)
Error_Handler();
if(HAL_TIM_Encoder_Start(htim19, TIM_CHANNEL_ALL) != HAL_OK)
Error_Handler();
/*
* Input capture for measuring frequency
* For TIM4 and TIM19
* Timer clock: 48 Mhz
* Prescaler: 4799
* Counter: 65535 (0xffff)
* Update frequency: 6.5535 Hz
* Example: For every second, it will count 10000
* Lowest frequency measurement: 1/(0xFFFF*0.0001) = 0.1526 Hz
* Highest frequency measurement: 1/(1*0.0001) = 10000 Hz
*/
if(HAL_TIM_IC_Start_DMA(htim4, TIM_CHANNEL_3, (uint32_t*)input_capture1, 2) != HAL_OK)
Error_Handler();
if(HAL_TIM_IC_Start_DMA(htim4, TIM_CHANNEL_4, (uint32_t*)input_capture0, 2) != HAL_OK)
Error_Handler();
if(HAL_TIM_IC_Start_DMA(htim19, TIM_CHANNEL_3, (uint32_t*)input_capture2, 2) != HAL_OK)
Error_Handler();
/* Save */
tim4_handle = htim4;
tim19_handle = htim19;
}
int16_t STM32_PLC_Encoder_Get(uint8_t i) {
if(i == 0)
return tim4_handle->Instance->CNT;
else
return tim19_handle->Instance->CNT;
}
static float compute_frequency(uint16_t input_capture[]) {
/*
* Typical worst case scenarios:
* T1: 0xFFFF - T0: 0x0
* T1: 0x0 - T0: 0xFFFF
* T1: 0x7FFF - T0: 0x7FFF
* T1: 0x0 - T0: 0x0
*/
if(input_capture[1] > input_capture[0]) {
return (float) 1/((input_capture[1] - input_capture[0])*0.0001f);
} else if(input_capture[1] < input_capture[0]) {
return (float) 1/((input_capture[1] + 0xFFFF - input_capture[0])*0.0001f);
} else if(input_capture[1] == 0x7FFF && input_capture[0] == 0x7FFF){
return (float) 1/(0xFFFF*0.0001f);
} else {
return 0;
}
}
float STM32_PLC_Input_Capture_Get(uint8_t i) {
if(i == 0)
return compute_frequency((uint16_t*)input_capture0);
else if(i == 1)
return compute_frequency((uint16_t*)input_capture1);
else
return compute_frequency((uint16_t*)input_capture2);
}
void STM32_PLC_Input_Capture_Reset() {
for(uint8_t i = 0; i < 2; i++){
input_capture0[i] = 0;
input_capture1[i] = 0;
input_capture2[i] = 0;
}
}
void STM32_PLC_Pulse_Count_Set(uint8_t i){
pulse_count[i]++;
}
uint32_t STM32_PLC_Pulse_Count_Get(uint8_t i){
return pulse_count[i];
}
void STM32_PLC_Pulse_Count_Reset(){
memset(pulse_count, 0, sizeof(pulse_count));
}
Solved! Go to Solution.
2021-08-07 03:11 PM
Is it totaly normal that I getting a number 65535 if I connect 3.3V to encoder plus? And I get only value 1 if I connect it to encoder minus.
If I not connect anything, I get the value 0. Why? I thougth encoder till remember the value.
Edit:
Now it's working!
static TIM_HandleTypeDef* tim4_handle;
static TIM_HandleTypeDef* tim19_handle;
static uint16_t encoder_pulses_per_revolution[2] = {0};
static int16_t encoder[2] = {0};
void STM32_PLC_Start_Encoder(TIM_HandleTypeDef* htim4, TIM_HandleTypeDef* htim19) {
/* Encoder - Prescaler does not effect encoder */
if(HAL_TIM_Encoder_Start(htim4, TIM_CHANNEL_ALL) != HAL_OK)
Error_Handler();
if(HAL_TIM_Encoder_Start(htim19, TIM_CHANNEL_ALL) != HAL_OK)
Error_Handler();
/* Save */
tim4_handle = htim4;
tim19_handle = htim19;
}
float STM32_PLC_Encoder_Get(uint8_t i) {
/* Safety */
if(encoder_pulses_per_revolution[i] == 0)
encoder_pulses_per_revolution[i] = 1;
float pulses = (float)encoder_pulses_per_revolution[i];
return ((float)STM32_PLC_Encoder_Get_Raw(i))/pulses;
}
int16_t STM32_PLC_Encoder_Get_Raw(uint8_t i) {
if(i == 0)
encoder[i] += __HAL_TIM_GET_COUNTER(tim4_handle);
else
encoder[i] += __HAL_TIM_GET_COUNTER(tim19_handle);
return encoder[i];
}
void STM32_PLC_Encoder_Set_Pulses_Per_Revolutions(uint8_t i, uint16_t pulses_per_revolution) {
encoder_pulses_per_revolution[i] = pulses_per_revolution;
}
2021-08-07 11:46 AM
Yes.
IC will capture the CNT value at the time of the event, which is then transferred by DMA.
2021-08-07 12:18 PM
So in this case, combining Encoder with IC....bad idea?
Do you have another solution?
I think I need to have DMA because if I using interrupts, then the interrupts will...well...interrupt other parts of the code.
2021-08-07 12:23 PM
2021-08-07 12:26 PM
Why does it not seems useful? Encoder + IC?
I'm using IC because I want to measure frequecy.
I'm using encoder because I want to measure position.
2021-08-07 12:35 PM
Use one timer for the encoder and use another timer to measure frequency.
It may be possible to hook up IC to transfer the CNT value from another timer instead, but it's probably not something that HAL supports out of the box.
2021-08-07 12:47 PM
So what is TIM_UP for something in DMA?
Is that for encoder?
2021-08-07 02:22 PM
Ok! I have split up now. Now I have 2 different timers for input capture and two different timers for encoders. I hope this will work for Input Capture.
volatile static uint32_t input_capture0[2] = {0};
volatile static uint32_t input_capture1[2] = {0};
void STM32_PLC_Start_Input_Capture(TIM_HandleTypeDef* htim17, TIM_HandleTypeDef* htim16) {
/*
* Input capture for measuring frequency
* For TIM17 and TIM16
* Timer clock: 48 Mhz
* Prescaler: 4799
* Counter: 65535 (0xffff)
* Update frequency: 0.1526 Hz (1/0.1526 = 6.5535 seconds)
* Example: For every second, it will count 10000
* Lowest frequency measurement: 1/(0xFFFF*0.0001) = 0.1526 Hz
* Highest frequency measurement: 1/(1*0.0001) = 10000 Hz
*/
if(HAL_TIM_IC_Start_DMA(htim16, TIM_CHANNEL_1, (uint32_t*)input_capture1, 2) != HAL_OK)
Error_Handler();
if(HAL_TIM_IC_Start_DMA(htim17, TIM_CHANNEL_1, (uint32_t*)input_capture0, 2) != HAL_OK)
Error_Handler();
}
static float compute_frequency(uint16_t input_capture[]) {
/*
* Typical worst case scenarios:
* T1: 0xFFFF - T0: 0x0
* T1: 0x0 - T0: 0xFFFF
* T1: 0x7FFF - T0: 0x7FFF
* T1: 0x0 - T0: 0x0
*/
if(input_capture[1] > input_capture[0]) {
return (float) 1/((input_capture[1] - input_capture[0])*0.0001f);
} else if(input_capture[1] < input_capture[0]) {
return (float) 1/((input_capture[1] + 0xFFFF - input_capture[0])*0.0001f);
} else if(input_capture[1] == 0x7FFF && input_capture[0] == 0x7FFF){
return (float) 1/(0xFFFF*0.0001f);
} else {
return 0;
}
}
float STM32_PLC_Input_Capture_Get(uint8_t i) {
if(i == 0)
return compute_frequency((uint16_t*)input_capture0);
else
return compute_frequency((uint16_t*)input_capture1);
}
2021-08-07 03:11 PM
Is it totaly normal that I getting a number 65535 if I connect 3.3V to encoder plus? And I get only value 1 if I connect it to encoder minus.
If I not connect anything, I get the value 0. Why? I thougth encoder till remember the value.
Edit:
Now it's working!
static TIM_HandleTypeDef* tim4_handle;
static TIM_HandleTypeDef* tim19_handle;
static uint16_t encoder_pulses_per_revolution[2] = {0};
static int16_t encoder[2] = {0};
void STM32_PLC_Start_Encoder(TIM_HandleTypeDef* htim4, TIM_HandleTypeDef* htim19) {
/* Encoder - Prescaler does not effect encoder */
if(HAL_TIM_Encoder_Start(htim4, TIM_CHANNEL_ALL) != HAL_OK)
Error_Handler();
if(HAL_TIM_Encoder_Start(htim19, TIM_CHANNEL_ALL) != HAL_OK)
Error_Handler();
/* Save */
tim4_handle = htim4;
tim19_handle = htim19;
}
float STM32_PLC_Encoder_Get(uint8_t i) {
/* Safety */
if(encoder_pulses_per_revolution[i] == 0)
encoder_pulses_per_revolution[i] = 1;
float pulses = (float)encoder_pulses_per_revolution[i];
return ((float)STM32_PLC_Encoder_Get_Raw(i))/pulses;
}
int16_t STM32_PLC_Encoder_Get_Raw(uint8_t i) {
if(i == 0)
encoder[i] += __HAL_TIM_GET_COUNTER(tim4_handle);
else
encoder[i] += __HAL_TIM_GET_COUNTER(tim19_handle);
return encoder[i];
}
void STM32_PLC_Encoder_Set_Pulses_Per_Revolutions(uint8_t i, uint16_t pulses_per_revolution) {
encoder_pulses_per_revolution[i] = pulses_per_revolution;
}