-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Please, unpack the WinRAR (.zip) archive only if is necessary. For the else, the Library RotaryEncoder, in the types .h and .cpp, will appear beside the file type .ino (sketch), at the top left of the IDE. Thank you !
- Loading branch information
0 parents
commit 7c2bfa3
Showing
6 changed files
with
717 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,2 @@ | ||
.vscode/* | ||
_* |
Binary file not shown.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,168 @@ | ||
// ----- | ||
// RotaryEncoder.cpp - Library for using rotary encoders. | ||
// This class is implemented for use with the Arduino environment. | ||
// | ||
// Copyright (c) by Matthias Hertel, http://www.mathertel.de | ||
// | ||
// This work is licensed under a BSD 3-Clause style license, | ||
// https://www.mathertel.de/License.aspx. | ||
// | ||
// More information on: http://www.mathertel.de/Arduino | ||
// ----- | ||
// Changelog: see RotaryEncoder.h | ||
// ----- | ||
|
||
#include "RotaryEncoder.h" | ||
#include "Arduino.h" | ||
|
||
#define LATCH0 0 // input state at position 0 | ||
#define LATCH3 3 // input state at position 3 | ||
|
||
|
||
// The array holds the values �1 for the entries where a position was decremented, | ||
// a 1 for the entries where the position was incremented | ||
// and 0 in all the other (no change or not valid) cases. | ||
|
||
const int8_t KNOBDIR[] = { | ||
0, -1, 1, 0, | ||
1, 0, 0, -1, | ||
-1, 0, 0, 1, | ||
0, 1, -1, 0}; | ||
|
||
|
||
// positions: [3] 1 0 2 [3] 1 0 2 [3] | ||
// [3] is the positions where my rotary switch detends | ||
// ==> right, count up | ||
// <== left, count down | ||
|
||
|
||
// ----- Initialization and Default Values ----- | ||
|
||
RotaryEncoder::RotaryEncoder(int pin1, int pin2, LatchMode mode) | ||
{ | ||
// Remember Hardware Setup | ||
_pin1 = pin1; | ||
_pin2 = pin2; | ||
_mode = mode; | ||
|
||
// Setup the input pins and turn on pullup resistor | ||
pinMode(pin1, INPUT_PULLUP); | ||
pinMode(pin2, INPUT_PULLUP); | ||
|
||
// when not started in motion, the current state of the encoder should be 3 | ||
int sig1 = digitalRead(_pin1); | ||
int sig2 = digitalRead(_pin2); | ||
_oldState = sig1 | (sig2 << 1); | ||
|
||
// start with position 0; | ||
_position = 0; | ||
_positionExt = 0; | ||
_positionExtPrev = 0; | ||
} // RotaryEncoder() | ||
|
||
|
||
long RotaryEncoder::getPosition() | ||
{ | ||
return _positionExt; | ||
} // getPosition() | ||
|
||
|
||
RotaryEncoder::Direction RotaryEncoder::getDirection() | ||
{ | ||
RotaryEncoder::Direction ret = Direction::NOROTATION; | ||
|
||
if (_positionExtPrev > _positionExt) { | ||
ret = Direction::COUNTERCLOCKWISE; | ||
_positionExtPrev = _positionExt; | ||
} else if (_positionExtPrev < _positionExt) { | ||
ret = Direction::CLOCKWISE; | ||
_positionExtPrev = _positionExt; | ||
} else { | ||
ret = Direction::NOROTATION; | ||
_positionExtPrev = _positionExt; | ||
} | ||
|
||
return ret; | ||
} | ||
|
||
|
||
void RotaryEncoder::setPosition(long newPosition) | ||
{ | ||
switch (_mode) { | ||
case LatchMode::FOUR3: | ||
case LatchMode::FOUR0: | ||
// only adjust the external part of the position. | ||
_position = ((newPosition << 2) | (_position & 0x03L)); | ||
_positionExt = newPosition; | ||
_positionExtPrev = newPosition; | ||
break; | ||
|
||
case LatchMode::TWO03: | ||
// only adjust the external part of the position. | ||
_position = ((newPosition << 1) | (_position & 0x01L)); | ||
_positionExt = newPosition; | ||
_positionExtPrev = newPosition; | ||
break; | ||
} // switch | ||
|
||
} // setPosition() | ||
|
||
|
||
void RotaryEncoder::tick(void) | ||
{ | ||
int sig1 = digitalRead(_pin1); | ||
int sig2 = digitalRead(_pin2); | ||
int8_t thisState = sig1 | (sig2 << 1); | ||
|
||
if (_oldState != thisState) { | ||
_position += KNOBDIR[thisState | (_oldState << 2)]; | ||
_oldState = thisState; | ||
|
||
switch (_mode) { | ||
case LatchMode::FOUR3: | ||
if (thisState == LATCH3) { | ||
// The hardware has 4 steps with a latch on the input state 3 | ||
_positionExt = _position >> 2; | ||
_positionExtTimePrev = _positionExtTime; | ||
_positionExtTime = millis(); | ||
} | ||
break; | ||
|
||
case LatchMode::FOUR0: | ||
if (thisState == LATCH0) { | ||
// The hardware has 4 steps with a latch on the input state 0 | ||
_positionExt = _position >> 2; | ||
_positionExtTimePrev = _positionExtTime; | ||
_positionExtTime = millis(); | ||
} | ||
break; | ||
|
||
case LatchMode::TWO03: | ||
if ((thisState == LATCH0) || (thisState == LATCH3)) { | ||
// The hardware has 2 steps with a latch on the input state 0 and 3 | ||
_positionExt = _position >> 1; | ||
_positionExtTimePrev = _positionExtTime; | ||
_positionExtTime = millis(); | ||
} | ||
break; | ||
} // switch | ||
} // if | ||
} // tick() | ||
|
||
|
||
unsigned long RotaryEncoder::getMillisBetweenRotations() const | ||
{ | ||
return (_positionExtTime - _positionExtTimePrev); | ||
} | ||
|
||
unsigned long RotaryEncoder::getRPM() | ||
{ | ||
// calculate max of difference in time between last position changes or last change and now. | ||
unsigned long timeBetweenLastPositions = _positionExtTime - _positionExtTimePrev; | ||
unsigned long timeToLastPosition = millis() - _positionExtTime; | ||
unsigned long t = max(timeBetweenLastPositions, timeToLastPosition); | ||
return 60000.0 / ((float)(t * 20)); | ||
} | ||
|
||
|
||
// End |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
// ----- | ||
// RotaryEncoder.h - Library for using rotary encoders. | ||
// This class is implemented for use with the Arduino environment. | ||
// | ||
// Copyright (c) by Matthias Hertel, http://www.mathertel.de | ||
// | ||
// This work is licensed under a BSD 3-Clause style license, | ||
// https://www.mathertel.de/License.aspx. | ||
// | ||
// More information on: http://www.mathertel.de/Arduino | ||
// ----- | ||
// 18.01.2014 created by Matthias Hertel | ||
// 16.06.2019 pin initialization using INPUT_PULLUP | ||
// 10.11.2020 Added the ability to obtain the encoder RPM | ||
// 29.01.2021 Options for using rotary encoders with 2 state changes per latch. | ||
// ----- | ||
|
||
#ifndef RotaryEncoder_h | ||
#define RotaryEncoder_h | ||
|
||
#include "Arduino.h" | ||
|
||
class RotaryEncoder | ||
{ | ||
public: | ||
enum class Direction { | ||
NOROTATION = 0, | ||
CLOCKWISE = 1, | ||
COUNTERCLOCKWISE = -1 | ||
}; | ||
|
||
enum class LatchMode { | ||
FOUR3 = 1, // 4 steps, Latch at position 3 only (compatible to older versions) | ||
FOUR0 = 2, // 4 steps, Latch at position 0 (reverse wirings) | ||
TWO03 = 3 // 2 steps, Latch at position 0 and 3 | ||
}; | ||
|
||
// ----- Constructor ----- | ||
RotaryEncoder(int pin1, int pin2, LatchMode mode = LatchMode::FOUR0); | ||
|
||
// retrieve the current position | ||
long getPosition(); | ||
|
||
// simple retrieve of the direction the knob was rotated last time. 0 = No rotation, 1 = Clockwise, -1 = Counter Clockwise | ||
Direction getDirection(); | ||
|
||
// adjust the current position | ||
void setPosition(long newPosition); | ||
|
||
// call this function every some milliseconds or by using an interrupt for handling state changes of the rotary encoder. | ||
void tick(void); | ||
|
||
// Returns the time in milliseconds between the current observed | ||
unsigned long getMillisBetweenRotations() const; | ||
|
||
// Returns the RPM | ||
unsigned long getRPM(); | ||
|
||
private: | ||
int _pin1, _pin2; // Arduino pins used for the encoder. | ||
|
||
LatchMode _mode; // Latch mode from initialization | ||
|
||
volatile int8_t _oldState; | ||
|
||
volatile long _position; // Internal position (4 times _positionExt) | ||
volatile long _positionExt; // External position | ||
volatile long _positionExtPrev; // External position (used only for direction checking) | ||
|
||
unsigned long _positionExtTime; // The time the last position change was detected. | ||
unsigned long _positionExtTimePrev; // The time the previous position change was detected. | ||
}; | ||
|
||
#endif | ||
|
||
// End |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,9 @@ | ||
name=RotaryEncoder | ||
version=1.5.3 | ||
author=Matthias Hertel | ||
maintainer=Matthias Hertel, http://www.mathertel.de | ||
sentence=Use a rotary encoder with quadrature pulses as an input device. | ||
paragraph=This library decodes the signals from a rotary encoder and translates them into a counter position. The library comes with some samples that show how to use the library with and without interrupts. | ||
category=Signal Input/Output | ||
url=http://www.mathertel.de/Arduino/RotaryEncoderLibrary.aspx | ||
architectures=* |
Oops, something went wrong.