#include <Arduino.h>
#include <LiquidCrystal_I2C.h>
#define CLK_PIN 25 // ESP32 pin GPIO25 connected to the rotary encoder's CLK pin
#define DT_PIN 26 // ESP32 pin GPIO26 connected to the rotary encoder's DT pin
#define SW_PIN 27 // ESP32 pin GPIO27 connected to the rotary encoder's SW pin
// set the LCD number of columns and rows
#define lcdColumns 20
#define lcdRows 4
#define lcdAdress 0x27
LiquidCrystal_I2C lcd(0x27, lcdColumns, lcdRows); // set the LCD address to 0x27 for a 20 chars and 4 line display
#define DIRECTION_CW 0 // clockwise direction
#define DIRECTION_CCW 1 // counter-clockwise direction
#define DEBOUNCE_TIME 50 // debounce time in milliseconds
volatile int counter = 0;
volatile int sliderValue = 10;
int prevCounter = counter;
int prevSliderValue = sliderValue;
#define DEBOUNCE_TIME_BUTTON 50
volatile bool buttonPressed = false;
volatile unsigned long lastDebounceTime = 0;
volatile bool buttonSignalSent = false;
#define SET_STATE true
#define SHOW_STATE false
volatile bool set = SHOW_STATE;
#define SET_COUNTER false
#define SET_SLIDER true
volatile bool state = SET_COUNTER;
#define START_MOTORS true
#define STOP_MOTORS false
volatile bool runMotors = STOP_MOTORS;
#define PATTERN_1 0
#define PATTERN_2 1
#define PATTERN_3 2
volatile int currentPattern = PATTERN_1;
int motorCounters[3][3] = { // make volatile ?
{200, 100, 150},
{500, 400, 300},
{150, 200, 400}
};
void IRAM_ATTR ISR_encoder() {
int direction = DIRECTION_CW;
unsigned long last_time; // for debouncing
if ((millis() - last_time) < DEBOUNCE_TIME) // debounce time is 50ms
return;
if (digitalRead(DT_PIN) == HIGH) {
// the encoder is rotating in counter-clockwise direction => decrease the counter
if (state == SET_SLIDER) {
if (sliderValue > 0)
sliderValue--;
} else if (state == SET_COUNTER){
counter--;
}
direction = DIRECTION_CCW;
} else {
// the encoder is rotating in clockwise direction => increase the counter
if (state == SET_SLIDER) {
if (sliderValue < 10)
sliderValue++;
} else if (state == SET_COUNTER){
counter++;
}
direction = DIRECTION_CW;
}
last_time = millis();
}
void IRAM_ATTR ISR_button() {
if ((millis() - lastDebounceTime) > DEBOUNCE_TIME_BUTTON) {
buttonPressed = true;
lastDebounceTime = millis();
}
}
void setup() {
Serial.begin(9600);
set = false;
state = SET_COUNTER;
sliderValue = 10;
Serial.println(String(sliderValue));
Serial.println(String(state));
Serial.println(String(set));
// initialize the LCD
lcd.init();
// configure encoder pins as inputs
pinMode(CLK_PIN, INPUT);
pinMode(DT_PIN, INPUT);
pinMode(SW_PIN, INPUT_PULLUP); // Set button pin as input with internal pull-up resistor
// use interrupt for CLK pin is enough
// call ISR_encoder() when CLK pin changes from LOW to HIGH
attachInterrupt(digitalPinToInterrupt(CLK_PIN), ISR_encoder, RISING);
attachInterrupt(digitalPinToInterrupt(SW_PIN), ISR_button, FALLING); // Trigger ISR on falling edge (button press)
}
void printCentered(String text, int row) {
int textLength = text.length();
int startingColumn = (lcdColumns - textLength) / 2;
lcd.setCursor(startingColumn, row);
lcd.print(text);
}
String stringSlider(bool set) {
String output = "";
output += "speed:";
set ? output += "{" : output += "[";
for (int i = 0; i < 10; i++) {
if (i < sliderValue) {
output += "#";
} else {
output += " ";
}
}
set ? output += "}" : output += "]";
return output;
}
void printMessage() {
//printCentered("***Pattern Engine***", 0);
printCentered("current Pattern: " + String(currentPattern), 0);
int normalizedCounter = counter % 6;
if (normalizedCounter < 0) {
normalizedCounter += 6;
}
if (normalizedCounter == 0) {
printCentered("<P1> P2 P3 ", 1);
if (buttonPressed) {
currentPattern = PATTERN_1;
buttonSignalSent = true;
}
}
else if (normalizedCounter == 1) {
printCentered(" P1 <P2> P3 ", 1);
if (buttonPressed) {
currentPattern = PATTERN_2;
buttonSignalSent = true;
}
}
else if (normalizedCounter == 2) {
printCentered(" P1 P2 <P3>", 1);
if (buttonPressed) {
currentPattern = PATTERN_3;
buttonSignalSent = true;
}
}
else {
printCentered(" P1 P2 P3 ", 1);
}
if (normalizedCounter == 3) {
printCentered("<start> stop ", 2);
if (buttonPressed) {
runMotors = START_MOTORS;
buttonSignalSent = true;
}
}
else if (normalizedCounter == 4) {
printCentered(" start <stop>", 2);
if (buttonPressed) {
runMotors = STOP_MOTORS;
buttonSignalSent = true;
}
}
else {
printCentered(" start stop ", 2);
}
if (normalizedCounter == 5) {
printCentered("<" + stringSlider(set) + ">", 3);
if (buttonPressed && state == SET_COUNTER) {
set = SET_STATE;
state = SET_SLIDER;
buttonSignalSent = true;
}
else if (buttonPressed && state == SET_SLIDER) {
set = SHOW_STATE;
state = SET_COUNTER;
buttonSignalSent = true;
}
}
else {
printCentered(" " + stringSlider(set) + " ", 3);
}
}
void loop() {
printMessage();
if (prevCounter != counter) {
Serial.print("Rotary Encoder:: counter: ");
Serial.println(counter);
prevCounter = counter;
}
if (prevSliderValue != sliderValue) {
Serial.print("Rotary Encoder:: Slider Value: ");
Serial.println(sliderValue);
prevSliderValue = sliderValue;
}
if (buttonSignalSent) {
Serial.println("The button is pressed");
buttonPressed = false; // Reset the buttonPressed flag
buttonSignalSent = false; // Reset the buttonSignalSent flag
}
}