#include "AiEsp32RotaryEncoder.h"
#include "AiEsp32RotaryEncoderNumberSelector.h"
#include "Arduino.h"
/*
connecting Rotary encoder
Rotary encoder side MICROCONTROLLER side
------------------- ---------------------------------------------------------------------
CLK (A pin) any microcontroler intput pin with interrupt -> in this example pin 32
DT (B pin) any microcontroler intput pin with interrupt -> in this example pin 21
SW (button pin) any microcontroler intput pin with interrupt -> in this example pin 25
GND - to microcontroler GND
VCC microcontroler VCC (then set ROTARY_ENCODER_VCC_PIN -1)
***OR in case VCC pin is not free you can cheat and connect:***
VCC any microcontroler output pin - but set also ROTARY_ENCODER_VCC_PIN 25
in this example pin 25
*/
#define ROTARY_ENCODER_A_PIN 33
#define ROTARY_ENCODER_B_PIN 25
#define ROTARY_ENCODER_BUTTON_PIN 26
#define ROTARY_ENCODER_VCC_PIN -1 /* 27 put -1 of Rotary encoder Vcc is connected directly to 3,3V; else you can use declared output pin for powering rotary encoder */
#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();
//paramaters for button
unsigned int shortPressAfterMiliseconds = 50; //how long short press shoud be. Do not set too low to avoid bouncing (false press events).
unsigned int longPressAfterMiliseconds = 1000; //how long čong press shoud be.
void on_button_short_click() {
Serial.print("button SHORT press ");
Serial.print(millis());
Serial.println(" milliseconds after restart");
} // end void on_button_short_click function
void on_button_long_click() {
Serial.print("button LONG press ");
Serial.print(millis());
Serial.println(" milliseconds after restart");
} // end void on_button_long_click function
void rotary_onButtonClick() {
static unsigned long lastTimeButtonDown = 0;
static bool wasButtonDown = false;
bool isEncoderButtonDown = rotaryEncoder->isEncoderButtonDown();
//isEncoderButtonDown = !isEncoderButtonDown; //uncomment this line if your button is reversed
if (isEncoderButtonDown) {
Serial.print("+"); //REMOVE THIS LINE IF YOU DONT WANT TO SEE
if (!wasButtonDown) {
//start measuring
lastTimeButtonDown = millis();
}
//else we wait since button is still down
wasButtonDown = true;
return;
}
//button is up
if (wasButtonDown) {
Serial.println(""); //REMOVE THIS LINE IF YOU DONT WANT TO SEE
//click happened, lets see if it was short click, long click or just too short
if (millis() - lastTimeButtonDown >= longPressAfterMiliseconds) {
on_button_long_click();
} else if (millis() - lastTimeButtonDown >= shortPressAfterMiliseconds) {
on_button_short_click();
}
}
wasButtonDown = false;
} // end void rotary_onButtonClick function
void rotary_loop() {
int16_t encoderDelta = rotaryEncoder->encoderChanged();
// When just needing to know if direction changed
//if (encoderDelta > 0) {
// Serial.println("CW");
//}
//if (encoderDelta < 0) {
// Serial.println("CCW");
//}
// When getting value
if (encoderDelta != 0){
Serial.print("Value: ");
// Get and print encoder value when not using numberSelector
//int16_t encoderValue = rotaryEncoder.readEncoder();
//Serial.println(encoderValue);
// Get encoder value when using numberSelector
Serial.println(numberSelector.getValue());
}
rotary_onButtonClick();
} // end void rotary_loop function
// Function required for interupts
void IRAM_ATTR readEncoderISR(){
rotaryEncoder->readEncoder_ISR();
} // end void IRAM
void setup() {
Serial.begin(115200);
//Initialize rotary encoder
rotaryEncoder->begin();
rotaryEncoder->setup(readEncoderISR);
//set boundaries and if values should cycle or not
//in this example we will set possible values between 0 and 1000
//and do not cycle from low
//bool circleValues = false;
//rotaryEncoder.setBoundaries(-50, 50, circleValues); //minValue, maxValue, circleValues true|false (when max go to min and vice versa)
/*Rotary acceleration
* in case range to select is huge, for example - select a value between 0 and 1000 and we want 785
* without accelerateion you need long time to get to that number
* Using acceleration, faster you turn, faster will the value raise.
* For fine tuning slow down.
*/
//rotaryEncoder.disableAcceleration(); //acceleration is now enabled by default - disable if you dont need it
//rotaryEncoder.setAcceleration(250); //or set the value - larger number = more accelearation; 0 or 1 means disabled acceleration
// AiEsp32RotaryEncoderNumberSelector is that additional helper which
// will hide calculation for a rotary encoder.
// 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
numberSelector.attachEncoder(rotaryEncoder);
/*
numberSelector.setRange parameters:
float minValue, set minimum value for example -12.0
float maxValue, set maximum value for example 31.5
float step, set step increment, default 1, can be smaller steps like 0.5 or 10
bool cycleValues, set true only if you want going to miminum value after maximum
unsigned int decimals = 0 precision - how many decimal places you want, default is 0
numberSelector.setValue - sets initial value
*/
numberSelector.setRange(-12.0, 31.5, 0.5, false, 1);
numberSelector.setValue(24.3);
}
void loop()
{
//in loop call your custom function which will process rotary encoder values
rotary_loop();
delay(50); //or do whatever you need to do...
}