Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Encoder: added rotary encoder library and example
- Loading branch information
1 parent
254c334
commit ec39d45
Showing
4 changed files
with
248 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,87 @@ | ||
/* | ||
____ _____ _ _ | ||
| __ )| ____| | / \ | ||
| _ \| _| | | / _ \ | ||
| |_) | |___| |___ / ___ \ | ||
|____/|_____|_____/_/ \_\ | ||
http://bela.io | ||
*/ | ||
/** | ||
\example Sensors/rotary-encoder/render.cpp | ||
Rotary Encoder | ||
================ | ||
Connect a rotary encoder to Bela's digital inputs, detect the direction of the | ||
rotation, and keep track of how far you've gone. | ||
If your encoder has a built-in switch, you can use that to reset the current count. | ||
*/ | ||
|
||
#include <Bela.h> | ||
#include <libraries/Scope/Scope.h> | ||
#include <libraries/Encoder/Encoder.h> | ||
|
||
Encoder gEncoder; | ||
Scope gScope; | ||
// Bela digital input channels connected to the encoder and button | ||
unsigned int kEncChA = 0; | ||
unsigned int kEncChB = 1; | ||
unsigned int kEncChBtn = 2; | ||
|
||
// adjust the values below based on your encoder and wiring | ||
unsigned int kDebouncingSamples = 15; | ||
Encoder::Polarity polarity = Encoder::ANY; // could be ANY, ACTIVE_LOW, ACTIVE_HIGH | ||
|
||
bool setup(BelaContext *context, void *userData) | ||
{ | ||
gScope.setup(3, context->audioSampleRate); | ||
gEncoder.setup(kDebouncingSamples, polarity); | ||
|
||
// Set the digital pins to inputs | ||
pinMode(context, 0, kEncChA, INPUT); | ||
pinMode(context, 0, kEncChB, INPUT); | ||
pinMode(context, 0, kEncChBtn, INPUT); | ||
return true; | ||
} | ||
|
||
bool gButton; | ||
unsigned int holdoff; | ||
void render(BelaContext *context, void *userData) | ||
{ | ||
for(unsigned int n=0; n<context->digitalFrames; n++){ | ||
bool a = digitalRead(context, n, kEncChA); | ||
bool b = digitalRead(context, n, kEncChB); | ||
bool button = digitalRead(context, n, kEncChBtn); | ||
Encoder::Rotation ret = gEncoder.process(a, b); | ||
if(Encoder::NONE != ret) | ||
{ | ||
rt_printf("%s : %3d\n", Encoder::CCW == ret ? "ccw" : "cw ", gEncoder.get()); | ||
} | ||
if(gButton != button) { | ||
gButton = button; | ||
if(button) { | ||
gEncoder.reset(); | ||
rt_printf("reset : %3d\n", gEncoder.get()); | ||
} | ||
} | ||
if(1) | ||
{ | ||
if(Encoder::CCW == ret) | ||
button = 1; | ||
else | ||
button = 0; | ||
|
||
} | ||
gScope.log( // log the values with a vertical offset to make them easier to see | ||
a * 0.5 + 0.333, | ||
b * 0.5 - 0.333, | ||
button * 0.5 - 0.88 | ||
); | ||
} | ||
} | ||
|
||
void cleanup(BelaContext *context, void *userData) | ||
{ | ||
} |
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,66 @@ | ||
#include "Encoder.h" | ||
#include <Bela.h> | ||
|
||
void Encoder::setup(unsigned int debounce, Polarity polarity) | ||
{ | ||
debounce_ = debounce; | ||
reset(); | ||
polarity_ = polarity; | ||
debouncing_ = 0; | ||
primed_ = false; | ||
} | ||
|
||
void Encoder::reset(int position) | ||
{ | ||
position_ = position; | ||
} | ||
|
||
bool Encoder::validEdge(bool a) | ||
{ | ||
return ( | ||
ANY == polarity_ | ||
|| (ACTIVE_LOW == polarity_ && !a) | ||
|| (ACTIVE_HIGH == polarity_ && a) | ||
); | ||
} | ||
|
||
Encoder::Rotation Encoder::process(bool a, bool b) | ||
{ | ||
Rotation ret = NONE; | ||
if(!primed_) { | ||
lastA_ = a_ = a; | ||
primed_ = true; | ||
} | ||
if(a != lastA_) { | ||
if(validEdge(a)) | ||
debouncing_ = debounce_ + 1; | ||
else | ||
a_ = a; | ||
} | ||
|
||
// wait for the data to be stable long enough | ||
// before checking for an updated value | ||
if(1 == debouncing_ && a_ != a) | ||
{ | ||
a_ = a; | ||
if(validEdge(a)) | ||
{ | ||
if(b == a) | ||
ret = CCW; | ||
else | ||
ret = CW; | ||
position_ += ret; | ||
} | ||
} | ||
if(debouncing_) | ||
--debouncing_; | ||
lastA_ = a; | ||
return ret; | ||
} | ||
|
||
int Encoder::get() | ||
{ | ||
return position_; | ||
} | ||
|
||
|
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,78 @@ | ||
#pragma once | ||
|
||
/** | ||
* @brief Connect a quadrature rotary encoder. | ||
* | ||
* Connect a quadrature rotary encoder. | ||
* | ||
* It provides a debouncer to ignore spurious readings due to mechanical | ||
* bouncing of the contacts. | ||
* | ||
* It contains an internal counter which tracks how many steps the encoder has | ||
* moved from its initial position. Position is incremented when it moves | ||
* clockwise and decremented when it movew counter-clockwise. | ||
*/ | ||
class Encoder | ||
{ | ||
public: | ||
typedef enum { | ||
CCW = -1, ///< The encoder rotated counter-clockwise | ||
NONE = 0, ///< The encoder did not rotate | ||
CW = 1, ///< The encoder rotate clockwise | ||
} Rotation; | ||
|
||
/** | ||
* Which edge of the `a` signal denotes a transition. | ||
*/ | ||
typedef enum { | ||
ANY, ///< Trigger on any edge | ||
ACTIVE_LOW, ///< Trigger on negative edges | ||
ACTIVE_HIGH, ///< Trigger on negative edges | ||
} Polarity; | ||
|
||
Encoder() { setup(0, ANY); }; | ||
|
||
/** | ||
* Same as setup(). | ||
*/ | ||
Encoder(unsigned int debounce, Polarity polarity = ANY) { setup(debounce, polarity); }; | ||
|
||
/** | ||
* Set up the encoder with a given debounce interval. | ||
* | ||
* @param debounce the number of calls to process() during which | ||
* changes are ignored after a change in `a` has been detected. | ||
* @param polarity on which edge to trigger. | ||
* | ||
*/ | ||
void setup(unsigned int debounce, Polarity polarity = ANY); | ||
|
||
/** | ||
* Sets the current position of the encoder to the specified value. | ||
* | ||
* @param position The new position (defaults to 0). | ||
*/ | ||
void reset(int position = 0); | ||
|
||
/** | ||
* Process new readings from the encoder's terminals. | ||
* | ||
* @return whether, and in which direction, the encoder has moved in | ||
* this last step. | ||
*/ | ||
Rotation process(bool a, bool b); | ||
|
||
/** | ||
* Get the position of the encoder. | ||
*/ | ||
int get(); | ||
private: | ||
bool validEdge(bool a); | ||
unsigned int debouncing_; | ||
unsigned int debounce_; | ||
int position_; | ||
Polarity polarity_; | ||
bool a_; | ||
bool lastA_; | ||
bool primed_; | ||
}; |
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,17 @@ | ||
name=Encoder | ||
version=1.0.0 | ||
author=Giulio Moro<giulio@bela.io> | ||
maintainer=Giulio Moro<giulio@bela.io>> | ||
description=A class to connect a quadrature encoder. | ||
examples=Sensors/rotary-encoder | ||
license=LGPL 3.0 | ||
url= | ||
board=* | ||
dependencies= | ||
LDFLAGS= | ||
LDLIBS= | ||
CXXFLAGS= | ||
CC= | ||
CXX= | ||
CFLAGS= | ||
CPPFLAGS= |