Skip to content

Commit

Permalink
version 1.2: AiEsp32RotaryEncoderNumberSelector
Browse files Browse the repository at this point in the history
  • Loading branch information
igorantolic committed Feb 28, 2021
1 parent 68e0deb commit 6993a63
Show file tree
Hide file tree
Showing 6 changed files with 176 additions and 21 deletions.
64 changes: 64 additions & 0 deletions examples/Number-select/Number-select.ino
Original file line number Diff line number Diff line change
@@ -0,0 +1,64 @@
#include "AiEsp32RotaryEncoder.h"
#include "AiEsp32RotaryEncoderNumberSelector.h"
#define ROTARY_ENCODER_A_PIN 32
#define ROTARY_ENCODER_B_PIN 21
#define ROTARY_ENCODER_BUTTON_PIN 25
#define ROTARY_ENCODER_STEPS 4
AiEsp32RotaryEncoder *rotaryEncoder = new AiEsp32RotaryEncoder(ROTARY_ENCODER_A_PIN, ROTARY_ENCODER_B_PIN, ROTARY_ENCODER_BUTTON_PIN, -1, ROTARY_ENCODER_STEPS);
AiEsp32RotaryEncoderNumberSelector numberSelector = AiEsp32RotaryEncoderNumberSelector();
/*
In this example an additional functionality is used.
AiEsp32RotaryEncoderNumberSelector is that additional helper which will hide calculation for a rotary encoder.
In example 1 - you can select some temperature between -12 and +31.5 degrees in steps by 0.5 degrees; using precision of 1 decimal
In example 2 - you can select some frequency between 6999000 and 7000000 Hz in steps by 10 Hz; using precision of 0 decimal (integer)
Internally AiEsp32RotaryEncoderNumberSelector will do the math and set the most apropriate acceleration, min and max values for you
use setRange to set parameters
use setValue for a default/initial value
and finally read the value with getValue
So, this value is actually value you need
In code bellow comment / uncomment example 1 or 2
*/

void rotary_onButtonClick()
{
static unsigned long lastTimePressed = 0;
if (millis() - lastTimePressed < 200)
return;
lastTimePressed = millis();

Serial.print("Selected value is ");
Serial.print(numberSelector.getValue(), 1);
Serial.println(" ***********************");
}

void setup()
{
Serial.begin(115200);
rotaryEncoder->begin();
rotaryEncoder->setup(
[] { rotaryEncoder->readEncoder_ISR(); },
[] { rotary_onButtonClick(); });

numberSelector.attachEncoder(rotaryEncoder);
//example 1
//numberSelector.setRange(-12.0, 31.5, 0.5, false, 1);
//numberSelector.setValue(24.3);
//example 2
numberSelector.setRange(6999000.0, 7000000.0, 10, false, 0);
numberSelector.setValue(6999500.0);
}

void loop()
{
if (rotaryEncoder->encoderChanged())
{
Serial.print(numberSelector.getValue());
Serial.println(" ");
}
}
4 changes: 2 additions & 2 deletions library.properties
Original file line number Diff line number Diff line change
@@ -1,9 +1,9 @@
name=Ai Esp32 Rotary Encoder
version=1.1
version=1.2
author=Igor Antolic (adapted code from github.com/marcmerlin/IoTuz)
maintainer=Igor Antolic <iantolic@gmail.com>
sentence=Easy implement rotary encoder to your application
paragraph=Supports acceleration, setting boundaries. Works with ESP32.
paragraph=Supports acceleration, setting boundaries. Works with ESP32. New in version 1.2: AiEsp32RotaryEncoderNumberSelector introduced to help selecting for example range -12 do 31.5 in steps of 0.5.
category=Device Control
url=https://github.com/iantolic/ai-esp32-rotary-encoder.git
architectures=esp32
18 changes: 9 additions & 9 deletions src/AiEsp32RotaryEncoder.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -27,9 +27,9 @@ void IRAM_ATTR AiEsp32RotaryEncoder::readEncoder_ISR()

