#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 fanServo;
const int BUTTON_PIN = 2;
int speedState = 0; // 0=OFF, 1=LOW, 2=MED, 3=TURBO
String speedNames[] = {"OFF", "LOW", "MED", "TURBO"};
// Live Battery values logic
int batteryLife = 98;
unsigned long lastBatteryTime = 0;
unsigned long lastDisplayTime = 0;
void setup() {
pinMode(BUTTON_PIN, INPUT_PULLUP);
fanServo.attach(9);
fanServo.write(0); // Rest position at start
if(!display.begin(SSD1306_SWITCHCAPVCC, 0x3C)) {
for(;;);
}
display.clearDisplay();
updateDisplay();
}
void loop() {
unsigned long currentMillis = millis();
// 1. Simple Click Detection Handler
if (digitalRead(BUTTON_PIN) == LOW) {
speedState = (speedState + 1) % 4; // Cycles: 0 -> 1 -> 2 -> 3 -> 0
// Position angles dynamically based on speed modes
if (speedState == 0) fanServo.write(0);
else if (speedState == 1) fanServo.write(45);
else if (speedState == 2) fanServo.write(110);
else if (speedState == 3) fanServo.write(180);
updateDisplay();
delay(300); // Click stabilization pause (Debounce)
}
// 2. Dynamic Battery Consumption Engine
if (speedState > 0) {
int drainInterval = 200000 / speedState; // Higher speeds drain battery faster
if (currentMillis - lastBatteryTime >= drainInterval) {
if (batteryLife > 0) batteryLife--;
lastBatteryTime = currentMillis;
}
}
// 3. Auto Refresh Interface Frame every 300ms
if (currentMillis - lastDisplayTime >= 300) {
updateDisplay();
lastDisplayTime = currentMillis;
}
}
void updateDisplay() {
display.clearDisplay();
display.setTextColor(SSD1306_WHITE);
// Render Current Battery Text Status
display.setTextSize(1);
display.setCursor(10, 8);
display.print("BATTERY: ");
display.print(batteryLife);
display.print("% mAh");
// DRAW CORE FIXES HERE: Correct function syntax layout
// drawRect = Outlined rectangle box frame container
display.drawRect(10, 22, 100, 10, SSD1306_WHITE);
if(batteryLife > 0) {
// fillRect = Filled indicator percentage block graphic
display.fillRect(12, 24, batteryLife, 6, SSD1306_WHITE);
}
// Render active speed mode texts
display.setCursor(10, 44);
display.setTextSize(2);
display.print(speedNames[speedState]);
display.display();
}