Go Down

Topic: Rotary Encoder Library (Read 13324 times) previous topic - next topic

Jul 01, 2013, 01:16 am Last Edit: Jul 11, 2013, 10:43 pm by frodofski Reason: 1
Hey Guys,

So the project I'm working on calls for the use of a rotary encoder, so I decided to write a library to do the decoding.
My library uses an interrupt on timer2 to poll the pins and decode the signals.
At the moment it only supports one encoder, but I hope to add the possibility for more encoders in the future.

Here is the library.

Here's an example of using it:
Code: [Select]
#include "Encoder.h"

const int encoderPin_A = 8;
const int encoderPin_B = 9;

int counter = 0;

void setup()
{
 Serial.begin(9600);
 encoder_begin(encoderPin_A, encoderPin_B); // Start the decoder
}

void loop()
{
 int dir = encoder_data(); // Check for rotation
 
 if(dir == 1)       // If its forward...
 {
   counter++;       // Increment the counter
   Serial.println(counter);
 }
 
 else if(dir == -1) // If its backward...
 {
   counter--;       // Decrement the counter
   Serial.println(counter);
 }
}


And I have a small explanation of it here.

Hopefully it will be useful for somebody.

THX_RoG

#1
Jul 06, 2013, 08:17 am Last Edit: Jul 06, 2013, 08:52 am by THX_RoG Reason: 1
yes like my i was looking for something like this small and easy to use
i want to connect a I2C and read a couples of this encoder  
UNO,MEGA2560,MEGA2560
Killed:UNO, MEGA2560, ... More to come

#2
Jul 10, 2013, 10:07 pm Last Edit: Jul 11, 2013, 10:43 pm by frodofski Reason: 1
Update: Support for multiple encoders.

I added support for up to 5 rotary encoders to the library. I've probably done it in the lease efficient way possible, but I have no experience with classes in C++, so I wrote it all in C.

Here is the full explanation.

And here is the library itself.

Paul Stoffregen

Were you aware of the Encoder library I published?

http://www.pjrc.com/teensy/td_libs_Encoder.html

It might be nice to change your library's name slightly, so it can be used along side this long-established library without the .h files conflicting.

Ah, sorry Paul, I didn't know about your library.

I'll change the name of the files.

Paul Stoffregen

Thanks for making that change.  It's good to have names that are different enough for the compiler to not have conflicts when both are installed.  Calling it "V2" might imply it's a newer version of the same library, but that's a minor issue.  I'd personally prefer you used a more distinctive name, but that's really your call.

Your library uses a different approach that could be really nice for people using boards with a very limited number of interrupt pins, like Arduino Uno.  Would be nice if the name somehow made that difference and its advantages clear.

Regarding the library, if you're willing to consider another idea, you might make it a C++ class?  That's the normal way almost all Arduino libraries are structured.  The object constructor could automatically assign the "_encNum", perhaps using an array or bitmask of which ones are already in use?  You'd make _encNum a private or protected class member, so there would be no need to pass it on every function call.

If you add a 32 bit counter, you could even give your C++ object the same read() and write() functions my library has.  Then people could use it as a drop-in replacement.  They could #include both libraries in the same project and use your library for some encoders and mine for others.  All they'd do to change which encoders use which library is change the object name where the instance is created.


Again, sorry about the naming :smiley-red: hopefully the new names make a bit more sense.

I have very little experience with C++, as I've only ever used C really. I think I should learn C++ properly, so I can take advantage of some of its features like you said.

Also, that's a really good idea! I'll take a good look at your library and try to make the two libraries integrable.

Paul Stoffregen

C++ has a lot of complex features, but for just making this an object, you can probably use almost any Arduino library as a guide.

The Encoder library I published has a lot of tricky optimizations, so it's probably not the best one to look at for an example.  Libraries like Stepper or Servo are probably good ones to use for an example.

Hello Paul,

First thanks for this excellent library.

In my project, I'd need to declare an encoder dynamically. I mean, declare the encoder first, and assign pins in a second time after reading a sort of config file.
is there a way to modify your library, creating a kind of "assign" function to dynamically declare the pins number instead of passing the values at declaration?

Thank you,

Michael.

Paul Stoffregen


In my project, I'd need to declare an encoder dynamically. I mean, declare the encoder first, and assign pins in a second time after reading a sort of config file.
is there a way to modify your library, creating a kind of "assign" function to dynamically declare the pins number instead of passing the values at declaration?


In theory, you should be able to create instances of the library with "new".  But in practice, it doesn't work.  There's some sort of bug.  Details here:

http://forum.pjrc.com/threads/23498-Using-the-Encoder-library-with-pointers

Fixing this is on my to-do list, but currently I'm working on many much higher priority tasks.  If you'd like an update when I work on this bug, please subscribe to that thread.  That's where I'll post any updates about a fix.

Ok, Paul, thanks a lot for your fast answer.

Looking forward for this mod ;)

Michael.


Were you aware of the Encoder library I published?

http://www.pjrc.com/teensy/td_libs_Encoder.html

It might be nice to change your library's name slightly, so it can be used along side this long-established library without the .h files conflicting.


It says there that SoftwareSerial is very likely to cause problems. I'm using GSM Shield on my circuit via hardware serial and Serial LCD via software serial. My microcontroller is an Arduino Uno clone. I'm about to use a rotary encoder to measure soil movement in a mountain. What problems would I be facing? Does it have something to do with my LCD displaying incorrectly? Can I turn off the interrupt whenever the Serial LCD comes up in the code? Any suggestions? Thank you in advance :)

Paul Stoffregen

SoftwareSerial disables interrupts while sending or receiving a byte.  For example, at 9600 baud, 8N1 format, a byte takes 1.04 ms.  During that time, the Encoder library can't recognize any changes on the encoder pins.

The pin interrupt hardware will save the fact that the pin changed, so as long as only 1 change happens during that time, it will be picked up later.  But 2 missed changes can cause incorrect counting.

With hardware serial, interrupts are disabled for only a few microseconds, instead of over 1000 us, so even fairly fast movement on encoders can be properly tracked while serial data flows.

PaulS

Quote
I'm about to use a rotary encoder to measure soil movement in a mountain.

How?

Code: [Select]
What problems would I be facing?
That depends on how fast the rotary encoder is turning, and what the rest of the code is doing.

Quote
Does it have something to do with my LCD displaying incorrectly?

Yes. No. Maybe. The answer depends on what the undefined it is.

Quote
Can I turn off the interrupt whenever the Serial LCD comes up in the code?

You can get anything you like at Alice's Restaurant. You can, similarly, do anything you like in your code. Whether it makes sense, or not, is a different story.

Quote
Any suggestions?

Well, now that you mention it, posting your code would be useful. Posting well defined questions might be, too.

Paul Stoffregen

The other possibility is my AltSoftSerial library.

http://www.pjrc.com/teensy/td_libs_AltSoftSerial.html

It does not disable interrupts for the entire byte, so it will interfere much less with Encoder.  However, AltSoftSerial depends on Timer1, so it's incompatible with any other libraries that need Timer1.

Go Up