esp32-rotary-encoder
ESP32-compatible C library for Incremental Rotary Encoders.
 All Data Structures Files Functions Variables Enumerations Enumerator
Macros | Functions
/home/travis/build/DavidAntliff/esp32-rotary-encoder/rotary_encoder.c File Reference

Driver implementation for the ESP32-compatible Incremental Rotary Encoder component. More...

#include "rotary_encoder.h"
#include "esp_log.h"
#include "driver/gpio.h"

Macros

#define TAG   "rotary_encoder"
 
#define EVENT_QUEUE_LENGTH   1
 
#define TABLE_ROWS   7
 
#define DIR_NONE   0x0
 
#define DIR_CW   0x10
 
#define DIR_CCW   0x20
 
#define R_START   0x0
 
#define H_CCW_BEGIN   0x1
 
#define H_CW_BEGIN   0x2
 
#define H_START_M   0x3
 
#define H_CW_BEGIN_M   0x4
 
#define H_CCW_BEGIN_M   0x5
 
#define F_CW_FINAL   0x1
 
#define F_CW_BEGIN   0x2
 
#define F_CW_NEXT   0x3
 
#define F_CCW_BEGIN   0x4
 
#define F_CCW_FINAL   0x5
 
#define F_CCW_NEXT   0x6
 

Functions

esp_err_t rotary_encoder_init (rotary_encoder_info_t *info, gpio_num_t pin_a, gpio_num_t pin_b)
 Initialise the rotary encoder device with the specified GPIO pins and full step increments. This function will set up the GPIOs as needed, Note: this function assumes that gpio_install_isr_service(0) has already been called. More...
 
esp_err_t rotary_encoder_enable_half_steps (rotary_encoder_info_t *info, bool enable)
 Enable half-stepping mode. This generates twice as many counted steps per rotation. More...
 
esp_err_t rotary_encoder_flip_direction (rotary_encoder_info_t *info)
 Reverse (flip) the sense of the direction. Use this if clockwise/counterclockwise are not what you expect. More...
 
esp_err_t rotary_encoder_uninit (rotary_encoder_info_t *info)
 Remove the interrupt handlers installed by rotary_encoder_init. Note: GPIOs will be left in the state they were configured by rotary_encoder_init. More...
 
QueueHandle_t rotary_encoder_create_queue (void)
 Create a queue handle suitable for use as an event queue. More...
 
esp_err_t rotary_encoder_set_queue (rotary_encoder_info_t *info, QueueHandle_t queue)
 Set the driver to use the specified queue as an event queue. It is recommended that a queue constructed by rotary_encoder_create_queue is used. More...
 
esp_err_t rotary_encoder_get_state (const rotary_encoder_info_t *info, rotary_encoder_state_t *state)
 Get the current position of the rotary encoder. More...
 
esp_err_t rotary_encoder_reset (rotary_encoder_info_t *info)
 Reset the current position of the rotary encoder to zero. More...
 

Detailed Description

Driver implementation for the ESP32-compatible Incremental Rotary Encoder component.

Based on https://github.com/buxtronix/arduino/tree/master/libraries/Rotary Original header follows:

Rotary encoder handler for arduino. v1.1

Copyright 2011 Ben Buxton. Licenced under the GNU GPL Version 3. Contact: bb@ca.nosp@m.ctii.nosp@m..net

A typical mechanical rotary encoder emits a two bit gray code on 3 output pins. Every step in the output (often accompanied by a physical 'click') generates a specific sequence of output codes on the pins.

There are 3 pins used for the rotary encoding - one common and two 'bit' pins.

The following is the typical sequence of code on the output when moving from one step to the next:

Position Bit1 Bit2

Step1 0 0 1/4 1 0 1/2 1 1 3/4 0 1 Step2 0 0

From this table, we can see that when moving from one 'click' to the next, there are 4 changes in the output code.

Detecting the direction is easy - the table simply goes in the other direction (read up instead of down).

To decode this, we use a simple state machine. Every time the output code changes, it follows state, until finally a full steps worth of code is received (in the correct order). At the final 0-0, it returns a value indicating a step in one direction or the other.

