Pages: [1] 2   Go Down
Author Topic: Rotary Encoder Library  (Read 10547 times)
0 Members and 1 Guest are viewing this topic.
Ireland
Offline Offline
Newbie
*
Karma: 0
Posts: 7
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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:
#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.
« Last Edit: July 11, 2013, 03:43:16 pm by frodofski » Logged

Germany
Offline Offline
Jr. Member
**
Karma: 1
Posts: 80
Arduino in VS MODE
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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  
« Last Edit: July 06, 2013, 01:52:52 am by THX_RoG » Logged

UNO,MEGA2560,MEGA2560
Killed:UNO, MEGA2560, ... More to come

Ireland
Offline Offline
Newbie
*
Karma: 0
Posts: 7
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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.
« Last Edit: July 11, 2013, 03:43:40 pm by frodofski » Logged

0
Offline Offline
God Member
*****
Karma: 25
Posts: 606
Always making something...
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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.
Logged

Ireland
Offline Offline
Newbie
*
Karma: 0
Posts: 7
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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

I'll change the name of the files.
Logged

0
Offline Offline
God Member
*****
Karma: 25
Posts: 606
Always making something...
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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.

Logged

Ireland
Offline Offline
Newbie
*
Karma: 0
Posts: 7
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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.
Logged

0
Offline Offline
God Member
*****
Karma: 25
Posts: 606
Always making something...
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 4
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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.
Logged

0
Offline Offline
God Member
*****
Karma: 25
Posts: 606
Always making something...
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 4
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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

Looking forward for this mod smiley-wink

Michael.
Logged

Offline Offline
Newbie
*
Karma: 0
Posts: 9
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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 smiley
Logged

0
Offline Offline
God Member
*****
Karma: 25
Posts: 606
Always making something...
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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.
Logged

Seattle, WA USA
Offline Offline
Brattain Member
*****
Karma: 601
Posts: 48543
Seattle, WA USA
View Profile
 Bigger Bigger  Smaller Smaller  Reset Reset

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

Code:
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.
Logged

0
Offline Offline
God Member
*****
Karma: 25
Posts: 606
Always making something...
View Profile
WWW
 Bigger Bigger  Smaller Smaller  Reset Reset

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.
Logged

Pages: [1] 2   Go Up
Jump to: