#include <Arduino.h>
#include <M5Stack.h>
#include <FastLED.h>
#include <Wire.h>
#ifndef BLACK
#define BLACK 0x0000
#endif
#ifndef WHITE
#define WHITE 0xFFF
#endif
#define LED_PIN 26
#define NUM_LEDS 37
#define LED_TYPE WS2812B
#define COLOR_ORDER GRB
#define ENCODER_ADDR 0x40
#define ENCODER_REG 0x10
#define DEBUG_MODE true
CRGB leds[NUM_LEDS];
int16_t lastEncoderValue = 0;
uint8_t currentBrightness = 0;
int16_t readEncoderValue();
void setNeoHexBrightness(uint8_t brightness);
void updateDisplay(int16_t encoderValue, uint8_t brightness);
void testInitialLEDs();
void scanI2CDevices();
void initializeEncoder();
void setup() {
M5.begin();
Wire.begin();
Serial.begin(115200);
delay(1000);
Serial.println("M5Stack Basic v2.7 NeoHex Encoder Controller Started");
M5.Lcd.fillScreen(BLACK);
M5.Lcd.setTextColor(WHITE);
M5.Lcd.setTextSize(2);
M5.Lcd.setCursor(10, 10);
M5.Lcd.println("NeoHex Encoder");
M5.Lcd.setTextSize(1);
M5.Lcd.setCursor(10, 40);
M5.Lcd.println("Rotate encoder to adjust brightness");
Serial.printf("LED Pin: %d\n", LED_PIN);
Serial.printf("Number of LEDs: %d\n", NUM_LEDS);
Serial.printf("LED Type: WS2812B\n");
Serial.printf("Color Order: GRB\n");
Serial.printf("Encoder I2C Address: 0x%02X\n", ENCODER_ADDR);
FastLED.addLeds<LED_TYPE, LED_PIN, COLOR_ORDER>(leds, NUM_LEDS);
FastLED.setBrightness(0);
for (int clearCount = 0; clearCount < 3; clearCount++) {
FastLED.clear(true);
for (int i = 0; i < NUM_LEDS; i++) {
leds[i] = CRGB::Black;
}
FastLED.show();
delay(50);
}
for (int brightness = 0; brightness <= 255; brightness += 10) {
FastLED.setBrightness(brightness);
delay(10);
}
FastLED.setBrightness(255);
Serial.println("NeoHex and Encoder initialized successfully");
Serial.println("Rotate encoder to adjust brightness (0-254)");
scanI2CDevices();
initializeEncoder();
testInitialLEDs();
}
void loop() {
int16_t encoderValue = readEncoderValue();
static unsigned long lastDebugTime = 0;
if (millis() - lastDebugTime > 1000) {
Serial.printf("Debug - Encoder Value: %d, Last Value: %d\n", encoderValue, lastEncoderValue);
lastDebugTime = millis();
}
if (encoderValue != lastEncoderValue) {
uint8_t brightness = map(encoderValue, -30, 30, 0, 254);
brightness = constrain(brightness, 0, 254);
Serial.printf("Encoder changed: %d -> %d, Brightness: %d\n", lastEncoderValue, encoderValue, brightness);
setNeoHexBrightness(brightness);
updateDisplay(encoderValue, brightness);
lastEncoderValue = encoderValue;
currentBrightness = brightness;
}
delay(50);
}
int16_t readEncoderValue() {
Wire.beginTransmission(ENCODER_ADDR);
Wire.write(ENCODER_REG);
uint8_t error = Wire.endTransmission(false);
if (error != 0) {
Serial.printf("I2C Error: %d\n", error);
return lastEncoderValue;
}
Wire.requestFrom(ENCODER_ADDR, 2);
if (Wire.available() >= 2) {
uint8_t lowByte = Wire.read();
uint8_t highByte = Wire.read();
int16_t value = (int16_t)((highByte << 8) | lowByte);
Serial.printf("Raw encoder bytes: 0x%02X 0x%02X, Value: %d\n", highByte, lowByte, value);
return value;
} else {
Serial.printf("I2C read failed, available: %d\n", Wire.available());
return lastEncoderValue;
}
}
void setNeoHexBrightness(uint8_t brightness) {
Serial.printf("Setting brightness to: %d\n", brightness);
FastLED.clear(true);
for (int i = 0; i < NUM_LEDS; i++) {
leds[i] = CRGB::Black;
}
FastLED.show();
delay(5);
for (int i = 0; i < NUM_LEDS; i++) {
leds[i] = CRGB(brightness, brightness, brightness);
}
FastLED.show();
delay(10);
Serial.println("LEDs updated");
}
void updateDisplay(int16_t encoderValue, uint8_t brightness) {
M5.Lcd.fillRect(10, 60, 300, 40, BLACK);
M5.Lcd.setCursor(10, 60);
M5.Lcd.printf("Encoder: %d", encoderValue);
M5.Lcd.setCursor(10, 80);
M5.Lcd.printf("Brightness: %d", brightness);
}
void testInitialLEDs() {
Serial.println("Starting initial LED test...");
for (int i = 0; i < 3; i++) {
Serial.printf("Test cycle %d\n", i + 1);
FastLED.clear(true);
for (int j = 0; j < NUM_LEDS; j++) {
leds[j] = CRGB(50, 0, 0);
}
FastLED.show();
delay(300);
FastLED.clear(true);
for (int j = 0; j < NUM_LEDS; j++) {
leds[j] = CRGB(0, 50, 0);
}
FastLED.show();
delay(300);
FastLED.clear(true);
for (int j = 0; j < NUM_LEDS; j++) {
leds[j] = CRGB(0, 0, 50);
}
FastLED.show();
delay(300);
FastLED.clear(true);
for (int j = 0; j < NUM_LEDS; j++) {
leds[j] = CRGB::Black;
}
FastLED.show();
delay(300);
}
for (int clearCount = 0; clearCount < 5; clearCount++) {
FastLED.clear(true);
for (int i = 0; i < NUM_LEDS; i++) {
leds[i] = CRGB::Black;
}
FastLED.show();
delay(100);
}
Serial.println("Initial LED test completed");
}
void scanI2CDevices() {
Serial.println("Scanning I2C devices...");
int deviceCount = 0;
for (uint8_t address = 1; address < 127; address++) {
Wire.beginTransmission(address);
uint8_t error = Wire.endTransmission();
if (error == 0) {
Serial.printf("I2C device found at address 0x%02X\n", address);
deviceCount++;
}
}
if (deviceCount == 0) {
Serial.println("No I2C devices found!");
} else {
Serial.printf("Found %d I2C device(s)\n", deviceCount);
}
}
void initializeEncoder() {
Serial.println("Initializing encoder unit...");
Wire.beginTransmission(ENCODER_ADDR);
Wire.write(0x00);
Wire.write(0x01);
uint8_t error = Wire.endTransmission();
if (error == 0) {
Serial.println("Encoder unit initialized successfully");
} else {
Serial.printf("Encoder initialization failed with error: %d\n", error);
}
delay(100);
}