## TINY3217 Quadrature Encoder Speed Calculation

13 posts / 0 new
Author
Message

Dear AVR Users,

this is my first post in this forum, so please be patient :)

I`m currently working on a quadrature encoder with a tiny3217. The decoding is done exactly the same way as the application note AN2434 describes.

And this is working just fine. But now I wanted to calculate the Rotationspeed with this formula, which I`ve got from one of my control technology books:

RPM = (((N2-N1)/N)*(fclk/(T2-T1)))*60

The problem now is that I have to get the time between the first and the last edge of the count signal (T2-T1) in a given time interval (1/fclk). The time interval is generated by the RTC, because TCA and both TCB are used for the decoding.

The count pulses have a max. frequency of 2MHz. So interrupt driven is not an option.

I thought I could use TCD and its capture function. So TCD could write its countervalue on any edge which comes from the Eventsystem into the corresponding capture register and after the time interval I can read the capture registers and get the timer value of the last edge.

But the datasheet tells me that the capture registers are not updated if the high Byte of the last value wasn`t read.

Does anybody know a workaroud for this problem or has another idea how this problem could be faced?

Thanks in advance and stay healthy!

Greetings

Studi_HS

Just a college student who is interested in AVR development.

The approach seems somewhat wrong

You shouldn't have to divide, over & over, or at all, depending on what you need.

If you can sample the count value at a known rate (such as a timer irq, say every ms)  then the difference is essentially the speed and you can use that to do many things (such as comparing two speeds, looking at accelerations, matching a a setpoint, etc).

The only time you need division is to display an actual value & that will be rare & at a very slow rate.  And you would use multiplication anyhow, since multiplying by a reciprocal is faster than division.

The problem now is that I have to get the time between the first and the last edge of the count signal (T2-T1) in a given time interval (1/fclk).

Again, you can use a timer to look at you encoder position values

say at t=0 you have an encoder position count of 234

10 ms later you have an encoder position count of 348  the unscaled avg "speed" is thus 114 & you can use it for any purpose needed.

If you want to show RPM, you just need to multiply by some constant that scales to the counts/rotation & the 10ms timebase--and you do that only when you need to display, not all the time.

When in the dark remember-the future looks brighter than ever.   I look forward to being able to predict the future!

Last Edited: Sat. May 1, 2021 - 04:36 PM

Welcome to AVRFreaks!

studi_hs wrote:

But the datasheet tells me that the capture registers are not updated if the high Byte of the last value wasn`t read.

So what is the problem, just read the whole data capture register???  You should not be reading the individual H/L registers (I'm assuming your using C or C++) the compiler knows how to properly read a multi-byte register.

Jim

(Possum Lodge oath) Quando omni flunkus, moritati.

"I thought growing old would take longer"

You are right.

But my book tells me that the resolution at lower RPM would be better by measuring the time difference between two consecutively edges.

This formula uses "both" methodes at once so you get the better resolution.

This is the idea behind this formula.

Just a college student who is interested in AVR development.

Last Edited: Sat. May 1, 2021 - 04:51 PM

Thanks for the welcoming :)

The problem is that the register would be updated at a rate of 2MHz and i wanted to give this task to the hardware so the CPU hast time to do other things and doesnt need to read this register all the time.

Just a college student who is interested in AVR development.

But my book tells me that the resolution at lower RPM would be better by measuring the time difference between two consecutively edges.

Forget about the book....you either see how many encoder counts you get per some amount of time (say 10ms, 100ms, whatever)....a longer time base allows an inherent averaged result (often desirable).

Or, you measure precisely how long it takes between counts.  If you count 2 drops of water in 1 sec  (vs perhaps 1 drop or 3 drops)   vs time between 2 drops measured at 1.063343 sec, you can see measuring the time exactly gives a lower variance result.  However, counting over a long enough time to get significant counts is often better (due to avg), and easier.   If the rotation grinds to a creepy-crawl, then yes, you'd need to measure time instead of counts.

Are you in a big hurry to update display....how about 5 times per second?   This is extremely similar to a freq counter.

When in the dark remember-the future looks brighter than ever.   I look forward to being able to predict the future!

Incidentally, I think 2MHz is beastly fast for a quadrature encoder on an AVR.  For that kind of speed you might consider a more expensive processor, or a dedicated FPGA or CPLD.  S.

Yes this seams a little bit fast, but the application note says they`ve experimentally found out that 2.5MHz are possible.

I`ve tested it with 2MHz from my function generator and anything is working just fine. So there`s no problem :)

Just a college student who is interested in AVR development.

The problem is that the tiny is part of a control loop and I need a refresh rate of 4kHz... So it isn`t possible to wait a longer time and average the result.

And yes you are correct the rotation speed can be anywhere between zero and approximately 2MHz quadrature pulses... So measuring the time between two counts without sourcing this out in hardware is still a big problem due to the high frequency.