It's also possible to use 'half-step' mode. This just emits an event at both the 0-0 and 1-1 positions. This might be useful for some encoders where you want to detect all positions.

If an invalid state happens (for example we go from '0-1' straight to '1-0'), the state machine resets to the start until 0-0 and the next valid codes occur.

The biggest advantage of using a state machine over other algorithms is that this has inherent debounce built in. Other algorithms emit spurious output with switch bounce, but this one will simply flip between sub-states until the bounce settles, then continue along the state machine. A side effect of debounce is that fast rotations can cause steps to be skipped. By not requiring debounce, fast rotations can be accurately measured. Another advantage is the ability to properly handle bad state, such as due to EMI, etc. It is also a lot simpler than others - a static state table and less than 10 lines of logic.

Function Documentation

esp_err_t rotary_encoder_init ( rotary_encoder_info_t info,
gpio_num_t  pin_a,
gpio_num_t  pin_b 
)

Initialise the rotary encoder device with the specified GPIO pins and full step increments. This function will set up the GPIOs as needed, Note: this function assumes that gpio_install_isr_service(0) has already been called.

Parameters
[in,out]infoPointer to allocated rotary encoder info structure.
[in]pin_aGPIO number for rotary encoder output A.
[in]pin_bGPIO number for rotary encoder output B.
Returns
ESP_OK if successful, ESP_FAIL or ESP_ERR_* if an error occurred.
esp_err_t rotary_encoder_enable_half_steps ( rotary_encoder_info_t info,
bool  enable 
)

Enable half-stepping mode. This generates twice as many counted steps per rotation.

Parameters
[in]infoPointer to initialised rotary encoder info structure.
[in]enableIf true, count half steps. If false, only count full steps.
Returns
ESP_OK if successful, ESP_FAIL or ESP_ERR_* if an error occurred.
esp_err_t rotary_encoder_flip_direction ( rotary_encoder_info_t info)

Reverse (flip) the sense of the direction. Use this if clockwise/counterclockwise are not what you expect.

Parameters
[in]infoPointer to initialised rotary encoder info structure.
Returns
ESP_OK if successful, ESP_FAIL or ESP_ERR_* if an error occurred.
esp_err_t rotary_encoder_uninit ( rotary_encoder_info_t info)

Remove the interrupt handlers installed by rotary_encoder_init. Note: GPIOs will be left in the state they were configured by rotary_encoder_init.

Parameters
[in]infoPointer to initialised rotary encoder info structure.
Returns
ESP_OK if successful, ESP_FAIL or ESP_ERR_* if an error occurred.
QueueHandle_t rotary_encoder_create_queue ( void  )

Create a queue handle suitable for use as an event queue.

Returns
A handle to a new queue suitable for use as an event queue.
esp_err_t rotary_encoder_set_queue ( rotary_encoder_info_t info,
QueueHandle_t  queue 
)

Set the driver to use the specified queue as an event queue. It is recommended that a queue constructed by rotary_encoder_create_queue is used.

Parameters
[in]infoPointer to initialised rotary encoder info structure.
[in]queueHandle to queue suitable for use as an event queue. See rotary_encoder_create_queue.
Returns
ESP_OK if successful, ESP_FAIL or ESP_ERR_* if an error occurred.
esp_err_t rotary_encoder_get_state ( const rotary_encoder_info_t info,
rotary_encoder_state_t state 
)

Get the current position of the rotary encoder.

Parameters
[in]infoPointer to initialised rotary encoder info structure.
[in,out]statePointer to an allocated rotary_encoder_state_t struct that will
Returns
ESP_OK if successful, ESP_FAIL or ESP_ERR_* if an error occurred.
esp_err_t rotary_encoder_reset ( rotary_encoder_info_t info)

Reset the current position of the rotary encoder to zero.

Parameters
[in]infoPointer to initialised rotary encoder info structure.
Returns
ESP_OK if successful, ESP_FAIL or ESP_ERR_* if an error occurred.