I want to use an encoder to find the speed of a wheel and the direction of the rotaion. I am using an incremental(quadrature) encoder. This is the piece of code I found for speed calculation.
`
float SPEED2;
static uint32_t TIM4_PreviousCount = 0;
uint32_t TIM4_CurrentCount;
int32_t TIM4_DiffCount;
TIM4_CurrentCount = __HAL_TIM_GET_COUNTER(&htim4);
/* evaluate increment of TIM4 counter from previous count */
if (__HAL_TIM_IS_TIM_COUNTING_DOWN(&htim4)){
/* check for counter underflow */
if (TIM4_CurrentCount <= TIM4_PreviousCount)
TIM4_DiffCount = TIM4_CurrentCount - TIM4_PreviousCount;
else
TIM4_DiffCount = -((TIM4_ARR_VALUE+1) - TIM4_CurrentCount) - TIM4_PreviousCount;
}
else
{
/* check for counter overflow */
if (TIM4_CurrentCount >= TIM4_PreviousCount)
TIM4_DiffCount = TIM4_CurrentCount - TIM4_PreviousCount;
else
TIM4_DiffCount = ((TIM4_ARR_VALUE+1) - TIM4_PreviousCount) + TIM4_CurrentCount;
}
TIM4_PreviousCount = TIM4_CurrentCount;
SPEED2 = (float) TIM4_DiffCount*60/(TS*TIM4_ARR_VALUE);//rpm
I know got the logic of this code tha how it calculates the speed but for the direction I dont exactly get the point. Is it true to say that when the wheel is rotating anti-clock wise the __HAL_TIM_IS_TIM_COUNTING_DOWN(&htim4)
gives us a true value and vice versa? or we need sth else to find the rotation of the speed? If we want to implement the code to find out the direction of the rotaion without using hal function for down counting what can we do?
I worked on an STM32 project like this very recently. The timer basically increments the counter when the rotation is in one direction, and decrements it when it is in the other. It also sets the "up or down" bit in the config register to indicate the direction. (Which is non-intuitive, since you don't normally read status from a config register.)
So there are two ways to know the direction:
Compare the current count value to the last count value. If it has increased, it is going one way, and if it has decreased, it has gone the other way.
Check the "up/down" bit in the timer config register.
I opted for option 1) because I was reading the current counter value anyway, so reading an additional status register seemed pointless.
Note that you have to cope with the overflow / underflow situation. The timer I used was a 16-bit timer, and I ended up with something like this:
uint16_t last_cnt = __HAL_TIM_GET_COUNTER(&htim4);
while (1)
{
uint16_t current_cnt;
current_cnt = __HAL_TIM_GET_COUNTER(&htim4);
uint16_t diff = (uint16_t)(current_cnt - last_cnt);
if (diff == 0u)
{
// No change
}
else if (diff & 0x8000u)
{
// Counter has decreased, diff is negative
}
else
{
// Counter has increased, diff is positive
}
last_cnt = current_cnt;
}
This relies on the fact that numbers are represented with 2's complement (i.e. high bit set is a negative number). This is certainly true on an STM32 (and probably any ARM core), but I don't know if C mandates it.