Add working colorFade puzzle

This commit is contained in:
C0d3v 2026-01-15 10:45:37 +01:00
commit f5610bfea2
3 changed files with 381 additions and 0 deletions

View File

@ -0,0 +1,5 @@
.pio
.vscode/.browse.c_cpp.db*
.vscode/c_cpp_properties.json
.vscode/launch.json
.vscode/ipch

View File

@ -0,0 +1,15 @@
; PlatformIO Project Configuration File
;
; Build options: build flags, source filter
; Upload options: custom upload port, speed and extra flags
; Library options: dependencies, extra library storages
; Advanced options: extra scripting
;
; Please visit documentation for the other options and examples
; https://docs.platformio.org/page/projectconf.html
[env:nanoatmega328new]
platform = atmelavr
board = nanoatmega328new
framework = arduino
lib_deps = adafruit/Adafruit NeoPixel@^1.15.2

View File

@ -0,0 +1,361 @@
#include <Arduino.h>
#include <Adafruit_NeoPixel.h>
#include <Wire.h>
#define I2C_SLAVE_ADDRESS 0x08
#define MIDDLE_POTI_R A0
#define MIDDLE_POTI_G A1
#define MIDDLE_POTI_B A2
#define RIGHT_POTI_R A3
#define RIGHT_POTI_G A6
#define RIGHT_POTI_B A7
#define COMPLETED_PIN 3
#define POWER_PIN 13
#define REGENERATE_PIN 2
Adafruit_NeoPixel strip(6, 4, NEO_RGB + NEO_KHZ800);
uint16_t slavePotiValues[6] = {0};
bool powerOnState = true;
void readExternalPotiValues()
{
Wire.requestFrom(I2C_SLAVE_ADDRESS, (uint8_t)12);
uint8_t *p = (uint8_t *)slavePotiValues;
uint8_t i = 0;
while (Wire.available() && i < 12)
{
p[i++] = Wire.read();
}
}
// 49, 8, 28
// 45, 39, 32
// the setup function runs once when you press reset or power the board
struct Section
{
uint16_t min;
uint16_t max;
uint8_t value;
};
struct NormalizedRGB
{
uint8_t r;
uint8_t g;
uint8_t b;
bool operator==(const NormalizedRGB &other) const
{
return r == other.r && g == other.g && b == other.b;
}
};
bool finishedLeft = false;
bool finishedMiddle = false;
bool finishedRight = false;
struct GameBoard
{
NormalizedRGB left;
NormalizedRGB middle;
NormalizedRGB right;
bool operator==(const GameBoard &other) const
{
return left == other.left && middle == other.middle && right == other.right;
}
};
const Section pot2[] = {
{0, 511, 0},
{512, 1023, 128}};
const Section pot3[] = {
{0, 340, 0},
{341, 680, 64},
{681, 1023, 128}};
const Section pot4[] = {
{0, 255, 0},
{256, 511, 42},
{512, 768, 84},
{769, 1023, 128}};
const Section pot5[] = {
{0, 200, 0},
{201, 400, 32},
{401, 600, 64},
{601, 800, 96},
{801, 1023, 128}};
// TODO
const Section pot6[] = {
{0, 170, 0},
{171, 340, 25},
{341, 510, 50},
{511, 680, 75},
{681, 850, 100},
{851, 1023, 128}};
uint8_t quantizizePoti(uint16_t val, const Section *sec, uint8_t count)
{
for (uint8_t i = 0; i < count; i++)
{
if (val >= sec[i].min && val <= sec[i].max)
return sec[i].value;
}
return 0;
}
int MAX_SUM = 64;
NormalizedRGB updateLeft()
{
uint16_t inputR = quantizizePoti(slavePotiValues[0], pot3, 3); // analogRead(RIGHT_POTI_R);
uint16_t inputG = quantizizePoti(slavePotiValues[1], pot3, 3); // analogRead(RIGHT_POTI_G);
uint16_t inputB = quantizizePoti(slavePotiValues[2], pot3, 3);
uint32_t sum = inputR + inputG + inputB;
NormalizedRGB leftRGB;
if (sum > 0)
{
leftRGB.r = (uint32_t)inputR * MAX_SUM / sum;
leftRGB.g = (uint32_t)inputG * MAX_SUM / sum;
leftRGB.b = (uint32_t)inputB * MAX_SUM / sum;
strip.setPixelColor(2, strip.Color(leftRGB.r, leftRGB.g, leftRGB.b, 0));
}
else
{
strip.setPixelColor(2, strip.Color(0, 0, 0, 0));
}
return leftRGB;
}
NormalizedRGB updateMiddle()
{
uint16_t inputR = quantizizePoti(slavePotiValues[3], pot4, 4); // analogRead(RIGHT_POTI_R);
uint16_t inputG = quantizizePoti(slavePotiValues[4], pot4, 4); // analogRead(RIGHT_POTI_G);
uint16_t inputB = quantizizePoti(slavePotiValues[5], pot4, 4);
uint32_t sum = inputR + inputG + inputB;
NormalizedRGB middleRGB;
if (sum > 0)
{
middleRGB.r = (uint32_t)inputR * MAX_SUM / sum;
middleRGB.g = (uint32_t)inputG * MAX_SUM / sum;
middleRGB.b = (uint32_t)inputB * MAX_SUM / sum;
strip.setPixelColor(1, strip.Color(middleRGB.r, middleRGB.g, middleRGB.b, 0));
}
else
{
strip.setPixelColor(1, strip.Color(0, 0, 0, 0));
}
return middleRGB;
}
NormalizedRGB updateRight()
{
uint16_t inputR = quantizizePoti(analogRead(RIGHT_POTI_R), pot5, 5); // analogRead(RIGHT_POTI_R);
uint16_t inputG = quantizizePoti(analogRead(RIGHT_POTI_G), pot5, 5); // analogRead(RIGHT_POTI_G);
uint16_t inputB = quantizizePoti(analogRead(RIGHT_POTI_B), pot5, 5);
uint32_t sum = inputR + inputG + inputB;
NormalizedRGB rightRGB;
if (sum > 0)
{
rightRGB.r = (uint32_t)inputR * MAX_SUM / sum;
rightRGB.g = (uint32_t)inputG * MAX_SUM / sum;
rightRGB.b = (uint32_t)inputB * MAX_SUM / sum;
strip.setPixelColor(0, strip.Color(rightRGB.r, rightRGB.g, rightRGB.b, 0));
}
else
{
strip.setPixelColor(0, strip.Color(0, 0, 0, 0));
}
return rightRGB;
}
NormalizedRGB generateRandomNormalizedRGB(const Section *section, uint8_t from, uint8_t to)
{
NormalizedRGB rgb;
uint32_t sum = 0;
do
{
rgb.r = section[random(from, to)].value;
rgb.g = section[random(from, to)].value;
rgb.b = section[random(from, to)].value;
sum = rgb.r + rgb.g + rgb.b;
if (sum > 0)
{
rgb.r = (uint32_t)rgb.r * MAX_SUM / sum;
rgb.g = (uint32_t)rgb.g * MAX_SUM / sum;
rgb.b = (uint32_t)rgb.b * MAX_SUM / sum;
}
} while (sum == 0);
return rgb;
}
GameBoard finishedBoard;
void generateTargetGameBoard()
{
strip.begin();
strip.clear();
GameBoard board;
// left
board.left = generateRandomNormalizedRGB(pot3, 0, 4);
finishedLeft = false;
strip.setPixelColor(3, strip.Color(board.left.r, board.left.g, board.left.b, 0)); // left
// middle
board.middle = generateRandomNormalizedRGB(pot4, 0, 5);
finishedMiddle = false;
strip.setPixelColor(4, strip.Color(board.middle.r, board.middle.g, board.middle.b, 0)); // left
// right
board.right = generateRandomNormalizedRGB(pot5, 1, 6);
finishedRight = false;
strip.setPixelColor(5, strip.Color(board.right.r, board.right.g, board.right.b, 0)); // left
//------------------
finishedBoard = board;
strip.show();
}
GameBoard currentBoard;
void setup()
{
// initialize digital pin LED_BUILTIN as an output.
randomSeed(analogRead(A0));
Serial.begin(9600);
Wire.begin();
pinMode(RIGHT_POTI_R, INPUT);
pinMode(RIGHT_POTI_G, INPUT);
pinMode(RIGHT_POTI_B, INPUT);
pinMode(POWER_PIN, INPUT_PULLUP);
powerOnState = digitalRead(POWER_PIN) == HIGH;
pinMode(COMPLETED_PIN, OUTPUT);
pinMode(REGENERATE_PIN, INPUT_PULLUP);
if (powerOnState)
{
strip.begin();
generateTargetGameBoard();
strip.show();
}
}
void flicker(uint8_t amount, uint8_t pin1, uint8_t pin2, uint8_t r, uint8_t g, uint8_t b)
{
for (size_t i = 0; i < amount; i++)
{
strip.begin();
strip.setPixelColor(pin1, strip.Color(r, g, b));
strip.setPixelColor(pin2, strip.Color(r, g, b));
strip.show();
delay(250);
strip.begin();
strip.setPixelColor(pin1, strip.Color(0, 0, 0, 0));
strip.setPixelColor(pin2, strip.Color(0, 0, 0, 0));
strip.show();
delay(250);
}
}
void loop()
{
if (powerOnState && digitalRead(POWER_PIN) == LOW)
{
powerOnState = false;
strip.begin();
for (size_t i = 0; i < 6; i++)
{
strip.setPixelColor(i, strip.Color(0, 0, 0, 0));
}
strip.show();
}
// Detecting turn-on
if (!powerOnState && digitalRead(POWER_PIN) == HIGH)
{
generateTargetGameBoard();
powerOnState = true;
}
if (!powerOnState)
{
// We are turned-off and stop anything after here
return;
}
if (digitalRead(REGENERATE_PIN) == HIGH)
{
generateTargetGameBoard();
delay(50); // Puls kurz blockieren
}
strip.begin();
readExternalPotiValues();
if (!finishedLeft)
{
currentBoard.left = updateLeft();
if (finishedBoard.left == currentBoard.left)
{
flicker(3, 2, 3, finishedBoard.left.r, finishedBoard.left.g, finishedBoard.left.b);
finishedLeft = true;
}
}
if (!finishedMiddle)
{
currentBoard.middle = updateMiddle();
if (finishedBoard.middle == currentBoard.middle)
{
flicker(3, 1, 4, finishedBoard.middle.r, finishedBoard.middle.g, finishedBoard.middle.b);
finishedMiddle = true;
}
}
if (!finishedRight)
{
currentBoard.right = updateRight();
if (finishedBoard.right == currentBoard.right)
{
flicker(3, 0, 5, finishedBoard.right.r, finishedBoard.right.g, finishedBoard.right.b);
finishedRight = true;
}
}
if (finishedLeft && finishedMiddle && finishedRight)
{
digitalWrite(3, HIGH);
}
// if (finishedBoard == currentBoard)
// {
// Serial.println("won");
// strip.clear();
// for (uint8_t i = 0; i < 6; i++){
// strip.setPixelColor(i, strip.Color(255, 255, 255, 0));
// }
// strip.show();
// delay(5000);
// }
strip.show();
}