gfvalvo / NewEncoder

Rotary Encoder Library
48 stars 16 forks source link

NewEncoder

Interrupt-driven rotary encoder library. Works both with encoders that produce one complete quadrature cycle every detent (such as this Bourns unit sold by Adafruit) and those that produce one complete quadrature cycle for every two detents (such as this Alps unit sold by Mouser).

The encoders' switches are debounced using a state table approach.

Two interrupt-capable pins are required for each encoder connected. Thus, only one encoder can be used with an Arduino Uno for example.

The encoders' "A" and "B" terminals should be connected to the processor's inputs and its common terminal should be grounded. The library enables the processor's internal pull-ups, so external ones are not required.

Version 2.x:

This is a major update to the NewEncoder library. It addresses discrepancies that could occur due to the nature of interrupts. Previous version could provide inconsistent results between the getValue(), upClick(), and downClick() functions.

For example a call to getValue() might indicate that the encoder was not moved, but a call to upClick() or downClick() immediately following this could show that it was. Or, upClick() might have indicated no change from the encoder but a call to getValue() immediately following this could return an incremented value.

These non-intuitive results depended on the exact timing of the calls to the various functions in relation to the exact moment the encoder caused the processor interrupt.

This new version of the library addresses these issues by introducing new member functions for accessing the encoder and new data structures that will be updated atomically. The older member functions are still available. However, they have been deprecated and will cause compiler warnings if used. They may be removed from a future release of this library.

New Datatypes in Version 2.0:

The following public datatypes are in NewEncoder scope (i.e. NewEncoder::).

enum EncoderClick {
    NoClick, DownClick, UpClick
};

This enum datatype indicates the direction of encoder movement.

struct EncoderState {
    int16_t currentValue = 0;
    EncoderClick currentClick = NoClick;
};

This struct datatype contains the current encoder value and click direction. Variables of these types are returned by several of the member functions new to Version 2.0. Those functions are described in the next section.

All examples have been updated to use the new datatypes / functions described.

NOTES:

1. This library is interrupt-safe for the single-core / single-thread platforms that make up the majority of the Arduino Ecosystem. It is also safe for the FreeRTOS / ESP32 platform if its functions are only called from a single core and single thread (task). The SingleEncoderEsp32FreeRTOS example follows these guidelines. A NewEncoderEsp32 library will soon be released that is multi-thread / multi-core safe.

2. If desired, the previous version of this library can be downloaded and used. However, it will no longer be supported / updated: NewEncoder v1.4

Library Description:

Class NewEncoder

This provides interfacing to the encoder, interrupt handling, and rotation counting. One instance of this class is created for each encoder.

Public NewEncoder Members Functions:

Constructor - creates and configures object

NewEncoder(uint8_t aPin, uint8_t bPin, int16_t minValue, int16_t maxValue, int16_t initalValue, uint8_t type = FULL_PULSE)

Arguments:

Constructor - only creates object

NewEncoder()

Arguments: None. The object must be configured using the configure() method before being used

Configure or Re-configure an encoder object

void configure(uint8_t aPin, uint8_t bPin, int16_t minValue, int16_t maxValue, int16_t initalValue, uint8_t type = FULL_PULSE);

Arguments: Same as Constructor Returns: Nothing

Start an encoder object

bool begin();

Arguments: None

Returns:

Disable an encoder object

 void end();

Arguments: None

Returns: Nothing

Check if encoder object is enabled

 bool enabled();

Arguments: None

Returns:

Get Current Encoder State

bool getState(NewEncoder::EncoderState &state);

Arguments:

Returns:

Returns:

Returns:

Customize increment/decrement and min/max behavior via inheritance

// This function may be implemented in an inherited class to customize the increment/decrement and min/max behavior.
// See the source code and CustomEncoder example
// Caution - this function is called in interrupt context.
// See "CustomEncoder" example
virtual void updateValue(uint8_t updatedState);

Arguments:

Returns: - true if change was successful, false otherwise

Credits:

The direct_pin_read.h and interrupt_pins.h header files were "borrowed" directly from the PRJC Encoder Library Copyright (c) PJRC.COM, LLC - Paul Stoffregen. All typical license verbiage applies.

Other concepts were inspired by http://www.buxtronix.net/2011/10/rotary-encoders-done-properly.html