Giter VIP home page Giter VIP logo

rotaryencoder's Introduction

RotaryEncoder library

Arduino Library Checks

A library for the Arduino environment for using a rotary encoder as an input.

Here you can find an Arduino compatible library for using rotary encoders.

When I was searching a library for using a rotary encoder in my latest project and found a lot of information on this topic but none of the existing libraries did immediately match my expectations so I finally built my own.

It supports the type of rotary encoder that has a phase change on both input signals when rotating one notch.

The article on my web site explains the software mechanisms used in detail so you can understand the coding and might be able to adjust it to your needs if you like:

http://www.mathertel.de/Arduino/RotaryEncoderLibrary.aspx

There are various aspects when writing a library for rotary encoders and you can also find a lot of the sources I analyzed at the bottom of the article.

rotaryencoder's People

Contributors

buildersky avatar deltaphi avatar giupo avatar mathertel avatar rprediger avatar sysshad avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

rotaryencoder's Issues

Does not work with ATTiny88 on pins 12 and 13

I am attempting to use your encoder library on a project of mine that employs an ATTiny88 with an EC11 rotary encoder attached to pins 12 and 13.

Here is the error stack using your interrupt example:
Rotary Encoder errors.txt

Here is my code, which compiles and runs without your library, but misses lots of interrupts and often reports the wrong direction:
Rotary Encoder Good.txt

Note the ATTiny88 requires a slightly modified PinChangeInterrupt.h library. See https://arduino.stackexchange.com/questions/92354/change-interrupts-on-the-attiny-88

Double output

Is there a simple way to only get one step per latch instead of two steps as it is now?

Sporadic 255/-255 values at interruptRotator example when hovering around 0

the interruptRotator example causes some spikes of 255 or -255 for the encoder position when you rotate around the "0" position.

it's fixable by calling noInterrupts(); and interrupts(); around the
"newPos = encoder->getPosition();" line to temporarily disable interrupts when getting the current value.

ESP8266 external interrupt support.

Is this library's interrupt rotary encoder compatible with esp8266? It seems like its not because of the use of pin change interupt vs external interrupt. What can I look into to change the type of interrupt for this library?

Working on mega 2560

What changes are required to make it work into a mega 2560, because it doesn't work as it is.

Regards

_pin1 and _pin2 not used in RotaryEncoder::tick(void)

Hi,

First of all, thank you for a very nice library!

I found one issue with the RotaryEncoder::tick(void) function, specifically lines 68 and 69

They should be changed to:
int sig1 = digitalRead(_pin1);
int sig2 = digitalRead(_pin2);

from :
int sig1 = digitalRead(A2);
int sig2 = digitalRead(A3);

As it works now it only reads pins A2 and A3 and not the pins used in the Encoder constructor.

Again, thank you for the very nice code!

/Thomas

Bug?

Hi, first of all thanks for this library.

I got some strange behavior here. When position getting in 8191 to 8192 it get -8192.

Try setPosition(8190) and then rotate.

Skips a step on direction change

The library works fine in either direction with a Bourns PEC-12R rotary encoder except when changing direction. When changing direction it takes another click on the encoder to register an increase or decrease.

Store two values

Hey Matthias, what a nice library!

I'm trying to make the same encoder kin of work as two. My idea is to have it's rotation to change a Lightroom parameter, and when I click the button, it will change another one. I could make it switch between the parameters - which means sending two different MIDI CC values - but when I switch from one to another, the value will be stored. So, say I changed Brightness to 10, and clicking the button will change the encoder to Contrast, Contrast will be on 10. If I raise it to 40, clicking back to Brightness, it will start from 40. My guess is that the encoder is storing this absolute value, so I tried changing the library a little bit, setting different encoders, different getPositions, but in the end I failed. Do you have any idea??

Thanks man!

request: set steps per revolution and relevant example how to use this

i.e.
1 rotary encoder, 16 steps, 2 leds.

Psudo-code:

if(RevolutionStep < 4) // Pos 0-3
{
  digitalWrite(13, HIGH); // LED_BUILTIN
  digitalWrite(12, HIGH); // LED_EXTERNAL
}
else if(RevolutionStep >= 4 && RevolutionStep < 8) // Pos 4-7
{
  digitalWrite(13, HIGH); // LED_BUILTIN
  digitalWrite(12, LOW); // LED_EXTERNAL
}
else if(RevolutionStep >= 8 && RevolutionStep < 12) // Pos 8-11
{
  digitalWrite(13, LOW); // LED_BUILTIN
  digitalWrite(12, LOW); // LED_EXTERNAL
}
else if(RevolutionStep >= 12) // Pos 12-15
{
  digitalWrite(13, LOW); // LED_BUILTIN
  digitalWrite(12, HIGH); // LED_EXTERNAL
}
// 16 steps completed. One full revolution.

