cancel
Showing results for 
Search instead for 
Did you mean: 

Weird behavior of timer after setting CNT register to 0 after specific time

Sarim-Jalil
Associate II

Hi,

I have background knowledge of programming and MCUs but I am fairly new to the STM32 ecosystem. I am trying to measure the RPM of a motor using an optical encoder that gives pulses on the output. I have done this on Arduino using the interrupts and I know that the encoder works well. My application requires me to do it with STM32F030C8T6. I have taken the approach of using two timers for this purpose. I am using TIM3 of this MCU in Encoder mode and TIM14 to generate an interrupt after every 100ms to read the CNT register of TIM3 and then reset it to 0 so that next time I can get the number of pulses. I am sending the number of pulses through a serial to a laptop. Everything is fine until I set the CNT register to zero. The counter increments correctly in increasing order, an interrupt is generated after every 100 ms, and data is sent to serial. but I need to set the CNT to zero to get the number of pulses in 100ms not the incremented value every time. When I set the CNT to 0 as shown in the serial terminal below for some time I get the correct value which is "20" but other times I get 16,17,18 or sometimes under 10. I have attached the SS of the code.

1 ACCEPTED SOLUTION

Accepted Solutions
TDK
Guru

> I was able to make it work with my current approach by using the input filter value of 10 on both channels.

To me that suggests the signal is rather noisy. I would make your own assessment of the direction via the CNT register rather than relying on DIR.

DIR is calculated on any transition, prior to application of the filter. If you have jitter, DIR won't give you what you want.

If you feel a post has answered your question, please click "Accept as Solution".

View solution in original post

4 REPLIES 4
TDK
Guru

Setting it to zero could be missing pulses between when you read it and set it to zero. You should measure pulses by looking at the difference in values between successive reads, instead of setting it to zero. Yes, you'll need to handle the overflow condition but that's very doable.

Also be aware this approach is subject to delays in IRQ execution, which should be super minimal, but could be significant if you have other higher priority interrupts going on. You could use DMA instead to get around this.

If you feel a post has answered your question, please click "Accept as Solution".
Sarim-Jalil
Associate II

Sorry for replying late, I was busy debugging the problem over the weekend and unfortunately, I didn't receive an email about your reply to the post. 

I was able to make it work with my current approach by using the input filter value of 10 on both channels. It works (with slight fluctuations of +-1 RPM) but Yes I think you are right it can miss some cycles at higher speeds. I will try your approach today and will get back to you. 

Sarim-Jalil
Associate II

So I did the testing and for my application the results are same from both the approaches, though max RPM that I would be measuring would be 120RPM which is quite low to miss pulses. I issue though I am facing is, I am also reading the DIR register of TIM3->CR1 and it seems to fluctuate. The timer is in encoder mode so according to datasheet the register is in read mode only and I am reading it to decide the direction of the pump. It gives the right direction some time (i.e 0 for upward counting and 1 for downward counting) then in between it throws the opposite direction for two three values as shown in SS.

TDK
Guru

> I was able to make it work with my current approach by using the input filter value of 10 on both channels.

To me that suggests the signal is rather noisy. I would make your own assessment of the direction via the CNT register rather than relying on DIR.

DIR is calculated on any transition, prior to application of the filter. If you have jitter, DIR won't give you what you want.

If you feel a post has answered your question, please click "Accept as Solution".