Capacitive Rotary Encoder

I am working on a compressed air engine in which I am controlling the intake and exhaust with solenoids triggered by the arduino.

I have been using a hall effect sensor and a magnet placed on a pulley, but I have been getting some inaccuracies. The code attempts to predict the next revolution, and any fluctuations in the rpm seem to affect the timing negatively.

I have been researching encoders to index the top dead center as well as count the revolution to accurately trigger the solenoids.

I came across this capacitive encoder on digikey ( http://products.cui.com/getpdf.aspx?fileID=3427 ) and I'm curious if anyone has tried it. This seems like the perfect tool for my issues vs the alternatives.

If this does not work, any suggestions on a good optical encoder with built in codewheel?

Thanks to this forum, and many you for helping me get to the point I have.

I am using 2 of these encoders on a telescope project, and they work really great for what I am doing with them. I have not tested them up to the speeds in the specs, but for me, they are much smoother than optical and mechanical ones I tried. I also like it that they provide multiple size adapters. For the price, it may be worth a try, but read the specs first and go to there website http://www.amtencoder.com/ if you haven't already done so.

Hope this helps!

aceisback:
I am using 2 of these encoders on a telescope project, and they work really great for what I am doing with them. I have not tested them up to the speeds in the specs, but for me, they are much smoother than optical and mechanical ones I tried. I also like it that they provide multiple size adapters. For the price, it may be worth a try, but read the specs first and go to there website http://www.amtencoder.com/ if you haven't already done so.

Hope this helps!

Thanks for info. Definitely helpful to know someone has tried it. Since I have not used an encoder before, I assume the two legs go into interrupt 1 and 2? What about the index? Can you post the part of your code in which you implemented the encoders?

Thanks

Have you tried a gear tooth hall effect sensor and a metal gear? Alternatively, you could use an IR optical sensor (side view), with alternating black/white painted stripes on the pulley. Either way you would get a pulse for every division; you could couple that with your current hall effect sensor, or add a separate IR sensor tripped by an index stripe (or hole).

I am using this code which is from the link provided in the code. This code worked the best for me and uses no interrupts. Just need to pay attention to the serial baud rate when using the serial monitor. I did not use the index, so I don't much about it. If you are using only one encoder, this code works great. I chopped it up quite a bit because I am using two encoders, and both had to be read pretty much simultaneously in order to maintain the ability to accurately read the encoders. I didn't use the button read either, so I removed all the button read code.

// Example 11.2
// rotary encoder demonstration
// http://tronixstuff.com/tutorials > Chapter 11
//
// Uses code from Sparkfun website, no author or licensing information
// from: http://bit.ly/a9OH2x
//
// Connect the middle pin of the three to ground, and also one of the pair on the other side
// The outside two pins of the three are connected to digital pins 2 and 4
// The other button pin is connected to digital pin 3
int dpInEncoderA=9;
int dpInEncoderB=10;
int dpInEncoderPress=3;
static void _ResetPins()
{
// Rotary encoder input lines
// Configure as input, turn on pullup resistors
pinMode(dpInEncoderA, INPUT);
digitalWrite(dpInEncoderA, HIGH);
pinMode(dpInEncoderB, INPUT);
digitalWrite(dpInEncoderB, HIGH);
pinMode(dpInEncoderPress, INPUT);
digitalWrite(dpInEncoderPress, HIGH);
}
void _lowlevel_ReadEncoder(int &rotate, int& press)
{
rotate = (digitalRead(dpInEncoderB) * 2) + digitalRead(dpInEncoderA);
press = digitalRead(dpInEncoderPress);
}
void ReadEncoder()
{
int Position, Press;
int isForward = 0;
int value = 0;
int value2 = 0;
_ResetPins();
Serial.println("Reading the encoder... press a key to abort.");
_lowlevel_ReadEncoder(Position, Press);
while (!Serial.available())
{
int Position2, Press2;
do
{
_lowlevel_ReadEncoder(Position2, Press2);
} while ((Position2 == Position) && (Press2 == Press));
if (Position2 != Position)
{
// "Forward" is shown by the position going from (0 to 1) or (1 to 3)
// or (3 to 2) or (2 to 0). Anything else indicates that the user is
// turning the device the other way. Remember: this is Gray code, not
// binary.
int isFwd = ((Position == 0) && (Position2 == 1)) ||
((Position == 1) && (Position2 == 3)) ||
((Position == 3) && (Position2 == 2)) ||
((Position == 2) && (Position2 == 0));
if (isFwd) {
  value=value + 1;
}
else {
  value=value - 1;
}

//Serial.println(isFwd ? "FWD " : "BWD ");
value2 = value/4;
Serial.println(value2);
}
if (Press2 != Press)
{
Serial.println(Press ? "Press " : "Release ");
}
Position = Position2;
Press = Press2;
}
}
void setup()
{
// configure the pins
_ResetPins();
// init serial communication
Serial.begin(115200);
Serial.println("Ready to begin");
}
void loop()
{
ReadEncoder();
}

cr0sh:
Have you tried a gear tooth hall effect sensor and a metal gear? Alternatively, you could use an IR optical sensor (side view), with alternating black/white painted stripes on the pulley. Either way you would get a pulse for every division; you could couple that with your current hall effect sensor, or add a separate IR sensor tripped by an index stripe (or hole).

I have researched all the above, but I am trying to avoid more "engineering". If I can have something that works out of the box, will be happy. I am not interested in finding a sensor, and then having to create or piece together a gear to be read. If there's a kit that I don't know about, please let me know!

aceisback:
I am using this code which is from the link provided in the code. This code worked the best for me and uses no interrupts. Just need to pay attention to the serial baud rate when using the serial monitor. I did not use the index, so I don't much about it. If you are using only one encoder, this code works great. I chopped it up quite a bit because I am using two encoders, and both had to be read pretty much simultaneously in order to maintain the ability to accurately read the encoders. I didn't use the button read either, so I removed all the button read code.

// Example 11.2

// rotary encoder demonstration
// Arduino Tutorials | tronixstuff.com > Chapter 11
//
// Uses code from Sparkfun website, no author or licensing information
// from: http://bit.ly/a9OH2x
//
// Connect the middle pin of the three to ground, and also one of the pair on the other side
// The outside two pins of the three are connected to digital pins 2 and 4
// The other button pin is connected to digital pin 3
int dpInEncoderA=9;
int dpInEncoderB=10;
int dpInEncoderPress=3;
static void _ResetPins()
{
// Rotary encoder input lines
// Configure as input, turn on pullup resistors
pinMode(dpInEncoderA, INPUT);
digitalWrite(dpInEncoderA, HIGH);
pinMode(dpInEncoderB, INPUT);
digitalWrite(dpInEncoderB, HIGH);
pinMode(dpInEncoderPress, INPUT);
digitalWrite(dpInEncoderPress, HIGH);
}
void _lowlevel_ReadEncoder(int &rotate, int& press)
{
rotate = (digitalRead(dpInEncoderB) * 2) + digitalRead(dpInEncoderA);
press = digitalRead(dpInEncoderPress);
}
void ReadEncoder()
{
int Position, Press;
int isForward = 0;
int value = 0;
int value2 = 0;
_ResetPins();
Serial.println("Reading the encoder... press a key to abort.");
_lowlevel_ReadEncoder(Position, Press);
while (!Serial.available())
{
int Position2, Press2;
do
{
_lowlevel_ReadEncoder(Position2, Press2);
} while ((Position2 == Position) && (Press2 == Press));
if (Position2 != Position)
{
// "Forward" is shown by the position going from (0 to 1) or (1 to 3)
// or (3 to 2) or (2 to 0). Anything else indicates that the user is
// turning the device the other way. Remember: this is Gray code, not
// binary.
int isFwd = ((Position == 0) && (Position2 == 1)) ||
((Position == 1) && (Position2 == 3)) ||
((Position == 3) && (Position2 == 2)) ||
((Position == 2) && (Position2 == 0));
if (isFwd) {
  value=value + 1;
}
else {
  value=value - 1;
}

//Serial.println(isFwd ? "FWD " : "BWD ");
value2 = value/4;
Serial.println(value2);
}
if (Press2 != Press)
{
Serial.println(Press ? "Press " : "Release ");
}
Position = Position2;
Press = Press2;
}
}
void setup()
{
// configure the pins
_ResetPins();
// init serial communication
Serial.begin(115200);
Serial.println("Ready to begin");
}
void loop()
{
ReadEncoder();
}

Thanks for the tips and code. I will continue researching.

By not using an interrupt, if a pulse is triggered while the arduino is running some code, won't I miss that count?

By not using an interrupt, if a pulse is triggered while the arduino is running some code, won't I miss that count?

I guess it would depend on the code. I know what you are talking about. I had that problem trying to run code and read 2 encoders simultaneously. I did try some of the interrupt code samples, but I did not have much luck with them as they seemed to miss counts. If you look at the rotary encoder examples in the arduino playground, you can read about the differences of using one vs. two interrupts and how the counts work. I am still learning these things, but after several hours of coding and recoding, I finally managed to get what I needed actually working. I am just using the encoders to give me a visual position of where my telescope is pointing on an LCD display. Your project probably will require a little more coding than mine, so it will be interesting to see what you come up with. I used one of those encoders from a chumby (better than the regular one they sell) that you can find at various places like Sparkfun for initial testing and debugging, and then made a test rig for the AMT encoder for tweaking and modifying.

aceisback is there a location on the sensor that indicates where the index is?

For anyone interested, I moved this post to http://arduino.cc/forum/index.php/topic,55589.0.html

Thanks

I really don't know. I have not ventured into using the index pulse because it was not necessary for my project. There is some info on their website at this link:

http://www.amtencoder.com/Portals/AMT/Documents/Resources/Technical%20Documents/ASIC%20specifications.pdf

Also, the FAQ I think has some info.

Let me know if the encoder works for you though. I am very satisfied with the two I am using, and I will probably use them again if I come up with another project that uses encoders. For the price, they were definitely worth trying. I bought one just to see how well it worked and if my project was feasible.

Duane

aceisback:
I really don't know. I have not ventured into using the index pulse because it was not necessary for my project. There is some info on their website at this link:

http://www.amtencoder.com/Portals/AMT/Documents/Resources/Technical%20Documents/ASIC%20specifications.pdf

Also, the FAQ I think has some info.

Let me know if the encoder works for you though. I am very satisfied with the two I am using, and I will probably use them again if I come up with another project that uses encoders. For the price, they were definitely worth trying. I bought one just to see how well it worked and if my project was feasible.

Duane

Thanks

For anyone interested, if you follow my link to the other post, I have heard back from the company and the index is a fixed point but not marked. Its easy to find it after running a simple code though...