INPUT_PULLUP

Hello,

I tried to make it work on STM32F103C8T6 (with STM32duino support) . The old code does not work:
pinMode(pin1, INPUT);
digitalWrite(pin1, HIGH); // turn on pullup resistor

And should be replaced by

pinMode(pin1, INPUT_PULLUP);

Same for pin2...

half step support

Hi,
first your library works like a charm, thank you for your nice work!
Have you thought about adding support for a half-step mode? I have a rotary encoder that has not only the state "3" but also the state "0" as a latch state.

add onChange callback? (Enhancement request)

have you considered adding a callback that is invoked when the position changes? Kind of like your OneButton library where the click invokes a callback.

Seems straightforward to callback from tick(), but maybe I'm missing some complication.

Error in LCD

when i compile your code, i receive errors regarding LCD as follows:

SimplePollRotatorLCD:25: error: 'LiquidCrystal_PCF8574' does not name a type
SimplePollRotatorLCD.ino: In function 'void setup()':
SimplePollRotatorLCD:29: error: 'lcd' was not declared in this scope
SimplePollRotatorLCD.ino: In function 'void loop()':
SimplePollRotatorLCD:43: error: 'lcd' was not declared in this scope

InterruptRotator issue

First comment - really great job this library.
Using the InterruptRotator example for Arduino Nano I used pin 2 and 3 (#define PIN_IN1 2,
#define PIN_IN2 3) instead of #PIN_IN1 A2, #define PIN_IN2 A3 because it's just for Arduino Uno (what I understand)?
The compiling process stops with 'PIN_IN1/2' was not declared.
Hope, you can help.
Best regards, Ronald

reversing rotation direction skips one count

in version 1.5.0 when reversing the direction of the knob the first getDirection returns 0 (norotation), needs one more tick to start reporting the proper direction. With 1.3.0 it works correctly.

attachInterrupt missing digitalPinToInterrupt in example

Tested your example with Interrupts (InterruptRotator.ino). There is no need the call encoder.tick() in the main loop if the interrupts would work.

Changed your
attachInterrupt(PIN_IN1, checkPosition, CHANGE); attachInterrupt(PIN_IN2, checkPosition, CHANGE);

to

attachInterrupt(digitalPinToInterrupt(PIN_IN1), checkPosition, CHANGE); attachInterrupt(digitalPinToInterrupt(PIN_IN2), checkPosition, CHANGE);
and deleted your tick in the main loop.

Tested on a Arduino Nano V3.

defined(ARDUINO_AVR_NANO_EVERY) not work with Nano

thank for your library, is very good !

i use Nano, and the precompilator "defined(ARDUINO_AVR_NANO_EVERY)" not work for my arduino ide 1.8.13
the correct syntax is "defined(ARDUINO_AVR_NANO)"

  1. in your exemple "AcceleratedRotator" exst 2 .ino strictely identical

best regard,

Stef

Decrement does not work when setPosition is called between latchstates

Hello, and thanks for your lib, works great for me besides this issue I just spent some time debugging.

Symptom:
slow decrements not being registered.

Context:
I'm using the lib with interrupts (tick() called in an ISR), and agressively used getPosition and setPosition(0) at each iteration of my main loop.

nointerrupts();
local_coderCounter = encoder.getPosition();
encoder.setPosition(0);
interrupts();

Issue
Turns out, if setPosition(0) is executed between 2 latchstates, if _position was negative, the way _position is reassigned is incorrect: it is treated as an unsigned int:
_position = ((newPosition<<2) | (_position & 0x03L));

Decrementing causes variable corruption when used with interrupts

Your library suffers from this issue:
https://www.arduino.cc/reference/en/language/variables/variable-scope--qualifiers/volatile/

You can easily reproduce this if you enhance your interrupt example with code for resetting the value after printing it by doing "setPosition(0)" after printing.

The easiest and not hardware dependent solution to fix this would be to make this variable an signed char. I could create a pull request for this but I want to wait for your feedback, first.

Constraining encoder to range of values

First off, awesome library. After feeling like I've scoured the earth, this one seems really reliable, elegant, and simple. I kept getting "microsteps" with other libraries, quick jitters between values (like printing 4, 5, 4, 5, 4, 5 sometimes when changing direction), stepping 4 at a time, etc.

I'm trying to use two encoders to create a sort of Etch-a-Sketch on a 16x16 LED matrix. Thus, I'd like my encoders to only range between 0-15 for my rows/columns. I also think I'll scale the detents so perhaps 3-4 is one "step" as my detents are pretty closely spaced.

My approach was as follows, based on your SimplePollRotator example:

  encoder.tick();

  int newPos = constrain(encoder.getPosition(), 0, 15);
  encoder.setPosition(newPos);
 
  if (pos != newPos) {
    Serial.print(newPos);
    Serial.println();
    pos = newPos;

  } // if

I'm using both constrain() and setPosition because constrain() by itself will only control newPos, not the cumulative encoder value that's getting picked up by getPosition. So, as I turn it past 15, I'll only see 15's printed out on the screen, but getPosition might be much higher. Thus, I have to turn back until getPosition is between 0-15 and then the value changes.

What I thought I could do was make sure that the position of the encoder would be fixed to 0 or 15 if it tried to go outside those ranges and that encoder.tick() would still pick up changes to get it out of that endpoint. What I'm finding is nothing happens, so I'm guessing pos != newPos is somehow never met?

Any suggestion on how I can sort of ignore the encoder if it's trying to go above/below my limits but still register changes that put it back in those limits? I'm not a hardcore C guy so I'm unable to follow your bit shifting code at the moment, but also feel like I may not understand what setPosition is doing.

Thanks for any tips!

AcceleratedRotator example seems to be wrong

Hello,

I've tried the AcceleratedRotator.ino example becase I want to use it on a project I'm doing, and I've noticed that is not working.

The variable lastMovementDirection is not updated, so the acceleration will never trigger.

Best regards.

getDirection() is not working as expected

If I call getDirection() I dont get the expected results.
CLOCKWISE is detected when I turn COUNTERCLOCKWISE.

The serial output below shows correct newPos is 0,1,2,3,4,3,2,1,0,-1,-2,-3,-4
But the corresponding ::Direction is not correct in every case.
It only is correct if newPos reaches 0.

I have no clue why - maybe because _positionExtPrev is not manipulated in tick().

Sketch

void loop()
{
static int pos = 0;
encoder.tick();

int newPos = encoder.getPosition();
if (pos != newPos) {
Serial.print(newPos);
Serial.println();
processEncoder(encoder);
pos = newPos;
} // if

// The End
void processEncoder(RotaryEncoder myEncoder)
{
switch (myEncoder.getDirection())
{
case RotaryEncoder::Direction::NOROTATION:
break;

case RotaryEncoder::Direction::CLOCKWISE:
  {
    Serial.println(F("CLOCKWISE"));
  }
  break;

case RotaryEncoder::Direction::COUNTERCLOCKWISE:
  {
    Serial.println(F("COUNTERCLOCKWISE"));
  }
  break;

default:
  {

  }

}
}

} // loop ()

Serial output

COUNTERCLOCKWISE
0
1
CLOCKWISE
2
CLOCKWISE
3
CLOCKWISE
4
CLOCKWISE
3
CLOCKWISE
2
CLOCKWISE
1
CLOCKWISE
0
-1
COUNTERCLOCKWISE
-2
COUNTERCLOCKWISE
-3
COUNTERCLOCKWISE
-4
COUNTERCLOCKWISE
2
CLOCKWISE
3
CLOCKWISE
4
CLOCKWISE
3
CLOCKWISE
2
CLOCKWISE
1
CLOCKWISE
0
-1
COUNTERCLOCKWISE
-2
COUNTERCLOCKWISE
-3
COUNTERCLOCKWISE
-4
COUNTERCLOCKWISE

Multiple encoders

Do you have an example code to use 3 or 4 encoders with this library?
Is this even possible with your library?

Interrupt example not actually using interrupts

The Interrupt example should be changed to use the following format in the setup section

     attachInterrupt(digitalPinToInterrupt(pin), ISR, mode)

i.e.
attachInterrupt(digitalPinToInterrupt(PIN_IN1), checkPosition, CHANGE);
attachInterrupt(digitalPinToInterrupt(PIN_IN2), checkPosition, CHANGE);

and then the line

     encoder.tick();

can be removed from the loop function.

As shipped the example does not use interrupts and simply polls encoder changes.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.