#include <U8g2lib.h>
// Pin definitions
#define RED_PIN 5
#define GREEN_PIN 6
#define BLUE_PIN 7
#define WARM_WHITE_PIN 9
#define COOL_WHITE_PIN 10
#define ENTER_BUTTON_PIN 2
#define UP_BUTTON_PIN 3
#define DOWN_BUTTON_PIN 4
#define BATTERY_PIN A0
// OLED display instance
U8G2_SSD1306_128X64_NONAME_F_HW_I2C u8g2(U8G2_R0, /* reset=*/ U8X8_PIN_NONE);
// Variables for menu and control
enum Mode { RGB, WHITE, AUTO_RGB };
Mode currentMode = RGB;
int menuIndex = 0; // To track parameter selection
int hue = 0;
int rgbBrightness = 255;
int whiteBrightness = 255;
int whiteTemp = 127;
int batteryLevel = 100;
unsigned long previousMillis = 0;
long interval = 1000; // Interval for color switching
unsigned long enterButtonPressTime = 0;
bool enterButtonLongPress = false;
bool isParameterSelection = false;
void setup() {
// Initialize OLED display
u8g2.begin();
// Set pin modes for buttons and LEDs
pinMode(ENTER_BUTTON_PIN, INPUT_PULLUP);
pinMode(UP_BUTTON_PIN, INPUT_PULLUP);
pinMode(DOWN_BUTTON_PIN, INPUT_PULLUP);
pinMode(RED_PIN, OUTPUT);
pinMode(GREEN_PIN, OUTPUT);
pinMode(BLUE_PIN, OUTPUT);
pinMode(WARM_WHITE_PIN, OUTPUT);
pinMode(COOL_WHITE_PIN, OUTPUT);
// Initial display
updateDisplay();
}
void loop() {
// Check button presses and update menu or values
handleButtons();
// Update RGB or white LED settings based on the menu selection
if (currentMode == RGB) {
setRGBColor();
} else if (currentMode == WHITE) {
setWhiteTemperature();
} else if (currentMode == AUTO_RGB) {
autoSwitchColor();
}
// Update battery level
batteryLevel = analogRead(BATTERY_PIN) * (100.0 / 1023.0); // Example battery level calculation
}
void handleButtons() {
if (digitalRead(ENTER_BUTTON_PIN) == LOW) {
if (enterButtonPressTime == 0) {
enterButtonPressTime = millis();
} else if (millis() - enterButtonPressTime > 1000) {
enterButtonLongPress = true;
enterButtonPressTime = 0;
// Long press detected: switch between mode selection and parameter selection
isParameterSelection = !isParameterSelection;
updateDisplay();
}
} else {
if (enterButtonPressTime > 0 && !enterButtonLongPress) {
// Short press detected: move to next parameter
if (isParameterSelection) {
menuIndex = (menuIndex + 1) % 3;
} else {
currentMode = static_cast<Mode>((currentMode + 1) % 3);
}
updateDisplay();
}
enterButtonPressTime = 0;
enterButtonLongPress = false;
}
if (digitalRead(UP_BUTTON_PIN) == LOW) {
adjustValue(1);
delay(200); // Debounce delay
updateDisplay();
}
if (digitalRead(DOWN_BUTTON_PIN) == LOW) {
adjustValue(-1);
delay(200); // Debounce delay
updateDisplay();
}
}
void adjustValue(int change) {
if (isParameterSelection) {
switch (currentMode) {
case RGB:
if (menuIndex == 1) {
hue = (hue + change) % 360;
if (hue < 0) hue += 360;
} else if (menuIndex == 2) {
rgbBrightness = constrain(rgbBrightness + change, 0, 255);
}
break;
case WHITE:
if (menuIndex == 1) {
whiteTemp = constrain(whiteTemp + change, 0, 255);
} else if (menuIndex == 2) {
whiteBrightness = constrain(whiteBrightness + change, 0, 255);
}
break;
case AUTO_RGB:
if (menuIndex == 1) {
interval = constrain(interval + change * 100, 100, 5000);
}
break;
}
}
}
void setRGBColor() {
int red, green, blue;
hsvToRgb(hue, 255, rgbBrightness, red, green, blue);
analogWrite(RED_PIN, red);
analogWrite(GREEN_PIN, green);
analogWrite(BLUE_PIN, blue);
analogWrite(WARM_WHITE_PIN, 0);
analogWrite(COOL_WHITE_PIN, 0);
}
void setWhiteTemperature() {
analogWrite(RED_PIN, 0);
analogWrite(GREEN_PIN, 0);
analogWrite(BLUE_PIN, 0);
analogWrite(WARM_WHITE_PIN, map(whiteTemp, 0, 255, 0, whiteBrightness));
analogWrite(COOL_WHITE_PIN, map(255 - whiteTemp, 0, 255, 0, whiteBrightness));
}
void autoSwitchColor() {
unsigned long currentMillis = millis();
if (currentMillis - previousMillis >= interval) {
previousMillis = currentMillis;
hue = (hue + 60) % 360; // Change hue every interval
setRGBColor();
}
}
void updateDisplay() {
u8g2.clearBuffer();
u8g2.setFont(u8g2_font_ncenB08_tr); // Regular font
// Battery icon and percentage
u8g2.drawFrame(0, 0, 32, 12);
u8g2.drawBox(2, 2, batteryLevel * 0.28, 8);
u8g2.setCursor(36, 10);
u8g2.print(batteryLevel);
u8g2.print("%");
// Menu display
if (!isParameterSelection) {
switch (currentMode) {
case RGB:
u8g2.drawStr(0, 25, "Mode: RGB");
break;
case WHITE:
u8g2.drawStr(0, 25, "Mode: White");
break;
case AUTO_RGB:
u8g2.drawStr(0, 25, "Mode: Auto RGB");
break;
}
} else {
switch (currentMode) {
case RGB:
if (menuIndex == 1) {
u8g2.drawStr(0, 25, "Hue:");
u8g2.setCursor(0, 40);
u8g2.print(hue);
} else if (menuIndex == 2) {
u8g2.drawStr(0, 25, "Brightness:");
u8g2.setCursor(0, 40);
u8g2.print(rgbBrightness);
}
break;
case WHITE:
if (menuIndex == 1) {
u8g2.drawStr(0, 25, "Temperature:");
u8g2.setCursor(0, 40);
u8g2.print(map(whiteTemp, 0, 255, 3000, 6000));
} else if (menuIndex == 2) {
u8g2.drawStr(0, 25, "Brightness:");
u8g2.setCursor(0, 40);
u8g2.print(whiteBrightness);
}
break;
case AUTO_RGB:
if (menuIndex == 1) {
u8g2.drawStr(0, 25, "Interval:");
u8g2.setCursor(0, 40);
u8g2.print(interval / 1000);
u8g2.print("s");
}
break;
}
}
u8g2.sendBuffer();
}
void hsvToRgb(int h, int s, int v, int &r, int &g, int &b) {
float hf = h / 60.0;
int i = floor(hf);
float f = hf - i;
float pv = v * (1 - s / 255.0);
float qv = v * (1 - s / 255.0 * f);
float tv = v * (1 - s / 255.0 * (1 - f));
switch (i) {
case 0:
r = v;
g = tv;
b = pv;
break;
case 1:
r = qv;
g = v;
b = pv;
break;
case 2:
r = pv;
g = v;
b = tv;
break;
case 3:
r = pv;
g = qv;
b = v;
break;
case 4:
r = tv;
g = pv;
b = v;
break;
case 5:
r = v;
g = pv;
b = qv;
break;
}
r = constrain(r, 0, 255);
g = constrain(g, 0, 255);
b = constrain(b, 0, 255);
}