#include <Wire.h> // Standard I2C library for ESP32
#include <LiquidCrystal_I2C.h> // LCD I2C library
// Pin Definitions
const int potPin = 34; // Slide Potentiometer connected to GPIO34 (Analog Input)
const int encCLK = 25; // Rotary Encoder CLK connected to GPIO25
const int encDT = 26; // Rotary Encoder DT connected to GPIO26
const int encSW = 33; // Rotary Encoder Switch connected to GPIO33
const int buttonPin = 32; // Pushbutton connected to GPIO32
// LCD Settings
LiquidCrystal_I2C lcd(0x27, 16, 2); // LCD I2C address, 16 chars, 2 rows
// Global Variables
int volume = 0;
int songPosition = 0; // This will hold the position value, starting at 0
String direction = "CW"; // Holds direction of rotation ("CW" for clockwise, "CCW" for counterclockwise)
bool songPlaying = false; // For tracking play/stop status
int lastCLKState = LOW; // Previous state of the CLK pin
int lastButtonState = HIGH; // Previous state of the button pin
void setup() {
// Initialize Serial Monitor for debugging
Serial.begin(9600);
// Initialize pins
pinMode(potPin, INPUT);
pinMode(encCLK, INPUT);
pinMode(encDT, INPUT);
pinMode(encSW, INPUT_PULLUP);
pinMode(buttonPin, INPUT_PULLUP);
// Initialize I2C for the LCD
Wire.begin(); // Default I2C pins: SDA on GPIO21 and SCL on GPIO22
// Initialize LCD
lcd.begin(16, 2); // 16 columns and 2 rows
lcd.backlight(); // Turn on the LCD backlight
// Display initial values on the LCD
lcd.setCursor(0, 0);
lcd.print("Vol: 0 Stop"); // Initial volume and play/stop state
lcd.setCursor(0, 1);
lcd.print("Pos: 0 CW"); // Initial position and direction
lastCLKState = digitalRead(encCLK); // Set initial state
}
void loop() {
// Handle Slide Potentiometer (Volume Control)
int potValue = analogRead(potPin);
volume = map(potValue, 0, 4095, 0, 127); // Map potentiometer value (0-4095) to range (0-127)
// Update Volume and Play/Stop status on LCD
lcd.setCursor(5, 0);
lcd.print(volume);
lcd.print(" "); // Pad with space to clear any leftover digits
lcd.print(songPlaying ? "Play " : "Stop");
// Handle Rotary Encoder (Song Position Control)
int currentCLKState = digitalRead(encCLK);
int currentDTState = digitalRead(encDT);
if (currentCLKState != lastCLKState) { // Detect CLK state change (rising or falling edge)
if (currentCLKState == HIGH && currentDTState == LOW) {
// Clockwise rotation
direction = "CW";
songPosition++; // Increment the song position
}
else if (currentCLKState == HIGH && currentDTState == HIGH) {
// Counterclockwise rotation
direction = "CCW";
songPosition--; // Decrement the song position
}
// Constrain song position to stay within -10 to 10
songPosition = constrain(songPosition, -10, 10);
// Update the LCD Display for position and direction
lcd.setCursor(0, 1);
lcd.print("Pos: ");
lcd.print(songPosition); // Display the song position
lcd.print(" "); // Clear any leftover characters
lcd.print(direction); // Display the direction (CW or CCW)
lcd.print(" "); // Clear leftover characters
}
lastCLKState = currentCLKState; // Update the last state
// Handle Pushbutton (Play/Stop Toggle)
int buttonState = digitalRead(buttonPin);
if (buttonState == LOW && lastButtonState == HIGH) {
songPlaying = !songPlaying; // Toggle play/stop state
// Update Play/Stop status on LCD immediately next to volume
lcd.setCursor(5, 0);
lcd.print(volume);
lcd.print(" ");
lcd.print(songPlaying ? "Play " : "Stop ");
}
lastButtonState = buttonState; // Update button state for next loop
// Small delay to prevent rapid flickering
delay(50);
}
esp:0
esp:2
esp:4
esp:5
esp:12
esp:13
esp:14
esp:15
esp:16
esp:17
esp:18
esp:19
esp:21
esp:22
esp:23
esp:25
esp:26
esp:27
esp:32
esp:33
esp:34
esp:35
esp:3V3
esp:EN
esp:VP
esp:VN
esp:GND.1
esp:D2
esp:D3
esp:CMD
esp:5V
esp:GND.2
esp:TX
esp:RX
esp:GND.3
esp:D1
esp:D0
esp:CLK
btn1:1.l
btn1:2.l
btn1:1.r
btn1:2.r
lcd1:GND
lcd1:VCC
lcd1:SDA
lcd1:SCL
encoder1:CLK
encoder1:DT
encoder1:SW
encoder1:VCC
encoder1:GND
pot1:VCC
pot1:SIG
pot1:GND