STM32F103C8 Fast Input Rate Counter

What are you developing?
GonzoG
Posts: 403
Joined: Wed Jan 15, 2020 11:30 am
Answers: 27
Location: Prudnik, Poland

Re: STM32F103C8 Fast Input Rate Counter

Post by GonzoG »

willywonka wrote: Tue Dec 27, 2022 3:05 pm Currently I am still having problems with the encoder, but that is probably due to hardware issues, either the magnet is not properly positioned or the resolution of the encoder is not high enough. I have tested two As5600 that work differently well. It reliably detects full rotations, but for example it has problems with half a rotation, then it suddenly lacks values or it has too many (+-20).
Maybe I need to create a lookup table, since the encoder read errors are pretty constant.
Looks like you have wrong magnets.
Magnets that usually come with AS5600 are wrong type. Almost all easily available cylindrical magnets are axially magnetized but for magnetic encoders you need diametrically magnetized one.
willywonka
Posts: 14
Joined: Wed Dec 21, 2022 11:28 am

Re: STM32F103C8 Fast Input Rate Counter

Post by willywonka »

Im pretty sure the magnets are fine, if they were not diametrically magnetised they would not work at all ? Those are the magnets I’m using
https://amzn.eu/d/4KhNtYf
dannyf
Posts: 447
Joined: Sat Jul 04, 2020 7:46 pm

Re: STM32F103C8 Fast Input Rate Counter

Post by dannyf »

40,000-80,000 inputs per second if that is possible.
this can be dicy: each interrupt has an overhead of 20-30 ticks, and your processing will likely take another 30-40 ticks, for a total of 70 ticks.

that means you are spending 70 ticks * 80K = 6M ticks per second servicing the interrupts alone. you may want to run the mcu at 10x of that, or >60Mhz .

an easier way is to route the pulses to a timer input pin and count on the pulses there. and then periodically check the timer counter to see how fast it is changing. the pulse rate would be (CNT1 - CNT0) / Period. if your counter value changed 4,000 counts over 10ms, your pulse rate is 4K/10ms=40K pulses/second.

very low overhead.
dannyf
Posts: 447
Joined: Sat Jul 04, 2020 7:46 pm

Re: STM32F103C8 Fast Input Rate Counter

Post by dannyf »

here is what I did to implement the idea mentioned above - on a different target but the gist should be the same

1. i configured a timer (TIMER5 in my case) to take input on a pulse train.
2. in the loop(), I periodically (=0.5sec) check the reading of that timer to calculate how many pulses have elapsed since the last read.

from that, I can calculate the pulse rate.

the code to calculate #2 is as follows:

Code: Select all

//read tmr5 counter
//returns the number of inpuse pulses between two consecutive reads / invokation
uint32_t pcGet(void) {
	uint16_t tmp, tmp0;
	static uint16_t _tmr5;				//previous reading of tmr5
	
	tmp = _tmr5;						//save the last tmr value
	_tmr5 = TMR5;						//save the current tmr value
	tmp0=_tmr5 - tmp;
	
	return (uint32_t) tmp0 * 2;			//prescaler is 2:1
}
for debugging, I used another timer to generate a pulse train at a known frequency (80000 in my case). At a half second interval, I should be expecting 40,000 counts from pcGet().

here is the output:

Code: Select all

F_PHB= 0,004,000,000   ticks= 0,008,022,692   tmp0 = 0,000,000,002   PR2  = 0,000,000,049   pcGet= 0,000,040,004   
F_PHB= 0,004,000,000   ticks= 0,012,023,092   tmp0 = 0,000,000,002   PR2  = 0,000,000,049   pcGet= 0,000,040,004   
F_PHB= 0,004,000,000   ticks= 0,016,023,492   tmp0 = 0,000,000,002   PR2  = 0,000,000,049   pcGet= 0,000,040,004   
F_PHB= 0,004,000,000   ticks= 0,020,023,892   tmp0 = 0,000,000,002   PR2  = 0,000,000,049   pcGet= 0,000,040,004   
F_PHB= 0,004,000,000   ticks= 0,024,023,492   tmp0 = 0,000,000,004   PR2  = 0,000,000,049   pcGet= 0,000,039,990   
F_PHB= 0,004,000,000   ticks= 0,028,023,892   tmp0 = 0,000,000,002   PR2  = 0,000,000,049   pcGet= 0,000,040,010   
F_PHB= 0,004,000,000   ticks= 0,032,023,492   tmp0 = 0,000,000,004   PR2  = 0,000,000,049   pcGet= 0,000,039,990   
F_PHB= 0,004,000,000   ticks= 0,036,023,892   tmp0 = 0,000,000,002   PR2  = 0,000,000,049   pcGet= 0,000,040,010   
F_PHB= 0,004,000,000   ticks= 0,040,023,492   tmp0 = 0,000,000,004   PR2  = 0,000,000,049   pcGet= 0,000,039,990   
F_PHB= 0,004,000,000   ticks= 0,044,023,892   tmp0 = 0,000,000,002   PR2  = 0,000,000,049   pcGet= 0,000,040,010   
F_PHB= 0,004,000,000   ticks= 0,048,023,492   tmp0 = 0,000,000,004   PR2  = 0,000,000,049   pcGet= 0,000,039,990   
F_PHB= 0,004,000,000   ticks= 0,052,023,892   tmp0 = 0,000,000,002   PR2  = 0,000,000,049   pcGet= 0,000,040,010   
F_PHB= 0,004,000,000   ticks= 0,056,023,492   tmp0 = 0,000,000,004   PR2  = 0,000,000,049   pcGet= 0,000,039,990   
F_PHB= 0,004,000,000   ticks= 0,060,023,892   tmp0 = 0,000,000,002   PR2  = 0,000,000,049   pcGet= 0,000,040,010   
F_PHB= 0,004,000,000   ticks= 0,064,023,492   tmp0 = 0,000,000,004   PR2  = 0,000,000,049   pcGet= 0,000,039,990   
F_PHB= 0,004,000,000   ticks= 0,068,023,892   tmp0 = 0,000,000,002   PR2  = 0,000,000,049   pcGet= 0,000,040,010   
F_PHB= 0,004,000,000   ticks= 0,072,023,492   tmp0 = 0,000,000,004   PR2  = 0,000,000,049   pcGet= 0,000,039,990   
F_PHB= 0,004,000,000   ticks= 0,076,023,892   tmp0 = 0,000,000,002   PR2  = 0,000,000,049   pcGet= 0,000,040,010  
the jitter is caused by interrupts happening during the loop execution.

the pulse rate I'm running at is F_PHB / (PR2 + 1) = 80K. so at 0.5s intervals, I should be getting 40K, vs. 39.99 - 40.01K.

the code can count upto Mhz range, depending on the mcu's clock rate - it is basically a crude frequency meter. you can enhance it by measurign the gate time and to handle the overflow - so you can measure a wide input frequency range.
Post Reply

Return to “Projects”