I`ve taken another look at the datasheet and it tells me that the capture registers are buffered. I hope that the buffer register is rewritten anytime an event occurs and isn`t protected like the capture register. In this case I only have to read the register twice and get the correct time value.

Does anyone know if the buffer has the same protection feature? Otherwise I`ll just try it myself.

Just a college student who is interested in AVR development.

Yes, it's quite possible that it can successfully count at 2.5MHz.  But that's the whole AVR running absolutely flat-out - and now you want to retrieve data from counters and process it?  And do division on a CPU that doesn't have a divider?

There's more problems than that.  How much velocity resolution do you want?  Assuming anything below 1Hz is treated as 'stationary' and 2MHz is treated as 'full speed', that's a 1:2-million ratio.  How many steps in there are you expecting?  Given that an AVR is generally an 8-bit device, that would be 256 steps, or 7.8kHz per step...  Even at 16 bits, you are still looking at 30Hz steps, and the processing time for that will be awhile.

And wait a minute - if your refresh rate is only 4kHz, you have plenty of time!  Just how quickly does the velocity change here?  Yes, this is important.

4,000 Hz is about 250 microseconds each.  That gives you plenty of time to average out and update - but not if you're also counting flat-out at the same time!  AVRs only have one core.  It's not going to do two things at once.

Here's a suggestion:  Use two AVRs.  Have one count, the other can potter about calculating the velocity, from the same input signals.  S.

eta:  "Flat-out" is an American expression meaning "go as fast as you can while not caring about anything else".  This sort of speed may indeed be possible in an AVR, but when you start to put in other concerns like "Oh, and I have to put it into this memory" or "and out on these pins" or "and then use it in this calculation"...  That's not counted in going 'flat-out' but is a concern in a real-life application.

Last Edited: Sun. May 2, 2021 - 10:05 AM

> part of a control loop and I need a refresh rate of 4kHz

>rotation speed can be anywhere between zero and approximately 2MHz quadrature pulses

Not sure how that all works out and maybe being off by up to 500 counts in each loop is ok. In any case the rtc has ext input with a restriction of it being <=4x cpu speed, so could use it to count (CNT) even though you do not have direction info (directly).

Probably different ways to use it, but simply letting it count one of the encoders (option to div2 in rtc) up to max (16bit) would get you 32ms (or 65ms if div2) of time before overflow. Use overflow irq to get to 24/32bits and you could check its value every 125ms (1/8 sec) to make division easy later, or simply check more often to keep in the 16bit range. There is probably some combo of div/read rate that makes rpm easy to calculate. You already have an irq for direction change it seems so could make note of the rtc value when that takes place. The rtc then becomes the rpm counter.

and I need a refresh rate of 4kHz

Have you thoroughly looked at that?   Is this for high-speed positioning?   By refresh...do you mean new calculations (probably), or resending whatever the latest happens to be?

For example, you could measure temperature 5 times a second, but send it out 300 times a second---some people will say the reading is being refreshed at 300Hz, others will say 5Hz.

At very slow speeds, how will you possibly give 4000 new readings a second...you might barely have any pulses for several ms  (what is your lowest possible pulse rate).

Maybe you can use a freq to volt circuit & use the ADC to report the speed...not sure what this particular chip limits are, but there are many such chips:

https://www.ti.com/lit/ds/symlin...

At your fastest speed (2Mpulses/sec) you will get 500 pulses  4000 times per sec.   ...if you simply use a counter and IRQ sample & reset it @ 4KHz you will have about 1/5% ercent resolution...as you move slower the counts & resolution fall.

Below 400000 pps, your count will fall to 100max (@4KHz), which is about 1 % tolerance,,,so below that, you prob want to switch over to measure time between pulses.

When in the dark remember-the future looks brighter than ever.   I look forward to being able to predict the future!

Last Edited: Sun. May 2, 2021 - 10:33 PM

To get the speed of a spinning shaft with an encoder attached, take one of the encoder signals and count the number of rising edges detected in a millisecond.  Then divide that by the number of holes in the encoder disk.

-quote|The count pulses have a max. frequency of 2MHz. So interrupt driven is not an option.  :  I'm going to assume that the 2MHz is the pre-scaled speed at which the timer/counter value is being incremented by the CPU , and not the number of times per second that the shaft is rotating.  So a shaft that is rotating 10000 times a second will get a count of 200 for each rotation  (if is one hole in encoder disk).

Interrupt driven response is always an option.  But a Cortex M4 200MHz 32-bit CPU module board (that sells for \$3 on eBay) will need to be used instead of an AVR (which sells for \$3 on digiKey).

Discard the formulas.  Microprocessors were invented by people who like math; microcontrollers were invented by people who don't.