#include <U8x8lib.h>
#include <EncButton.h>
#include <FastLED.h>
// Конфигурация OLED дисплея
U8X8_SSD1306_128X64_NONAME_HW_I2C u8x8(/* reset=*/ U8X8_PIN_NONE);
// Конфигурация энкодера
#define ENC_CLK 4
#define ENC_DT 3
#define ENC_SW 2
EncButton enc(ENC_CLK, ENC_DT, ENC_SW); // Простая инициализация без шаблонов
// Конфигурация LED ленты
#define LED_PIN 5
#define NUM_LEDS 16
CRGB leds[NUM_LEDS];
// Состояние системы
enum Mode {
MODE_COLOR,
MODE_BRIGHTNESS,
MODE_EFFECT,
MODE_EFFECT_SPEED
};
struct State {
Mode mode = MODE_COLOR;
uint8_t color[3] = {255, 255, 255}; // RGB
uint8_t brightness = 128;
uint8_t effect = 0;
uint8_t effectSpeed = 50;
bool hasChanged = true;
bool ledUpdate = true;
} state;
// Названия эффектов
const char* effects[] = {
"Static ",
"Rainbow ",
"Pulse ",
"Running "
};
void setup() {
Serial.begin(9600);
// Инициализация дисплея
u8x8.begin();
u8x8.setFont(u8x8_font_chroma48medium8_r);
u8x8.clear();
// Инициализация LED ленты
FastLED.addLeds<WS2812B, LED_PIN, GRB>(leds, NUM_LEDS);
FastLED.setBrightness(state.brightness);
fill_solid(leds, NUM_LEDS, CRGB(state.color[0], state.color[1], state.color[2]));
FastLED.show();
// Инициализация энкодера
enc.setEncReverse(false);
enc.setEncType(EB_STEP4_LOW);
enc.setClickTimeout(500);
enc.setDebTimeout(50);
}
void loop() {
// Обработка ввода с энкодера
enc.tick();
if (enc.turn()) {
handleEncoderTurn(enc.dir());
state.hasChanged = true;
}
if (enc.click()) {
handleEncoderClick();
state.hasChanged = true;
}
// Обновление дисплея при изменении состояния
if (state.hasChanged) {
displayMenu();
state.hasChanged = false;
}
// Обновление LED ленты
updateLeds();
FastLED.delay(20);
}
void handleEncoderTurn(int dir) {
switch (state.mode) {
case MODE_COLOR:
if (dir > 0) {
state.color[0] = min(state.color[0] + 5, 255);
} else {
state.color[0] = max(state.color[0] - 5, 0);
}
state.ledUpdate = true;
break;
case MODE_BRIGHTNESS:
if (dir > 0) {
state.brightness = min(state.brightness + 5, 255);
} else {
state.brightness = max(state.brightness - 5, 0);
}
FastLED.setBrightness(state.brightness);
state.ledUpdate = true;
break;
case MODE_EFFECT:
if (dir > 0) {
state.effect = (state.effect + 1) % (sizeof(effects)/sizeof(effects[0]));
} else {
state.effect = (state.effect - 1 + (sizeof(effects)/sizeof(effects[0]))) % (sizeof(effects)/sizeof(effects[0]));
}
state.ledUpdate = true;
break;
case MODE_EFFECT_SPEED:
if (dir > 0) {
state.effectSpeed = min(state.effectSpeed + 5, 100);
} else {
state.effectSpeed = max(state.effectSpeed - 5, 5);
}
break;
}
}
void handleEncoderClick() {
state.mode = (Mode)((state.mode + 1) % (MODE_EFFECT_SPEED + 1));
}
void displayMenu() {
u8x8.clear();
u8x8.setCursor(0, 0);
u8x8.print("RGB Controller");
u8x8.setCursor(0, 2);
u8x8.print(state.mode == MODE_COLOR ? ">Color:" : " Color:");
u8x8.print(state.color[0]);
u8x8.setCursor(0, 3);
u8x8.print(state.mode == MODE_BRIGHTNESS ? ">Bright:" : " Bright:");
u8x8.print(state.brightness);
u8x8.setCursor(0, 4);
u8x8.print(state.mode == MODE_EFFECT ? ">Effect:" : " Effect:");
u8x8.print(effects[state.effect]);
u8x8.setCursor(0, 5);
u8x8.print(state.mode == MODE_EFFECT_SPEED ? ">Speed:" : " Speed:");
u8x8.print(state.effectSpeed);
}
void updateLeds() {
static uint8_t hue = 0;
static uint32_t lastUpdate = 0;
if (!state.ledUpdate && millis() - lastUpdate < (100 - state.effectSpeed) * 10) {
return;
}
lastUpdate = millis();
switch (state.effect) {
case 0: // Static
fill_solid(leds, NUM_LEDS, CRGB(state.color[0], state.color[1], state.color[2]));
state.ledUpdate = false;
break;
case 1: // Rainbow
fill_rainbow(leds, NUM_LEDS, hue++);
break;
case 2: // Pulse
fill_solid(leds, NUM_LEDS, CHSV(hue++, 255, beatsin8(state.effectSpeed * 2, 50, 255)));
break;
case 3: // Running
fadeToBlackBy(leds, NUM_LEDS, 20);
int pos = beatsin16(state.effectSpeed, 0, NUM_LEDS-1);
leds[pos] = CRGB(state.color[0], state.color[1], state.color[2]);
break;
}
FastLED.show();
}