#include <Wire.h>
#include <LiquidCrystal_I2C.h>
// LCD Configuration
LiquidCrystal_I2C lcd(0x27, 16, 2); // Change address if needed
// Rotary Encoder Pins
const int encoderPinA = 18;
const int encoderPinB = 19;
// Potentiometer Pin
const int potPin = 34; // Analog input
// Encoder Variables
volatile int pulseCount = 0;
unsigned long lastTime = 0;
float rpm = 0;
// Encoder specification
const int pulsesPerRevolution = 20;
// Interrupt Service Routine for Encoder
void IRAM_ATTR encoderISR() {
pulseCount++;
}
void setup() {
Serial.begin(115200);
// LCD Setup
lcd.init();
lcd.backlight();
lcd.setCursor(0, 0);
lcd.print("RPM + POT Monitor");
// Encoder Pins
pinMode(encoderPinA, INPUT_PULLUP);
pinMode(encoderPinB, INPUT_PULLUP);
// Attach interrupt to encoder A pin
attachInterrupt(digitalPinToInterrupt(encoderPinA), encoderISR, RISING);
lastTime = millis();
}
void loop() {
unsigned long currentTime = millis();
// Read potentiometer value (0 - 4095)
int potValue = analogRead(potPin);
// Map potentiometer to simulated RPM range
int simulatedRPM = map(potValue, 0, 4095, 0, 5000);
// Calculate actual encoder RPM every second
if (currentTime - lastTime >= 1000) {
rpm = (pulseCount / (float)pulsesPerRevolution) * 60.0;
pulseCount = 0;
lastTime = currentTime;
// Print to Serial Monitor
Serial.print("Encoder RPM: ");
Serial.print(rpm);
Serial.print(" | Pot Value: ");
Serial.print(potValue);
Serial.print(" | Simulated RPM: ");
Serial.println(simulatedRPM);
// Display on LCD
lcd.clear();
lcd.setCursor(0, 0);
lcd.print("EncRPM:");
lcd.print(rpm, 0);
lcd.setCursor(0, 1);
lcd.print("PotRPM:");
lcd.print(simulatedRPM);
}
}