Skip to content

Commit

Permalink
Add files via upload
Browse files Browse the repository at this point in the history
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
GilbertoCsar authored Jul 21, 2024
0 parents commit 7c2bfa3
Show file tree
Hide file tree
Showing 6 changed files with 717 additions and 0 deletions.
2 changes: 2 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,2 @@
.vscode/*
_*
Binary file added RotaryEncoder-master.zip
Binary file not shown.
168 changes: 168 additions & 0 deletions RotaryEncoder.cpp
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
76 changes: 76 additions & 0 deletions RotaryEncoder.h
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
9 changes: 9 additions & 0 deletions library.properties
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=*
Loading

0 comments on commit 7c2bfa3

Please sign in to comment.