Encoder library missing pulses

Status
Not open for further replies.
I just got a reply back from CUI:

Will, the AMT102 does not output in gray code. It outputs in TTL voltage square wave on the 2 channels. Let me know if you need anything else.

Best Regards,

Ryan Smoot
Technical Support Engineer
CUI Inc
 
If you want to call 2-bit gray code, gray code, fine. 2-bit gray code is exactly the same as 2-bit binary. There is no difference.

Well, actually there is quite a difference.

graycode.jpg

Gray code is exactly the same as digital quadrature waveforms. Binary counting is not.


Do you know of a documented example where a 16mHz board has actually driven a motor at 300RPM and counted pulses from a quadrature encoder at 2048ppr?

No. The Encoder library has only been tested stand-alone.

Like all interrupt-based libraries, Encoder can be impacted by interrupt latency from other code. If that other code disables interrupts for too long, Encoder will miss the signal changes.

Have you tested your encoders with the Encoder library without any other libraries or code that might be disabling interrupts for too long?
 
I wonder if Ryan can answer whether the two TTL voltage square waves are in phase, or have a quadrature (90 degree) or other phase relationship?
 
From AMT10X datasheet:

incremental output signals: Quadrature A/B and X index
output phase difference: 90° (B ch leads A ch in CW direction viewed from front)
incremental output waveform: TTL voltage square wave
square wave duty cycle: 50%
 
Will, can I talk you into testing this encoder without the motor or other stuff, using only the Encoder library?

If not, not worries. But please let me know either way. If you will not, I'll buy one from Digikey today and do test it next week.
 
I can send you his email address if you'd like to ask him.

You have the code I tested it with. It is pretty bare bones. If you compare what the encoder library is returning with direct port reads, you can easily see the difference.

The fact is, that part is working with my routines. I don't need to debate it further. My problem is that if I go with the Teensy, I have to carry excess inventory, assembly costs and have more components to potentially fail. Or, I can just slap a quadrature decoder IC on each line and use the ATega. Again, same problem.

I hear a lot of noise online about how fast the ATmega board will read encoder pulses but no empirical evidence from someone who has ever tried it with anything other than... knobs.
 
Last edited:
I did test it by hand turning. I went through every step you outlined in your original post. Nothing worked correctly with encoder.h.

Please don't buy an AMT102 encoder. I don't plan to use them. I need something smaller. I just bought one to see if it made a difference when I couldn't read the pulses on the ATmega. The AMT102 was tested with a quadrature decoder; the E4P was not.

If you have recommendations for an encoder you have tested, please let me know.
 

Attachments

  • EncoderTestResultsByHand.txt
    3.6 KB · Views: 229
Last edited:
I can send you his email address if you'd like to ask him.

I'm pretty sure this "what is gray code" discussion has run its course. Obviously Ryan just quoted the words right from the datasheet. It doesn't say "grey code" in the datasheet, so he answered "no", but obviously gray code and 2 quadrature square waves are the same thing, even if Ryan isn't aware of that fact.

You have the code I tested it with. It is pretty bare bones. If you compare what the encoder library is returning with direct port reads, you can easily see the difference.

That code used another library and did several other things. I commented out the stuff associated with the motor library.

When I did run your code, sans the motor stuff, I saw the different with the encoder knob here. The pulse counting gave wrong results, while the Encoder library was clearly correct.

The fact is, that part is working with my routines.

If you're happy with the results, then I guess it's not a problem for you. If it's working for your application, then great.

But if there's a discrepancy between those results and the Encoder library, then I have more work to do.

I hear a lot of noise online about how fast the ATmega board will read encoder pulses but no empirical evidence from someone who has ever tried it with anything other than... knobs.

Did you not see the section of the Encoder library page where it was tested with synthesized waveforms?

I have placed an order with Digikey for one AMT102-V Kit. With the upcoming holiday, I expect it will arrive near the end of next week.

I will test this exact encoder with the Encoder library. My first tests will involve simply turning carefully measured numbers of degrees and reading the Encoder value. If that works, I'll rig up a motor to turn it at a few hundred RPM. My intention is to verify the Encoder library, but not to develop a motion control application.
 
I just got a reply from Chris Dillman at Digikey saying also that the AMT102 encoder is not a gray code encoder. This fact was also confirmed by Chris (x1952) at Digikey and by the product manager for that line, whose name I don't have.

You guys can call it grey code if you like but the fact is that calling 2-bit gray code gray code is like calling a mule an equine. Technically, yes. But he's stil a mule.