if (currentDirection != 0)
{
int16_t prevRotaryPosition = this->encoder0Pos / this->encoderSteps;
long prevRotaryPosition = this->encoder0Pos / this->encoderSteps;
this->encoder0Pos += currentDirection;
int16_t newRotaryPosition = this->encoder0Pos / this->encoderSteps;
long newRotaryPosition = this->encoder0Pos / this->encoderSteps;

if (newRotaryPosition != prevRotaryPosition && rotaryAccelerationCoef > 1)
{
Expand Down Expand Up @@ -122,28 +122,28 @@ AiEsp32RotaryEncoder::AiEsp32RotaryEncoder(uint8_t encoder_APin, uint8_t encoder
pinMode(this->encoderBPin, INPUT_PULLDOWN);
}

void AiEsp32RotaryEncoder::setBoundaries(int16_t minEncoderValue, int16_t maxEncoderValue, bool circleValues)
void AiEsp32RotaryEncoder::setBoundaries(long minEncoderValue, long maxEncoderValue, bool circleValues)
{
this->_minEncoderValue = minEncoderValue * this->encoderSteps;
this->_maxEncoderValue = maxEncoderValue * this->encoderSteps;

this->_circleValues = circleValues;
}

int16_t AiEsp32RotaryEncoder::readEncoder()
long AiEsp32RotaryEncoder::readEncoder()
{
return (this->encoder0Pos / this->encoderSteps);
}

void AiEsp32RotaryEncoder::setEncoderValue(int16_t newValue)
void AiEsp32RotaryEncoder::setEncoderValue(long newValue)
{
reset(newValue);
}

int16_t AiEsp32RotaryEncoder::encoderChanged()
long AiEsp32RotaryEncoder::encoderChanged()
{
int16_t _encoder0Pos = readEncoder();
int16_t encoder0Diff = _encoder0Pos - this->lastReadEncoder0Pos;
long _encoder0Pos = readEncoder();
long encoder0Diff = _encoder0Pos - this->lastReadEncoder0Pos;

this->lastReadEncoder0Pos = _encoder0Pos;

Expand Down Expand Up @@ -179,7 +179,7 @@ ButtonState AiEsp32RotaryEncoder::currentButtonState()
return buttonState;
}

void AiEsp32RotaryEncoder::reset(int16_t newValue_)
void AiEsp32RotaryEncoder::reset(long newValue_)
{
newValue_ = newValue_ * this->encoderSteps;
this->encoder0Pos = newValue_;
Expand Down
20 changes: 10 additions & 10 deletions src/AiEsp32RotaryEncoder.h
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,7 @@ class AiEsp32RotaryEncoder
private:
portMUX_TYPE mux = portMUX_INITIALIZER_UNLOCKED;
portMUX_TYPE buttonMux = portMUX_INITIALIZER_UNLOCKED;
volatile int16_t encoder0Pos = 0;
volatile long encoder0Pos = 0;

volatile int8_t lastMovementDirection = 0; //1 right; -1 left
volatile unsigned long lastMovementAt = 0;
Expand All @@ -45,13 +45,13 @@ class AiEsp32RotaryEncoder
uint8_t encoderBPin = AIESP32ROTARYENCODER_DEFAULT_B_PIN;
uint8_t encoderButtonPin = AIESP32ROTARYENCODER_DEFAULT_BUT_PIN;
uint8_t encoderVccPin = AIESP32ROTARYENCODER_DEFAULT_VCC_PIN;
int16_t encoderSteps = AIESP32ROTARYENCODER_DEFAULT_STEPS;
long encoderSteps = AIESP32ROTARYENCODER_DEFAULT_STEPS;

int16_t _minEncoderValue = -1 << 15;
int16_t _maxEncoderValue = 1 << 15;
long _minEncoderValue = -1 << 15;
long _maxEncoderValue = 1 << 15;

uint8_t old_AB;
int16_t lastReadEncoder0Pos;
long lastReadEncoder0Pos;
bool previous_butt_state;

ButtonState buttonState;
Expand All @@ -67,19 +67,19 @@ class AiEsp32RotaryEncoder
uint8_t encoderButtonPin = AIESP32ROTARYENCODER_DEFAULT_BUT_PIN,
uint8_t encoderVccPin = AIESP32ROTARYENCODER_DEFAULT_VCC_PIN,
uint8_t encoderSteps = AIESP32ROTARYENCODER_DEFAULT_STEPS);
void setBoundaries(int16_t minValue = -100, int16_t maxValue = 100, bool circleValues = false);
void setBoundaries(long minValue = -100, long maxValue = 100, bool circleValues = false);
void IRAM_ATTR readEncoder_ISR();
void IRAM_ATTR readButton_ISR();

void setup(void (*ISR_callback)(void));
void setup(void (*ISR_callback)(void), void (*ISR_button)(void));
void begin();
void reset(int16_t newValue = 0);
void reset(long newValue = 0);
void enable();
void disable();
int16_t readEncoder();
void setEncoderValue(int16_t newValue);
int16_t encoderChanged();
long readEncoder();
void setEncoderValue(long newValue);
long encoderChanged();
ButtonState currentButtonState();
unsigned long getAcceleration() { return this->rotaryAccelerationCoef; }
void setAcceleration(unsigned long acceleration) { this->rotaryAccelerationCoef = acceleration; }
Expand Down
Empty file.
91 changes: 91 additions & 0 deletions src/AiEsp32RotaryEncoderNumberSelector.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,91 @@
#pragma once

#include <Arduino.h>
#include "AiEsp32RotaryEncoder.h"
/*
setRange (float min, max, step)
100,500,25
88 , 104 , 0.05
coef = 1/step
range min/step, max/step -> 4 - 20
realValue = value*step -> 6*25 =150
*/
//#define DEBUG_NUM_SEL

class AiEsp32RotaryEncoderNumberSelector
{
private:
float minValue = 0;
float maxValue = 100;
float step = 2;
float coeficient = 1;
AiEsp32RotaryEncoder *encoder;

public:
AiEsp32RotaryEncoderNumberSelector(AiEsp32RotaryEncoder *encoderInstance = NULL)
{
encoder = encoderInstance;
}

void attachEncoder(AiEsp32RotaryEncoder *encoderInstance = NULL)
{
encoder = encoderInstance;
}

void setRange(float minValue, float maxValue, float step, bool cycleValues, unsigned int decimals = 0)
{
this->minValue = minValue;
this->maxValue = maxValue;
this->coeficient = pow(10.0, decimals);
if (maxValue < minValue)
coeficient *= -1.0;
this->step = step * this->coeficient;

long minEncoderValue = (long)((this->coeficient * this->minValue) / this->step);
long maxEncoderValue = (long)((this->coeficient * this->maxValue) / this->step);
long range = maxEncoderValue - minEncoderValue;

encoder->setBoundaries(minEncoderValue, maxEncoderValue, cycleValues);

if (range < 20)
encoder->setAcceleration(0);
else if (range < 60)
encoder->setAcceleration(20);
else if (range < 200)
encoder->setAcceleration(100);
else if (range < 1000)
encoder->setAcceleration(300);
else
encoder->setAcceleration(500);

#ifdef DEBUG_NUM_SEL
Serial.println(minEncoderValue);
Serial.println(maxEncoderValue);
Serial.println(range);
Serial.println(step);
Serial.println(coeficient);

#endif
}

void setValue(float value)
{
long encoderValue = (long)((coeficient * value) / step);
encoder->setEncoderValue(encoderValue);
}

float getValue()
{
float encoderValue = 1.0 * encoder->readEncoder();
float value = encoderValue * step / coeficient;

#ifdef DEBUG_NUM_SEL
Serial.print(encoderValue);
Serial.print(" -> ");
Serial.println(value);
#endif
return value;
}
};

0 comments on commit 6993a63

Please sign in to comment.