#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
// *** Include the desired Adafruit GFX font header ***
#include <Fonts/FreeSansBold18pt7b.h>
// --- SSD1306 Display Setup ---
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
// Use the correct I2C address (0x3C or 0x3D)
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, -1);
// --- Rotary Encoder Setup ---
#define ENCODER_CLK 2
#define ENCODER_DT 3
#define ENCODER_SW A0
// --- Rotary Encoder Variables ---
volatile long encoderCount = 0;
volatile long zeroOffset = 0;
// --- Physical/Resolution Constants ---
const long PPR = 360000; // 360,000 counts for 0.001 degree resolution
const float DEGREE_PER_COUNT = 360.0 / PPR;
// Set to 2 decimal places. A 3-digit integer + 2 decimals fits best with this font.
const int NUM_DECIMAL_PLACES = 3;
// --- Interrupt Service Routine (ISR) ---
void readEncoder() {
if (digitalRead(ENCODER_DT) == HIGH) {
encoderCount++;
} else {
encoderCount--;
}
}
void setup() {
Serial.begin(115200);
// --- Encoder Pins Setup ---
pinMode(ENCODER_CLK, INPUT_PULLUP);
pinMode(ENCODER_DT, INPUT_PULLUP);
pinMode(ENCODER_SW, INPUT_PULLUP);
attachInterrupt(digitalPinToInterrupt(ENCODER_CLK), readEncoder, RISING);
// --- Display Setup ---
if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
Serial.println(F("SSD1306 allocation failed. Check wiring and address (0x3C or 0x3D)."));
for(;;);
}
display.display();
delay(1000);
display.setTextColor(SSD1306_WHITE);
display.clearDisplay();
}
void loop() {
// --- 1. Read Button and Zero Function ---
if (digitalRead(ENCODER_SW) == LOW) {
zeroOffset = encoderCount;
delay(200);
}
// --- 2. Calculate Angle (Floating Point) ---
long currentCount = encoderCount - zeroOffset;
float angle = currentCount * DEGREE_PER_COUNT;
// Apply the modulo 360 wrap
angle = fmod(angle, 360.0);
if (angle < 0) {
angle += 360.0;
}
// --- 3. Format and Display ---
display.clearDisplay();
// Set up the output string with 2 decimal places ("XXX.XX")
char angleString[8]; // Buffer large enough for "360.00" + null terminator
dtostrf(angle, 6, NUM_DECIMAL_PLACES, angleString);
// **Display Angle (Custom GFX Font)**
display.setTextSize(1); // ALWAYS set size to 1 when using GFX fonts
display.setFont(&FreeSansBold18pt7b); // Set the custom font
display.setCursor(0, 30); // Center the font vertically
display.print(angleString);
// **Display Label (Default System Font)**
// We switch back to the default font to save space for the label
display.setFont(NULL); // Switch back to the default 5x7 system font
display.setTextSize(1);
display.setCursor(0, 50); // Position the label below
display.println("DEGREES (XX.XX)");
display.display();
delay(10);
}