I don't know any reputable commercial rotary encoder supplier who would sell that as gray code. Maybe the hobby stores do. I don't know. Don't buy from them.

If you have further questions about that I would take it up with them.
 
Last edited:
Please don't buy an AMT102 encoder. I don't plan to use them. I need something smaller. I just bought one to see if it made a difference when I couldn't read the pulses on the ATmega. The AMT102 was tested with a quadrature decoder; the E4P was not.

It's too late. I completed the purchase while you were writing this message. It's not terribly expensive, and I really do intend to investigate this issue.
 
Paul, I appreciate your willingness to go the extra mile to try to resolve this. My biggest concern right now is voltage. Back to my original questions:

1. Are there any plans to make the teensy pins 5v tolerant?

2. Do you know of a high-resolution quadrature encoder that will operate off 3.3v?
 
The new wave of microprocessors are generally low voltage, 3.6 and lower, some have 5V
tolerant inputs, but they remain 3.6 or lower devices. Thats the way evolution goes.

The encoders linked in the OP works with a 3.6 V supply according to the datasheet
so that should work well with the Teensy 3.

As others have stated, quadrature encoding is the same as 2 bit Grey code.

Regards
Magnus
 
As others have stated, quadrature encoding is the same as 2 bit Grey code.

Regards
Magnus

So, I suppose two engineers at CUI, a tech rep at Digikey and the product manager for the CUI encoder line at Digikey must be wrong, huh? Wow. You guys should go into the encoder business. If you tried to pass off a 2-bit quadrature encoder off as a grey-code encoder in the industrial world, they would laugh you out of the building.

I believe we're debating semantics and industry cross-speak, gentlemen. Let's put it to rest, shall we.

The new wave of processors may work in the toy market but they'll never fly in the industrial world. If I were building a board like this, that would be my target market. Most of the industrial PLC's look for 24v input. Some of the smaller ones are 5v tolerant.

Paul, do you have any answers to the two questions I posed previously?
 
Last edited:
My first tests will involve simply turning carefully measured numbers of degrees and reading the Encoder value. If that works, I'll rig up a motor to turn it at a few hundred RPM. My intention is to verify the Encoder library, but not to develop a motion control application.
The lib works reliably with my Avago 5540 (500PPR, so 2000 encoder lib counts per revolution). Tested with 5000rpm.
 
Thank you for a real-life example, tni. So, you're saying you were able to process 41667 pps? With which board? Have you attempted to control the position of a motor using this setup?
 
