#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <Servo.h>
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);
Servo myServo;
// Encoder pins
#define CLK 2
#define DT 3
#define SW 4
int lastCLK;
int angle = 90;
int stepSize = 5;
bool lastButton = HIGH;
int buttonMode = 0;
void setup() {
pinMode(CLK, INPUT);
pinMode(DT, INPUT);
pinMode(SW, INPUT_PULLUP);
myServo.attach(9);
myServo.write(angle);
lastCLK = digitalRead(CLK);
display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
drawUI();
}
void loop() {
readEncoder();
readButton();
}
void readEncoder() {
int currentCLK = digitalRead(CLK);
if (currentCLK != lastCLK && currentCLK == HIGH) {
bool direction = digitalRead(DT);
// ---- HARD SYNC LOGIC ----
if (direction == HIGH && angle < 180) {
angle += stepSize;
}
else if (direction == LOW && angle > 0) {
angle -= stepSize;
}
angle = constrain(angle, 0, 180);
myServo.write(angle);
drawUI();
}
lastCLK = currentCLK;
}
void readButton() {
bool btn = digitalRead(SW);
if (lastButton == HIGH && btn == LOW) {
buttonMode++;
if (buttonMode == 1) angle = 90;
else if (buttonMode == 2) angle = 180;
else {
angle = 0;
buttonMode = 0;
}
myServo.write(angle);
drawUI();
delay(250);
}
lastButton = btn;
}
void drawUI() {
display.clearDisplay();
// ---- Progress Bar (TOP) ----
int barX = 10, barY = 6, barW = 108, barH = 12;
display.drawRect(barX, barY, barW, barH, SSD1306_WHITE);
int fill = map(angle, 0, 180, 0, barW - 2);
display.fillRect(barX + 1, barY + 1, fill, barH - 2, SSD1306_WHITE);
// Scale
display.setTextSize(1);
display.setCursor(8, 22); display.print("0");
display.setCursor(58, 22); display.print("90");
display.setCursor(104, 22); display.print("180");
// ---- Angle Text (BOTTOM) ----
display.setCursor(10, 45);
display.print("Servo Angle:");
display.setTextSize(2);
display.setCursor(85, 40);
display.print(angle);
display.print((char)247);
display.display();
}