advice on rotary encoders at high speed

I'm looking for general guidance on rotary encoders.

I will be using this encoder:

at 600 pulses per revolution.

Currently I am using a Nano at 3.5RPM and it works fine (I may step up to an Industino after implementation), but ultimately, I will be turning it at 50RPM or 500 pulses per second.

  1. It does not seem unreasonable to use good old-fashioned digitalRead rather than "direct port manipulation" YES OR NO??

  2. I am NOT currently considering using "AttachInterrupt" either.

  3. Better suggestion on the encoder? (I'd like to stay under $100, but picked this to play with -- the resolution is actually a bit high, 100 pulse/Rev would be fine)

I can do 1 & 2 of the above, but am wondering WHY bother?

Since I'm about to spend some serious money on this project, I was wanting to hear "Pros and Cons" on rotary encoder usage from guys who may do this a little more often than I do..

Any experience or advice would be greatly appreciated!!

You better let a timer count the pulses and check the count in regular time intervals.

In the abstract, digitalRead sounds fine to catch a 500Hz signal. It depends on what else your code is doing of course. If you have something slow or blocking, interrupts will be the way to go - it's simple enough.

Can you run what you have at 50RPM and see whether the Nano can keep up?

The digitalWriteFast library is a great deal faster than the standard digitalWrite() and digitalRead() while remaining as convenient to use.

Personally I would use an interrupt to detect the encoder pulses. The code in this link is derived from a project in which I was controlling the speed of a small DC motor.

...R

I would consider using an Arduino Due - in the AT91SAM3X8E microcontroller the Timer Counter module has a quadrature decoder
there is an application note which disusses the QD
https://www.microchip.com/wwwAppNotes/AppNotes.aspx?appnote=en591367

600 pulses per revolution.

The way encoders are typically spec'd this means there are 4*600 = 2400 quadrature pulses available per revolution. You no not need to read them all, and there are algorithms for reading 1,2 or 4 of the available quadrature pulses?

What is the application, and why do you need a quadrature encoder? Are you just trying to measure the rotational speed of a motor? Do you need to determine direction or do you know the direction from the code?

THANKS TO ALL.. just a few responses (I'll still take more advice for anyone giving!

You better let a timer count the pulses and check the count in regular time intervals.

Please expand this thought.

In the abstract, digitalRead sounds fine to catch a 500Hz signal. It depends on what else your code is doing of course. If you have something slow or blocking, interrupts will be the way to go - it's simple enough.

Can you run what you have at 50RPM and see whether the Nano can keep up?

At present, I cannot actually run it at 50RPM - was hoping to get some insight as to what to expect when I actually hooked this up.. I can reduce the speed using either a chain or timing belt so that the encoder is only seeing about 10RPM.. I may also drop back to another encoder that is something more like 100 Pulse/Rev.

@Robin, Definitely gonna try that... I was trying to talk myself out of interrupts just to keep the code "simple," but it seems prudent.

@Horace.. was considering the Due based on a it having a higher processing speed.. I'm not familiar with the quadrature decoder feature .. something to look into - thank you.

there are algorithms for reading 1,2 or 4 of the available quadrature pulses?

This I definitely need to look into.. I just need to read one of the 4 pulses, TBH. It will probably not run in reverse, although, the way I have it now, it CAN and still stay in step

Are you just trying to measure the rotational speed of a motor?

...

I'm trying to determine the linear inches a chain has traveled by counting the rotations of it's drive sprocket. It this case, the sprocket is roughly has an 11" "pitch diameter," so one revolution means that the cargo ON the chain has moved 34.54" away from the sensor. The sensor will be measuring length, but my accuracy can be +/- 3-inches, so dividing the sprocket rotation into 600 "steps" gives me a theoretical resolution of > 1/8 inch --which is a bit of overkill. LOL

Do you need to determine direction or do you know the direction from the code?

I will probably need to determine the direction using the encoder, but it should not ever run in reverse, so this should never be an issue. The arduino is NOT controlling the drive motor, it just runs continuously

Hi,
Built a proof of concept project and use a battery drill to turn the encoder shaft.

50RPM is a rev every 1.2Seconds.

Tom... :slight_smile:
PS, BUILD and TRY...

+1 for 32-bit boards with optical encoders... I recently built a digital tacho-generator to provide feedback to an analog servo amp and the only way I could get the precision and response time I needed was with a Teensy and a 2500 line encoder.

As for encoders, check out a brand called Calt on amazon. I have no affiliation whatsoever with them, but have never had any issues with them. Line counts go all the way up into the thousands and they offer a variety of different outputs- open collector, push-pull, line-driven differential. That 2500 line encoder I got even has NSK bearings and was only $45

After all I wonder what "high speed" actually means. What's the expected rpm range? What's the use for the counts?

Quote
You better let a timer count the pulses and check the count in regular time intervals.

Please expand this thought.

There is a good, easy to use library which implements this method of using the timer as a counter for external pulses. Since you don't need or use the quadrature output, just counting the A or B channel pulses will be a good approach.

FreqCount.h

About freqCount.h:

I tried the example -- I attached one leg of my encoder to pin 5 and ran the example sketch. I got nothing but a repetition of "0" on the serial monitor.

Am I missing something? DO I need to tell it to "count" on pin 5? It seemed to me the web page was telling me to use pin 5 only.

I added pinMode(5, INPUT); to void setup()

still got nothing but a repetition of "0" in Serial Monitor.

My encoder was working in my previous sketch and remained "powered" the same way, so it should be sending pulses. I switched it back and ran my previous sketch and it worked fine (I switched the one leg from Pin 5 back to where I had it on Pin 3)

You have to tell the library to use the timer as a counter. Each timer has one special pin for use as its external clock, e.g. pin 5 for T1. But this pin has to be enabled as the counter clock by setting special configuration bits, that's what the library does if you tell it to do so. Then the timer can count pulses of 4MHz freqency - that's what I'd call "high speed".

Then you can examine the timer register at any time for the position reached. Eventually you have to handle counter overflows, and of course the direction of movement from the other encoder channel.

I added pinMode(5, INPUT); to void setup()

The encoder output is open collector and definitely needs a pullup resistor.

You can try pinMode(5, INPUT_PULLUP). I'm fairly certain it is enabled in the counter mode.

If not, use an external resistor of 2.2K or 4.7K as a pull up.

Perhaps you are using too big of a hammer to smash a fly.

The machines I have had that do what you are attempting use an inductive sensor to count the teeth on the gear driving the the conveyor.

Paul

You can try pinMode(5, INPUT_PULLUP).

That did the trick.. but I guess I'm uncertain how to implement that - i'm getting a reading of 635-638 off my encoder.

In my case, one rotation of my encoder would be equivalent to 28.699 linear inches (I have an item on a conveyor and am trying to measure length as it passes a photo-eye; if it took 200 pulses to pass the eye, then it would measure 9.56 inches long). 600 PulsesPerRev / 28.699 inchesPerRev = 0.0478 inchesPerPulse && 0.0478 * 200pulses = 9.56 inches long

How is FeqCount.h method "more accurate' or "more reliable" than my current method? Can you maybe walk me thru some code using the info above and implementing FreqCount.h ?

Perhaps you are using too big of a hammer to smash a fly.

That is a certainty. For this project, the encoder is 600 PPR, which gives me a accuracy to about 1/32 of an inch, when +/- 3 inches would probably do.

In your very low speed application both solutions are applicable. You have to get the pulses at the time the photo-eye is covered and when it's uncovered again. Then it doesn't make a difference whether you count the pulses by a hardware counter or in software. A hardware counter is more reliable if the pulses arrive so fast or other activities block software counting for some time.

i'm getting a reading of 635-638 off my encoder.

For 1 revolution? Please post the code that produced that.

In my case, one rotation of my encoder would be equivalent to 28.699 linear inches (I have an item on a conveyor and am trying to measure length as it passes a photo-eye; if it took 200 pulses to pass the eye, then it would measure 9.56 inches long). 600 PulsesPerRev / 28.699 inchesPerRev = 0.0478 inchesPerPulse && 0.0478 * 200pulses = 9.56 inches long

i'm getting a reading of 635-638 off my encoder.

If you are using the library example with a one second gate time, you are seeing 635-638 pulses in one second.

Because the library uses Timer2 to gate the interval, I'm not clear how to get the interval to start and stop with with the object sensor. You can certainly manipulate the timer/counter without the library, but there is a work around with the library as it stands with the fixed gate interval.

First, calculate the belt speed
636/600 = 1.06 rev/second = 1.06*28.699 = 30.421 inches/second

Now you need the time that the object blocks the sensor. For example, if the sensor is blocked for 250 ms as the object goes by, then you know that the object is 7.61 inches long.

The object size is independent of the time or belt speed.