Thank you for a real-life example, tni. So, you're saying you were able to process 41667 pps? With which board? Have you attempted to control the position of a motor using this setup?
Teensy 3, the encoder lib is using interrupts for all pins (5000rpm makes 166'000 interrupts per second). That was just a test setup, the motor driven against mechanical stops. I ended up using a motor controller with builtin quadrature decoder.
 
Which motor controller, tni? Is it working reliably for you? That's another option I could consider.
 
I did test it by hand turning. I went through every step you outlined in your original post. Nothing worked correctly with encoder.h.

Encoder certainly appears to be working, based on the results you posted on message #32. Each 1/4 turn, the M1Distance and AMT100.read() from the Encoder library are equal to the PPR setting you noted.

I would personally use simpler code for testing. Merely printing the Encoder value repetitively in a loop is much simpler and avoids any possibility of confusing results due to the two ways your code writes to the Encoder count.

This is really all that's needed:

Code:
#define encoder1PinA 2
#define encoder1PinB 3
Encoder AMT100(encoder1PinA, encoder1PinB);
void setup()
{
  Serial.begin(115200);
}
void loop()
{
  Serial.println(AMT100.read());
  delay(250);
}

I would just run this, make a note of whatever number it's printing (if not zero), then turn the shaft 1 full revolution and look over at the screen to see how the number has changed.


1. Are there any plans to make the teensy pins 5v tolerant?

Not at this time, no.

In general, nearly all new higher performance 32 bit microcontrollers run on 3.3 volts (or less) and use only 3.3 volt signals.

2. Do you know of a high-resolution quadrature encoder that will operate off 3.3v?

I have not shopped for hi-res encoders nor used one in any product I've designed, so no, I'm not familiar with nearly any specific models, no matter what their voltage or other specs.

I'll work with the CUI encoder arrives next week. In the meantime, I just can't keep pouring more time into this specific issue. I can't every every last question for things that aren't PJRC products.
 
Encoder certainly appears to be working, based on the results you posted on message #32. Each 1/4 turn, the M1Distance and AMT100.read() from the Encoder library are equal to the PPR setting you noted.

Take another look. There are no results even closely consistent with a resolution higher than 512ppr. At 2048ppr, the position was out as much as 1/8" in a quarter turn. Multiply that by 4 and you are out 1/2" in a single turn. Multiply that by 50 turns and your are off by 25". I think most people using rotary encoders in the AVR world seem to be turning knobs. I suppose that's great if you're into that sort of thing but I need precision motion control at a high resolution.

Merely printing the Encoder value repetitively in a loop is much simpler and avoids any possibility of confusing results due to the two ways your code writes to the Encoder count.

That does nothing to tell me the device's ability to control motion. It just gives me a vague idea of what the count is at a certain spot.

I can't every every last question for things that aren't PJRC products.

I believe the voltage is very specific to PRJC products. Microcontrollers may be going into the tiny-volt world but the devices that connect to them aren't. I can't justify trying to mass produce something that requires additional components to interface it with encoders that run at industry standard voltage.
 
Take another look. There are no results even closely consistent with a resolution higher than 512ppr.

Ok, I'm looking at the file again, the one attached to message #32.

I see five sections that say the encoder was set to 2048, 48, 96, 96, 48 ppr. Perhaps those last 2 are mis-labeled? The data certainly seems to be for 512 and 1024 ppr.

So, looking at the last section, I see this:

Encoder stopping...
encoder1Pos=1024
encoder1ACount=545
encoder1BCount=540
M1Distance=1024
AMT100.read()=1024
SHAFT TURNED 1/4 REVOLUTIONS

This seems to be pretty "closely consistent". The Encoder library counted 1024. Your pulse counting code saw 545 and 540 pulses. The fact they they are not equal or within 1 count should be an indication something is not perfect with those 2 counts. But assuming 545 is right, that's about 6% more than the 512 which should have occurred (your code counts both rising and falling edge, so it's 2X ppr and should ideally be half Encoder's count). Any slight backwards motion or noise on the signals could easily explain that 6% difference, since simple pulse counting always increments where true quadrature decoding accumulates the net distance.

There are plenty of other discrepancies in the file, which just don't make any sense to me. For example, in the first part for 2048 ppr tests:

Encoder stopping...
encoder1Pos=2048
encoder1ACount=1078
encoder1BCount=1076
M1Distance=2048
AMT100.read()=2048

SHAFT TURNED ~3/8 REVOLUTIONS

If the shaft actually turned 3/8 rev, the simple pulse counts should have seen 1536 rising/falling edges. Of course, the Encoder library should have counted 3072. Neither lines up with the claim the shaft turned 135 degrees. However, the simple pulse counts are very close to half Encoder's count. Again, they're slightly higher, which would be expected if the signals indicate slight reverse motion or noise causing spurious edges at any point. The data from the Encoder library and both your pulse accumulators strongly suggests the shaft did not actually turn 3/8 rev. Or if it did, the other 1/8th rev occurred after this data was printed (see below reading these methodology). Or if the motion truly was 3/8 rev, the CUI encoder sent signals that both techniques saw as indicating about 1/4 rev. I have absolutely no way of knowing what truly happened.... all I can do is look at the data you published and try to guess. Remember, you specifically asked me to review at this data again.

In nearly all your tests (except the first one), your pulse counts are slightly higher than half the Encoder library count, which is exactly the expected behavior. In the cases where Encoder does not agree with your notes about the actual motion, the simple pulse counts also do not agree, but they do track Encoder's count.

Another issue that makes me feel very uncertain about this data is way you are testing. Your code is printing numbers only when the Encoder library count reaches a threshold, and then you reset the count. This methodology is not good (aside from the fact you're using Encoder's count as the threshold, when you believe the Encoder library is faulty). If you intend to turn the shaft 90 degrees, but the actual motion is 112 degrees, your program prints one result as you pass the point where the Encoder library reports a specific count. But when you stop turning, you get no indication of the count from Encoder or your pulse accumulators. You should be printing the results continuously (as I suggested earlier). Resetting the counts is also not good. If you continue turning, positions such as 360 degrees are easy to see. If you were continuously printing the count, you could stop when the shaft is back at the starting point and note the total count for 1 rev. Then you could continue turning and note the count for 2 revs, 3 revs, and so on.

Even though I resolved not to look at this further until the CUI encoder arrives next week, yet again I've spent about 20-30 minutes looking at this and writing another detailed message. I still do not know what's really wrong here. These test results do have many inconsistencies, but their most consistent feature is the accumulators are usually slightly more than half Encoder's quadrature count, which is a pretty good indication both techniques are working as intended and the signals contain either a small amount of noise/chatter or backwards motion. This behavior seems consistent at every setting.

Somehow you're convinced the Encoder library is not working, but I can not see how you are reaching that conclusion?
 
Last edited:
Will, one thing that troubles me is you seem to be absolutely certain these microcontrollers are incapable of quadrature decoding at faster rates, in the 10000 pulses/sec range. Why do you believe this?

You're very pointedly asked me to respond to every single question, so in turn I would like to ask you to re-read and comment on the speed test (which I've brought up a few times in this lengthy thread). The speed test is on the Encoder library page. Scroll down to "Maximum Speed and CPU Usage". There's even a photo showing the test being performed.

In that test, a Teensy 2.0, which is based on a 16 MHz AVR, measures nearly all CPU time used at 127 kHz interrupt rate. Since there's 1 interrupt per count and quadrature decoding is 4 counts per pulse, that corresponds to 31750 pulses/sec. An encoder with 1024 pulses/rev would need to spin 1860 RPM to reach this limit.

Earlier, you felt a 16 MHz CPU must be too slow. Why? But by very simple math, 16 MHz divided by 127000 is about 126 CPU cycles per interrupt. Within Encoder.h, the interrupt code is 28 instructions, then 1 entry from a dispatch table of jumps, then a longest case of 5 instructions, plus 4 more at the end. The compile adds about 20-some more for the interrupt entry and exit. That's about 58 instructions. Many of those instructions take 2 cycles. It still easily adds up to less than 126 CPU cycles.

I've heard you repeatedly say "nobody has tested" fast encoders. Do you believe the speed test published on the Encoder page is invalid?

You're repeatedly asserted that these microcontrollers are incapable of tracking signals at these speeds. What do you think my analysis of the assembly language code on 16 MHz AVR?
 
You are correct in your observation that hand turning an encoder is not a reliable way of observing distance. Did the shaft turn exactly 5/16th of a turn? How can I know? I can only try to measure what it appears to be. That's why I never tested by hand turning before. I wouldn't dream of writing an encoder routine without testing it on a high-speed motor over at least a thousand iterations.

When I ran the hand test I didn't understand that your routine is counting signal changes. I was assuming it was counting pulses on channel A and using channel B for directional information. I understand why you are doing this to give a higher degree of accuracy but I have seen no documentation to that effect and most counters return a pulse count on channel A. That is why everything came out in the neighborhood of 1/4 turn.

The counts are what they are. I didn't make them up. That data is very raw. I just kept banging at it at different resolutions (and there may have certainly been repeats of the same resolution) trying to get consistent numbers. Although looking at the file, it appears my PPR notations were incorrect in a couple of places. The correct PPR number is in M1Distance.

I don't know if your library is correct or not. All I know is I have not been able to accurately control motion using it. That is not a big deal to me, as I have pointed out previously. I also know that I can get accurate counts using a quadrature decoder.

I think you are misunderstanding the precison I am after. If I turn the shaft 1000 turns and it is off by more than 3*, that is not acceptable. Pretty closely consistant is not what I need. As I pointed out, even a small discrepancy multiplied 50 fold becomes a huge discrepancy. I would like to have it the mechansim accurate to 1mm in a thousand feet if that were possible. I don't know if that is possible ouside the closed-loop servo environment but closed-loop servo does nothing for me but tell me what the motor is doing. I already know what the motor is doing--I am dirving it. I need to know what the entire mechanism is doing, which is why I chose to implement position control in this manner. It may turn out that I need both servo motors and external encoders to achieve this. The problem is, no servo motor exists that will produce the torque I need in a NEMA-17 (or smaller) footprint.

All I can say to your lab tests is try it in the real world. Things that work with o-scopes and on paper don't always work when you are attached to a motor and attempting to control the motion of that motor over thousands of iterations of different distances. I have exhaustively tested this with the ATmega board using 8 different motors across three brands, six different encoders, three different boards and five different motor controllers using at least 20 different cables. I have tried it with interrupts and without interrupts, inside tight loops, using direct port reads over tens of thousands of iterations. I believe if there was a workable solution with the ATmega chip, I would've found it by now. Add to that synchronizing the speed and position of two motors using a PID rotuine and stopping them on a dime, monitoring four limit switches, while monitoring a SPI bus in a wireless mesh network. I don't think the ATmega has a prayer at doing all that. It appears that at least the chip in the Teensy can keep up with the signal changes. I wish I were wrong. I would like nothing more than to control each motor with a pro mini. Perhaps you can prove me wrong. I hope you can.

All I can say is try it.
 
Status
Not open for further replies.
Back
Top