Compare commits
37 Commits
4459df1f18
...
main
| Author | SHA1 | Date | |
|---|---|---|---|
| d501292f32 | |||
| 1974376134 | |||
| 8c0f98b7a7 | |||
| 92a2d39e49 | |||
| 69f1cba2f8 | |||
| e2bf85c91e | |||
| d3f10ea70b | |||
| c2b5331bbd | |||
| 462485dfa6 | |||
| 64cde85752 | |||
| 26ee30d1e9 | |||
| 9df16a82c4 | |||
| 9f964f63d3 | |||
| 3ac09781e5 | |||
| 54ffd02ab4 | |||
| b3322b169b | |||
| dd9ced2962 | |||
| 99014b0f1d | |||
| 210f70a946 | |||
| 5c0c1e5672 | |||
| d198904319 | |||
| 1c36cfcde1 | |||
| f1f17cf754 | |||
| 7ad21cd1d4 | |||
| f52dd314cb | |||
| 120c89e3a4 | |||
| 0f867c2248 | |||
| 3f3a93a440 | |||
| 876b2f0db6 | |||
| 7a77347bc2 | |||
| c7e5a92edf | |||
| 4b6eefae65 | |||
| feb7e31cdb | |||
| 15297dfaec | |||
| fc5e5f862b | |||
| 5080a004af | |||
| a2945bad9a |
5
drawers/.gitignore
vendored
Normal file
5
drawers/.gitignore
vendored
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
.pio
|
||||||
|
.vscode/.browse.c_cpp.db*
|
||||||
|
.vscode/c_cpp_properties.json
|
||||||
|
.vscode/launch.json
|
||||||
|
.vscode/ipch
|
||||||
14
drawers/platformio.ini
Normal file
14
drawers/platformio.ini
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
; 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:megaatmega2560]
|
||||||
|
platform = atmelavr
|
||||||
|
board = megaatmega2560
|
||||||
|
framework = arduino
|
||||||
95
drawers/src/main.cpp
Normal file
95
drawers/src/main.cpp
Normal file
@@ -0,0 +1,95 @@
|
|||||||
|
#include <Arduino.h>
|
||||||
|
#include <Wire.h>
|
||||||
|
|
||||||
|
const uint8_t I2C_ADDR = 0x10;
|
||||||
|
|
||||||
|
const uint8_t BITMASK_CMD = 0b00011000;
|
||||||
|
const uint8_t BITMASK_PAYLOAD = 0b00000111;
|
||||||
|
|
||||||
|
const uint8_t CMD_POWER_OFF = 0b00001000;
|
||||||
|
const uint8_t CMD_LIGHT_INDEX = 0b00010000;
|
||||||
|
const uint8_t CMD_DRAWER_INDEX = 0b00011000;
|
||||||
|
|
||||||
|
struct Schublade {
|
||||||
|
int schlossPin;
|
||||||
|
int ledPin;
|
||||||
|
};
|
||||||
|
|
||||||
|
Schublade schubladen[8] = {
|
||||||
|
{6, 30},
|
||||||
|
{9, 32},
|
||||||
|
{7, 31},
|
||||||
|
{8, 33},
|
||||||
|
{2, 29},
|
||||||
|
{12, 28},
|
||||||
|
{11, 27},
|
||||||
|
{10, 26}
|
||||||
|
};
|
||||||
|
|
||||||
|
void turnAllLedsOf() {
|
||||||
|
for (int i = 0; i < 8; i++) {
|
||||||
|
digitalWrite(schubladen[i].ledPin, LOW);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
void turnOnSingleLed(uint8_t indexOn) {
|
||||||
|
if (indexOn < 0 || indexOn >= 8)
|
||||||
|
return;
|
||||||
|
turnAllLedsOf();
|
||||||
|
digitalWrite(schubladen[indexOn].ledPin, HIGH);
|
||||||
|
}
|
||||||
|
|
||||||
|
const int LOCK_THRESHOLD = 750;
|
||||||
|
unsigned long lockTimer = 0;
|
||||||
|
bool unlocked = false;
|
||||||
|
|
||||||
|
void openLock(uint8_t indexOn) {
|
||||||
|
digitalWrite(schubladen[indexOn].schlossPin, HIGH);
|
||||||
|
delay(400);
|
||||||
|
digitalWrite(schubladen[indexOn].schlossPin, LOW);
|
||||||
|
delay(400);
|
||||||
|
digitalWrite(schubladen[indexOn].schlossPin, HIGH);
|
||||||
|
unlocked = true;
|
||||||
|
lockTimer = millis();
|
||||||
|
}
|
||||||
|
|
||||||
|
void onI2CReceive(int len) {
|
||||||
|
while (Wire.available()) {
|
||||||
|
uint8_t data = Wire.read();
|
||||||
|
|
||||||
|
switch (data & BITMASK_CMD) {
|
||||||
|
|
||||||
|
case CMD_POWER_OFF:
|
||||||
|
turnAllLedsOf();
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CMD_LIGHT_INDEX:
|
||||||
|
turnOnSingleLed(data & BITMASK_PAYLOAD);
|
||||||
|
break;
|
||||||
|
|
||||||
|
case CMD_DRAWER_INDEX:
|
||||||
|
openLock(data & BITMASK_PAYLOAD);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
Wire.begin(I2C_ADDR);
|
||||||
|
Wire.onReceive(onI2CReceive);
|
||||||
|
|
||||||
|
for (int i = 0; i < 8; i++) {
|
||||||
|
pinMode(schubladen[i].ledPin, OUTPUT);
|
||||||
|
pinMode(schubladen[i].schlossPin, OUTPUT);
|
||||||
|
digitalWrite(schubladen[i].ledPin, LOW);
|
||||||
|
digitalWrite(schubladen[i].schlossPin, LOW);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
if (unlocked && millis() - lockTimer >= LOCK_THRESHOLD) {
|
||||||
|
for (int i = 0; i < 8; i++) {
|
||||||
|
digitalWrite(schubladen[i].schlossPin, LOW);
|
||||||
|
}
|
||||||
|
unlocked = false;
|
||||||
|
}
|
||||||
|
}
|
||||||
5
terminal/master/.gitignore
vendored
Normal file
5
terminal/master/.gitignore
vendored
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
.pio
|
||||||
|
.vscode/.browse.c_cpp.db*
|
||||||
|
.vscode/c_cpp_properties.json
|
||||||
|
.vscode/launch.json
|
||||||
|
.vscode/ipch
|
||||||
14
terminal/master/platformio.ini
Normal file
14
terminal/master/platformio.ini
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
; 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
|
||||||
209
terminal/master/src/main.cpp
Normal file
209
terminal/master/src/main.cpp
Normal file
@@ -0,0 +1,209 @@
|
|||||||
|
#include <Arduino.h>
|
||||||
|
#include <Wire.h>
|
||||||
|
|
||||||
|
void resetPuzzles(bool easy);
|
||||||
|
|
||||||
|
/* ========================================================= */
|
||||||
|
const uint8_t ARCHIV_ADDR = 0x10;
|
||||||
|
|
||||||
|
const uint8_t BITMASK_CMD = 0b00011000;
|
||||||
|
const uint8_t BITMASK_PAYLOAD = 0b00000111;
|
||||||
|
|
||||||
|
const uint8_t CMD_POWER_OFF = 0b00001000;
|
||||||
|
const uint8_t CMD_LIGHT_INDEX = 0b00010000;
|
||||||
|
const uint8_t CMD_DRAWER_INDEX = 0b00011000;
|
||||||
|
|
||||||
|
void setDrawerLight(uint8_t index)
|
||||||
|
{
|
||||||
|
Wire.beginTransmission(ARCHIV_ADDR);
|
||||||
|
Wire.write(CMD_LIGHT_INDEX | (index & BITMASK_PAYLOAD));
|
||||||
|
Wire.endTransmission();
|
||||||
|
}
|
||||||
|
|
||||||
|
void turnLightsOff()
|
||||||
|
{
|
||||||
|
Wire.beginTransmission(ARCHIV_ADDR);
|
||||||
|
Wire.write(CMD_POWER_OFF);
|
||||||
|
Wire.endTransmission();
|
||||||
|
}
|
||||||
|
|
||||||
|
void openDrawer(uint8_t index)
|
||||||
|
{
|
||||||
|
Wire.beginTransmission(ARCHIV_ADDR);
|
||||||
|
Wire.write(CMD_DRAWER_INDEX | (index & BITMASK_PAYLOAD));
|
||||||
|
Wire.endTransmission();
|
||||||
|
}
|
||||||
|
/* ========================================================= */
|
||||||
|
const int encoderPinA = A1;
|
||||||
|
const int encoderPinB = A2;
|
||||||
|
const int stepsPerClick = 500;
|
||||||
|
volatile long encoderPostion = 0;
|
||||||
|
volatile uint8_t lastState;
|
||||||
|
long lastClickPosition = 0;
|
||||||
|
uint8_t selectedIndex = 0;
|
||||||
|
void setupEncoder()
|
||||||
|
{
|
||||||
|
lastState = (PINC >> 1) & 0x03;
|
||||||
|
PCMSK1 |= (1 << PCINT9) | (1 << PCINT10);
|
||||||
|
}
|
||||||
|
void enableEncoder() {
|
||||||
|
PCICR |= (1 << PCIE1);
|
||||||
|
}
|
||||||
|
void disableEncoder() {
|
||||||
|
PCICR &= ~(1 << PCIE1);
|
||||||
|
}
|
||||||
|
|
||||||
|
ISR(PCINT1_vect)
|
||||||
|
{
|
||||||
|
uint8_t state = (PINC >> 1) & 0x03;
|
||||||
|
|
||||||
|
if ((lastState == 0b00 && state == 0b01) ||
|
||||||
|
(lastState == 0b01 && state == 0b11) ||
|
||||||
|
(lastState == 0b11 && state == 0b10) ||
|
||||||
|
(lastState == 0b10 && state == 0b00))
|
||||||
|
{
|
||||||
|
encoderPostion++;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
encoderPostion--;
|
||||||
|
}
|
||||||
|
lastState = state;
|
||||||
|
}
|
||||||
|
uint8_t inputPattern = 0;
|
||||||
|
uint8_t secretPattern = 0b10101010;
|
||||||
|
void handleEncoderMovement()
|
||||||
|
{
|
||||||
|
long diff = encoderPostion - lastClickPosition;
|
||||||
|
if (abs(diff) >= stepsPerClick)
|
||||||
|
{
|
||||||
|
if (diff > 0)
|
||||||
|
{
|
||||||
|
// right turn
|
||||||
|
selectedIndex = (selectedIndex + 1) % 8;
|
||||||
|
inputPattern = ((inputPattern << 1) | 1) & 0xFF;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
//left turn
|
||||||
|
selectedIndex = (selectedIndex + 7) % 8;
|
||||||
|
inputPattern = ((inputPattern << 1) | 0) & 0xFF;
|
||||||
|
}
|
||||||
|
bool reset = inputPattern == secretPattern;
|
||||||
|
resetPuzzles(reset);
|
||||||
|
setDrawerLight(selectedIndex);
|
||||||
|
lastClickPosition = encoderPostion;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/* ========================================================= */
|
||||||
|
const int PIN_POWER_SWITCH_INPUT = 2;
|
||||||
|
const int PIN_POWER_SWITCH_OUTPUT = 12;
|
||||||
|
const unsigned long POWER_STABLE_THRESHOLD = 100;
|
||||||
|
bool powerStableState;
|
||||||
|
bool powerLastRawState;
|
||||||
|
unsigned long powerLastChangeTime = 0;
|
||||||
|
|
||||||
|
bool checkPowerState()
|
||||||
|
{
|
||||||
|
bool rawState = digitalRead(PIN_POWER_SWITCH_INPUT);
|
||||||
|
|
||||||
|
if (rawState != powerLastRawState)
|
||||||
|
{
|
||||||
|
powerLastChangeTime = millis();
|
||||||
|
powerLastRawState = rawState;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((millis() - powerLastChangeTime) > POWER_STABLE_THRESHOLD &&
|
||||||
|
rawState != powerStableState)
|
||||||
|
{
|
||||||
|
powerStableState = rawState;
|
||||||
|
if (powerStableState)
|
||||||
|
{
|
||||||
|
setDrawerLight(selectedIndex);
|
||||||
|
digitalWrite(PIN_POWER_SWITCH_OUTPUT, HIGH);
|
||||||
|
enableEncoder();
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
turnLightsOff();
|
||||||
|
digitalWrite(PIN_POWER_SWITCH_OUTPUT, LOW);
|
||||||
|
disableEncoder();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return powerStableState;
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ========================================================= */
|
||||||
|
const int puzzleSolvedInputPins[3] = {3, 4, 5};
|
||||||
|
const int puzzleResetPins[3] = {7, 8, 9};
|
||||||
|
bool puzzlesSolved[3] = {false, false, false};
|
||||||
|
bool allSolvedSent = false;
|
||||||
|
|
||||||
|
void resetPuzzles(bool easy)
|
||||||
|
{
|
||||||
|
for (size_t i = 0; i < 3; i++)
|
||||||
|
{
|
||||||
|
digitalWrite(puzzleResetPins[i], HIGH);
|
||||||
|
puzzlesSolved[i] = false;
|
||||||
|
}
|
||||||
|
if (easy)
|
||||||
|
delay(400);
|
||||||
|
else
|
||||||
|
delay(90);
|
||||||
|
|
||||||
|
for (size_t i = 0; i < 3; i++)
|
||||||
|
{
|
||||||
|
digitalWrite(puzzleResetPins[i], LOW);
|
||||||
|
}
|
||||||
|
allSolvedSent = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
void checkPuzzleSolvedStatus()
|
||||||
|
{
|
||||||
|
if (allSolvedSent)
|
||||||
|
return;
|
||||||
|
for (int i = 0; i < 3; i++)
|
||||||
|
{
|
||||||
|
if (!puzzlesSolved[i] && digitalRead(puzzleSolvedInputPins[i]) == HIGH)
|
||||||
|
{
|
||||||
|
puzzlesSolved[i] = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if (puzzlesSolved[0] && puzzlesSolved[1] && puzzlesSolved[2])
|
||||||
|
{
|
||||||
|
openDrawer(selectedIndex);
|
||||||
|
allSolvedSent = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/* ========================================================= */
|
||||||
|
|
||||||
|
void setup()
|
||||||
|
{
|
||||||
|
Wire.begin();
|
||||||
|
|
||||||
|
pinMode(encoderPinA, INPUT_PULLUP);
|
||||||
|
pinMode(encoderPinB, INPUT_PULLUP);
|
||||||
|
pinMode(PIN_POWER_SWITCH_INPUT, INPUT_PULLUP);
|
||||||
|
pinMode(PIN_POWER_SWITCH_OUTPUT, OUTPUT);
|
||||||
|
powerStableState = digitalRead(PIN_POWER_SWITCH_INPUT);
|
||||||
|
powerLastRawState = powerStableState;
|
||||||
|
digitalWrite(PIN_POWER_SWITCH_OUTPUT, powerStableState == HIGH);
|
||||||
|
|
||||||
|
for (int i = 0; i < 3; i++)
|
||||||
|
{
|
||||||
|
pinMode(puzzleResetPins[i], OUTPUT);
|
||||||
|
pinMode(puzzleSolvedInputPins[i], INPUT_PULLUP);
|
||||||
|
}
|
||||||
|
|
||||||
|
setupEncoder();
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop()
|
||||||
|
{
|
||||||
|
if (checkPowerState())
|
||||||
|
{
|
||||||
|
handleEncoderMovement();
|
||||||
|
checkPuzzleSolvedStatus();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -7,6 +7,7 @@
|
|||||||
;
|
;
|
||||||
; Please visit documentation for the other options and examples
|
; Please visit documentation for the other options and examples
|
||||||
; https://docs.platformio.org/page/projectconf.html
|
; https://docs.platformio.org/page/projectconf.html
|
||||||
|
; hihihi
|
||||||
|
|
||||||
[env:nanoatmega328new]
|
[env:nanoatmega328new]
|
||||||
platform = atmelavr
|
platform = atmelavr
|
||||||
|
|||||||
@@ -127,6 +127,7 @@ NormalizedRGB updateLeft()
|
|||||||
uint32_t sum = inputR + inputG + inputB;
|
uint32_t sum = inputR + inputG + inputB;
|
||||||
|
|
||||||
NormalizedRGB leftRGB;
|
NormalizedRGB leftRGB;
|
||||||
|
strip.begin();
|
||||||
if (sum > 0)
|
if (sum > 0)
|
||||||
{
|
{
|
||||||
leftRGB.r = (uint32_t)inputR * MAX_SUM / sum;
|
leftRGB.r = (uint32_t)inputR * MAX_SUM / sum;
|
||||||
@@ -138,6 +139,7 @@ NormalizedRGB updateLeft()
|
|||||||
{
|
{
|
||||||
strip.setPixelColor(2, strip.Color(0, 0, 0, 0));
|
strip.setPixelColor(2, strip.Color(0, 0, 0, 0));
|
||||||
}
|
}
|
||||||
|
strip.show();
|
||||||
return leftRGB;
|
return leftRGB;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -149,7 +151,7 @@ NormalizedRGB updateMiddle()
|
|||||||
uint32_t sum = inputR + inputG + inputB;
|
uint32_t sum = inputR + inputG + inputB;
|
||||||
|
|
||||||
NormalizedRGB middleRGB;
|
NormalizedRGB middleRGB;
|
||||||
|
strip.begin();
|
||||||
if (sum > 0)
|
if (sum > 0)
|
||||||
{
|
{
|
||||||
middleRGB.r = (uint32_t)inputR * MAX_SUM / sum;
|
middleRGB.r = (uint32_t)inputR * MAX_SUM / sum;
|
||||||
@@ -161,6 +163,7 @@ NormalizedRGB updateMiddle()
|
|||||||
{
|
{
|
||||||
strip.setPixelColor(1, strip.Color(0, 0, 0, 0));
|
strip.setPixelColor(1, strip.Color(0, 0, 0, 0));
|
||||||
}
|
}
|
||||||
|
strip.show();
|
||||||
return middleRGB;
|
return middleRGB;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -172,7 +175,7 @@ NormalizedRGB updateRight()
|
|||||||
uint32_t sum = inputR + inputG + inputB;
|
uint32_t sum = inputR + inputG + inputB;
|
||||||
|
|
||||||
NormalizedRGB rightRGB;
|
NormalizedRGB rightRGB;
|
||||||
|
strip.begin();
|
||||||
if (sum > 0)
|
if (sum > 0)
|
||||||
{
|
{
|
||||||
rightRGB.r = (uint32_t)inputR * MAX_SUM / sum;
|
rightRGB.r = (uint32_t)inputR * MAX_SUM / sum;
|
||||||
@@ -184,7 +187,7 @@ NormalizedRGB updateRight()
|
|||||||
{
|
{
|
||||||
strip.setPixelColor(0, strip.Color(0, 0, 0, 0));
|
strip.setPixelColor(0, strip.Color(0, 0, 0, 0));
|
||||||
}
|
}
|
||||||
|
strip.show();
|
||||||
return rightRGB;
|
return rightRGB;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -211,24 +214,36 @@ NormalizedRGB generateRandomNormalizedRGB(const Section *section, uint8_t from,
|
|||||||
}
|
}
|
||||||
|
|
||||||
GameBoard finishedBoard;
|
GameBoard finishedBoard;
|
||||||
void generateTargetGameBoard()
|
void generateTargetGameBoard(bool easy)
|
||||||
{
|
{
|
||||||
|
for (size_t i = 0; i < 6; i++)
|
||||||
|
{
|
||||||
|
slavePotiValues[i] = 0;
|
||||||
|
}
|
||||||
|
digitalWrite(COMPLETED_PIN, LOW);
|
||||||
|
GameBoard board;
|
||||||
|
if (easy)
|
||||||
|
{
|
||||||
|
board.left = generateRandomNormalizedRGB(pot3, 2, 3);
|
||||||
|
board.middle = generateRandomNormalizedRGB(pot4, 3, 4);
|
||||||
|
board.right = generateRandomNormalizedRGB(pot5, 4, 5);
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
board.left = generateRandomNormalizedRGB(pot3, 0, 3);
|
||||||
|
board.middle = generateRandomNormalizedRGB(pot4, 0, 4);
|
||||||
|
board.right = generateRandomNormalizedRGB(pot5, 1, 5);
|
||||||
|
}
|
||||||
strip.begin();
|
strip.begin();
|
||||||
strip.clear();
|
strip.clear();
|
||||||
GameBoard board;
|
|
||||||
// left
|
|
||||||
board.left = generateRandomNormalizedRGB(pot3, 0, 3);
|
|
||||||
finishedLeft = false;
|
finishedLeft = false;
|
||||||
strip.setPixelColor(3, strip.Color(board.left.r, board.left.g, board.left.b, 0)); // left
|
strip.setPixelColor(3, strip.Color(board.left.r, board.left.g, board.left.b, 0)); // left
|
||||||
// middle
|
|
||||||
board.middle = generateRandomNormalizedRGB(pot4, 0, 4);
|
|
||||||
finishedMiddle = false;
|
finishedMiddle = false;
|
||||||
strip.setPixelColor(4, strip.Color(board.middle.r, board.middle.g, board.middle.b, 0)); // middle
|
strip.setPixelColor(4, strip.Color(board.middle.r, board.middle.g, board.middle.b, 0)); // middle
|
||||||
// right
|
|
||||||
board.right = generateRandomNormalizedRGB(pot5, 1, 5);
|
|
||||||
finishedRight = false;
|
finishedRight = false;
|
||||||
strip.setPixelColor(5, strip.Color(board.right.r, board.right.g, board.right.b, 0)); // left
|
strip.setPixelColor(5, strip.Color(board.right.r, board.right.g, board.right.b, 0)); // right
|
||||||
//------------------
|
|
||||||
|
|
||||||
finishedBoard = board;
|
finishedBoard = board;
|
||||||
strip.show();
|
strip.show();
|
||||||
@@ -248,15 +263,15 @@ void setup()
|
|||||||
pinMode(RIGHT_POTI_G, INPUT);
|
pinMode(RIGHT_POTI_G, INPUT);
|
||||||
pinMode(RIGHT_POTI_B, INPUT);
|
pinMode(RIGHT_POTI_B, INPUT);
|
||||||
|
|
||||||
pinMode(POWER_PIN, INPUT_PULLUP);
|
pinMode(POWER_PIN, INPUT);
|
||||||
powerOnState = digitalRead(POWER_PIN) == HIGH;
|
powerOnState = digitalRead(POWER_PIN) == HIGH;
|
||||||
pinMode(COMPLETED_PIN, OUTPUT);
|
pinMode(COMPLETED_PIN, OUTPUT);
|
||||||
pinMode(REGENERATE_PIN, INPUT_PULLUP);
|
pinMode(REGENERATE_PIN, INPUT);
|
||||||
|
|
||||||
if (powerOnState)
|
if (powerOnState)
|
||||||
{
|
{
|
||||||
strip.begin();
|
strip.begin();
|
||||||
generateTargetGameBoard();
|
generateTargetGameBoard(false);
|
||||||
strip.show();
|
strip.show();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -293,7 +308,7 @@ void loop()
|
|||||||
// Detecting turn-on
|
// Detecting turn-on
|
||||||
if (!powerOnState && digitalRead(POWER_PIN) == HIGH)
|
if (!powerOnState && digitalRead(POWER_PIN) == HIGH)
|
||||||
{
|
{
|
||||||
generateTargetGameBoard();
|
generateTargetGameBoard(false);
|
||||||
powerOnState = true;
|
powerOnState = true;
|
||||||
}
|
}
|
||||||
if (!powerOnState)
|
if (!powerOnState)
|
||||||
@@ -304,11 +319,14 @@ void loop()
|
|||||||
|
|
||||||
if (digitalRead(REGENERATE_PIN) == HIGH)
|
if (digitalRead(REGENERATE_PIN) == HIGH)
|
||||||
{
|
{
|
||||||
generateTargetGameBoard();
|
unsigned long resetTimer = millis();
|
||||||
delay(50); // Puls kurz blockieren
|
while (digitalRead(REGENERATE_PIN) == HIGH)
|
||||||
|
{
|
||||||
|
delay(10);
|
||||||
|
}
|
||||||
|
generateTargetGameBoard(millis() - resetTimer > 150);
|
||||||
}
|
}
|
||||||
|
|
||||||
strip.begin();
|
|
||||||
readExternalPotiValues();
|
readExternalPotiValues();
|
||||||
|
|
||||||
if (!finishedLeft)
|
if (!finishedLeft)
|
||||||
@@ -343,19 +361,6 @@ void loop()
|
|||||||
|
|
||||||
if (finishedLeft && finishedMiddle && finishedRight)
|
if (finishedLeft && finishedMiddle && finishedRight)
|
||||||
{
|
{
|
||||||
digitalWrite(3, HIGH);
|
digitalWrite(COMPLETED_PIN, 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();
|
|
||||||
}
|
}
|
||||||
|
|||||||
5
terminal/puzzle_colorFade/potiNano/.gitignore
vendored
Normal file
5
terminal/puzzle_colorFade/potiNano/.gitignore
vendored
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
.pio
|
||||||
|
.vscode/.browse.c_cpp.db*
|
||||||
|
.vscode/c_cpp_properties.json
|
||||||
|
.vscode/launch.json
|
||||||
|
.vscode/ipch
|
||||||
14
terminal/puzzle_colorFade/potiNano/platformio.ini
Normal file
14
terminal/puzzle_colorFade/potiNano/platformio.ini
Normal file
@@ -0,0 +1,14 @@
|
|||||||
|
; 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
|
||||||
39
terminal/puzzle_colorFade/potiNano/src/main.cpp
Normal file
39
terminal/puzzle_colorFade/potiNano/src/main.cpp
Normal file
@@ -0,0 +1,39 @@
|
|||||||
|
#include <Arduino.h>
|
||||||
|
#include <Wire.h>
|
||||||
|
|
||||||
|
#define I2C_SLAVE_ADDRESS 0x08
|
||||||
|
|
||||||
|
volatile uint16_t bufferA[6];
|
||||||
|
volatile uint16_t bufferB[6];
|
||||||
|
|
||||||
|
// Pointer to the buffer currently exposed to ISR
|
||||||
|
volatile uint16_t* activeBuffer = bufferA;
|
||||||
|
|
||||||
|
void onI2CRequest() {
|
||||||
|
// Safe: ISR only reads active buffer
|
||||||
|
Wire.write((uint8_t*)activeBuffer, 6 * sizeof(uint16_t));
|
||||||
|
}
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
Wire.begin(I2C_SLAVE_ADDRESS);
|
||||||
|
Wire.onRequest(onI2CRequest);
|
||||||
|
analogReference(DEFAULT);
|
||||||
|
}
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
// Choose the inactive buffer
|
||||||
|
volatile uint16_t* writeBuffer =
|
||||||
|
(activeBuffer == bufferA) ? bufferB : bufferA;
|
||||||
|
|
||||||
|
writeBuffer[0] = analogRead(A0);
|
||||||
|
writeBuffer[1] = analogRead(A1);
|
||||||
|
writeBuffer[2] = analogRead(A2);
|
||||||
|
writeBuffer[3] = analogRead(A3);
|
||||||
|
writeBuffer[4] = analogRead(A6);
|
||||||
|
writeBuffer[5] = analogRead(A7);
|
||||||
|
|
||||||
|
// Atomic pointer swap
|
||||||
|
noInterrupts();
|
||||||
|
activeBuffer = writeBuffer;
|
||||||
|
interrupts();
|
||||||
|
}
|
||||||
5
terminal/puzzle_colorRemember/.gitignore
vendored
Normal file
5
terminal/puzzle_colorRemember/.gitignore
vendored
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
.pio
|
||||||
|
.vscode/.browse.c_cpp.db*
|
||||||
|
.vscode/c_cpp_properties.json
|
||||||
|
.vscode/launch.json
|
||||||
|
.vscode/ipch
|
||||||
17
terminal/puzzle_colorRemember/platformio.ini
Normal file
17
terminal/puzzle_colorRemember/platformio.ini
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
; 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
|
||||||
|
robtillaart/PCF8575@^0.2.4
|
||||||
345
terminal/puzzle_colorRemember/src/main.cpp
Normal file
345
terminal/puzzle_colorRemember/src/main.cpp
Normal file
@@ -0,0 +1,345 @@
|
|||||||
|
|
||||||
|
// ================== Projekt: Modul 2 ==================
|
||||||
|
// SPIELMECHANIK – mit Gewinnanimation + Gewinnsignal
|
||||||
|
//
|
||||||
|
// Fix integriert:
|
||||||
|
// - zeitbasierte Entprellung pro Taster
|
||||||
|
// - verhindert Mehrfachregistrierung eines einzelnen Tastendrucks
|
||||||
|
#include <Arduino.h>
|
||||||
|
#include <Wire.h>
|
||||||
|
#include <PCF8575.h>
|
||||||
|
#include <Adafruit_NeoPixel.h>
|
||||||
|
|
||||||
|
// ------------------ Hardware ------------------
|
||||||
|
|
||||||
|
PCF8575 expander(0x20);
|
||||||
|
|
||||||
|
#define PIN_NEOPIXEL_BUTTONS 4
|
||||||
|
#define NUM_NEOPIXEL_BUTTONS 18
|
||||||
|
|
||||||
|
#define PIN_NEOPIXEL_LOESUNG 6
|
||||||
|
#define NUM_NEOPIXEL_LOESUNG 6
|
||||||
|
|
||||||
|
#define PIN_POWER_ON 13
|
||||||
|
#define PIN_TRIGGER_SHUFFLE 2
|
||||||
|
#define PIN_SEND_WIN 5
|
||||||
|
|
||||||
|
// ------------------ Timing ------------------
|
||||||
|
|
||||||
|
#define WIN_OFF_DELAY_MS 300
|
||||||
|
#define WIN_STEP_DELAY_MS 60
|
||||||
|
#define DEBOUNCE_TIME_MS 200 // <<< Entprellzeit
|
||||||
|
|
||||||
|
Adafruit_NeoPixel pixelsButtons(
|
||||||
|
NUM_NEOPIXEL_BUTTONS,
|
||||||
|
PIN_NEOPIXEL_BUTTONS,
|
||||||
|
NEO_RGB + NEO_KHZ800
|
||||||
|
);
|
||||||
|
|
||||||
|
Adafruit_NeoPixel pixelsSolution(
|
||||||
|
NUM_NEOPIXEL_LOESUNG,
|
||||||
|
PIN_NEOPIXEL_LOESUNG,
|
||||||
|
NEO_RGB + NEO_KHZ800
|
||||||
|
);
|
||||||
|
|
||||||
|
// ------------------ Mapping ------------------
|
||||||
|
|
||||||
|
enum ButtonSource { SRC_NANO, SRC_PCF8575 };
|
||||||
|
|
||||||
|
struct LedButtonMap {
|
||||||
|
uint8_t ledIndex;
|
||||||
|
ButtonSource source;
|
||||||
|
uint8_t pin;
|
||||||
|
};
|
||||||
|
|
||||||
|
const LedButtonMap ledButtonMap[18] = {
|
||||||
|
{ 0, SRC_NANO, A0 }, { 1, SRC_NANO, A1 }, { 2, SRC_NANO, A2 }, { 3, SRC_NANO, A3 },
|
||||||
|
{ 4, SRC_NANO, 7 }, { 5, SRC_NANO, 8 },
|
||||||
|
{ 6, SRC_PCF8575, 0 }, { 7, SRC_PCF8575, 1 }, { 8, SRC_PCF8575, 2 }, { 9, SRC_PCF8575, 3 },
|
||||||
|
{10, SRC_PCF8575, 4 }, {11, SRC_PCF8575, 5 }, {12, SRC_PCF8575, 6 }, {13, SRC_PCF8575, 7 },
|
||||||
|
{14, SRC_PCF8575, 8 }, {15, SRC_PCF8575, 9 }, {16, SRC_PCF8575,10 }, {17, SRC_PCF8575,11 }
|
||||||
|
};
|
||||||
|
|
||||||
|
// ------------------ Pride-Farben (dunkler) ------------------
|
||||||
|
|
||||||
|
const uint8_t prideColors[6][3] = {
|
||||||
|
{25, 0, 0},
|
||||||
|
{35, 10, 0},
|
||||||
|
{25, 25, 0},
|
||||||
|
{ 0, 25, 0},
|
||||||
|
{ 0, 0, 25},
|
||||||
|
{20, 0, 25}
|
||||||
|
};
|
||||||
|
|
||||||
|
// ------------------ Spielzustände ------------------
|
||||||
|
|
||||||
|
uint8_t solutionOrder[6];
|
||||||
|
uint8_t expectedOrder[6];
|
||||||
|
int8_t buttonAssignment[18];
|
||||||
|
bool winActive = false;
|
||||||
|
bool powerOnState = true;
|
||||||
|
|
||||||
|
|
||||||
|
bool lastPressed[18];
|
||||||
|
unsigned long ledOffTime[18];
|
||||||
|
unsigned long lastPressTime[18]; // <<< Entprellspeicher
|
||||||
|
|
||||||
|
uint8_t progressIndex = 0;
|
||||||
|
bool lastTriggerState = LOW;
|
||||||
|
|
||||||
|
// ------------------ Hilfsfunktionen ------------------
|
||||||
|
|
||||||
|
bool readButton(uint8_t i) {
|
||||||
|
if (ledButtonMap[i].source == SRC_NANO)
|
||||||
|
return digitalRead(ledButtonMap[i].pin) == LOW;
|
||||||
|
return expander.read(ledButtonMap[i].pin) == LOW;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------ Neues Spiel ------------------
|
||||||
|
|
||||||
|
void generateNewGame(bool easy) {
|
||||||
|
|
||||||
|
for (uint8_t i = 0; i < 6; i++)
|
||||||
|
solutionOrder[i] = i;
|
||||||
|
|
||||||
|
if (!easy)
|
||||||
|
{
|
||||||
|
for (int i = 5; i > 0; i--)
|
||||||
|
{
|
||||||
|
int j = random(i + 1);
|
||||||
|
uint8_t t = solutionOrder[i];
|
||||||
|
solutionOrder[i] = solutionOrder[j];
|
||||||
|
solutionOrder[j] = t;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (uint8_t i = 0; i < 6; i++)
|
||||||
|
expectedOrder[i] = solutionOrder[5 - i];
|
||||||
|
|
||||||
|
pixelsSolution.begin();
|
||||||
|
for (uint8_t i = 0; i < 6; i++) {
|
||||||
|
uint8_t c = solutionOrder[i];
|
||||||
|
pixelsSolution.setPixelColor(
|
||||||
|
i,
|
||||||
|
pixelsSolution.Color(
|
||||||
|
prideColors[c][0],
|
||||||
|
prideColors[c][1],
|
||||||
|
prideColors[c][2]
|
||||||
|
)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
pixelsSolution.show();
|
||||||
|
|
||||||
|
pixelsButtons.begin();
|
||||||
|
for (uint8_t i = 0; i < 18; i++) {
|
||||||
|
buttonAssignment[i] = -1;
|
||||||
|
pixelsButtons.setPixelColor(i, 0);
|
||||||
|
ledOffTime[i] = 0;
|
||||||
|
lastPressTime[i] = 0;
|
||||||
|
}
|
||||||
|
pixelsButtons.show();
|
||||||
|
|
||||||
|
uint8_t idx[18];
|
||||||
|
for (uint8_t i = 0; i < 18; i++) idx[i] = i;
|
||||||
|
|
||||||
|
if (!easy)
|
||||||
|
{
|
||||||
|
for (int i = 17; i > 0; i--)
|
||||||
|
{
|
||||||
|
int j = random(i + 1);
|
||||||
|
uint8_t t = idx[i];
|
||||||
|
idx[i] = idx[j];
|
||||||
|
idx[j] = t;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
for (uint8_t i = 0; i < 6; i++)
|
||||||
|
buttonAssignment[idx[i]] = solutionOrder[i];
|
||||||
|
|
||||||
|
progressIndex = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------ Gewinnanimation + Signal ------------------
|
||||||
|
|
||||||
|
void winAnimation() {
|
||||||
|
|
||||||
|
winActive = true;
|
||||||
|
digitalWrite(PIN_SEND_WIN, HIGH);
|
||||||
|
|
||||||
|
// 1) letzte korrekte Farbe stehen lassen
|
||||||
|
delay(500);
|
||||||
|
|
||||||
|
// 2) ALLES AUS (inkl. Off-Timer löschen)
|
||||||
|
for (uint8_t i = 0; i < 18; i++)
|
||||||
|
ledOffTime[i] = 0;
|
||||||
|
|
||||||
|
pixelsSolution.clear();
|
||||||
|
pixelsButtons.clear();
|
||||||
|
pixelsSolution.show();
|
||||||
|
pixelsButtons.show();
|
||||||
|
delay(WIN_OFF_DELAY_MS);
|
||||||
|
|
||||||
|
// 3) richtige Reihenfolge (umgekehrt), Lösung + Taster synchron
|
||||||
|
for (int i = 5; i >= 0; i--) {
|
||||||
|
|
||||||
|
uint8_t color = solutionOrder[i];
|
||||||
|
|
||||||
|
// Lösungs-LED
|
||||||
|
pixelsSolution.setPixelColor(
|
||||||
|
i,
|
||||||
|
pixelsSolution.Color(
|
||||||
|
prideColors[color][0],
|
||||||
|
prideColors[color][1],
|
||||||
|
prideColors[color][2]
|
||||||
|
)
|
||||||
|
);
|
||||||
|
|
||||||
|
// zugehöriger Taster
|
||||||
|
for (uint8_t b = 0; b < 18; b++) {
|
||||||
|
if (buttonAssignment[b] == color) {
|
||||||
|
pixelsButtons.setPixelColor(
|
||||||
|
b,
|
||||||
|
pixelsButtons.Color(
|
||||||
|
prideColors[color][0],
|
||||||
|
prideColors[color][1],
|
||||||
|
prideColors[color][2]
|
||||||
|
)
|
||||||
|
);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pixelsSolution.show();
|
||||||
|
pixelsButtons.show();
|
||||||
|
delay(WIN_STEP_DELAY_MS);
|
||||||
|
}
|
||||||
|
|
||||||
|
digitalWrite(PIN_SEND_WIN, LOW);
|
||||||
|
winActive = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
// ------------------ Setup ------------------
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
randomSeed(analogRead(A0));
|
||||||
|
|
||||||
|
Wire.begin();
|
||||||
|
expander.begin();
|
||||||
|
|
||||||
|
pinMode(PIN_TRIGGER_SHUFFLE, INPUT);
|
||||||
|
pinMode(PIN_POWER_ON, INPUT);
|
||||||
|
pinMode(PIN_SEND_WIN, OUTPUT);
|
||||||
|
digitalWrite(PIN_SEND_WIN, LOW);
|
||||||
|
|
||||||
|
pinMode(A0, INPUT_PULLUP);
|
||||||
|
pinMode(A1, INPUT_PULLUP);
|
||||||
|
pinMode(A2, INPUT_PULLUP);
|
||||||
|
pinMode(A3, INPUT_PULLUP);
|
||||||
|
pinMode(7, INPUT_PULLUP);
|
||||||
|
pinMode(8, INPUT_PULLUP);
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
for (uint8_t i = 0; i < 12; i++)
|
||||||
|
expander.write(i, HIGH);
|
||||||
|
|
||||||
|
for (uint8_t i = 0; i < 18; i++)
|
||||||
|
lastPressed[i] = false;
|
||||||
|
|
||||||
|
powerOnState = digitalRead(PIN_POWER_ON) == HIGH;
|
||||||
|
|
||||||
|
if (powerOnState)
|
||||||
|
{
|
||||||
|
generateNewGame(false);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// ------------------ Loop ------------------
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
if (powerOnState && digitalRead(PIN_POWER_ON) == LOW)
|
||||||
|
{
|
||||||
|
powerOnState = false;
|
||||||
|
pixelsSolution.begin();
|
||||||
|
for (size_t i = 0; i < 6; i++)
|
||||||
|
{
|
||||||
|
pixelsSolution.setPixelColor(i, pixelsSolution.Color(0, 0, 0, 0));
|
||||||
|
}
|
||||||
|
pixelsSolution.show();
|
||||||
|
pixelsButtons.begin();
|
||||||
|
for (size_t i = 0; i < 18; i++)
|
||||||
|
{
|
||||||
|
pixelsButtons.setPixelColor(i, pixelsButtons.Color(0, 0, 0, 0));
|
||||||
|
}
|
||||||
|
pixelsButtons.show();
|
||||||
|
|
||||||
|
}
|
||||||
|
// Detecting turn-on
|
||||||
|
if (!powerOnState && digitalRead(PIN_POWER_ON) == HIGH)
|
||||||
|
{
|
||||||
|
generateNewGame(false);
|
||||||
|
powerOnState = true;
|
||||||
|
}
|
||||||
|
if (!powerOnState)
|
||||||
|
{
|
||||||
|
// We are turned-off and stop anything after here
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (digitalRead(PIN_TRIGGER_SHUFFLE) == HIGH)
|
||||||
|
{
|
||||||
|
unsigned long resetTimer = millis();
|
||||||
|
while (digitalRead(PIN_TRIGGER_SHUFFLE) == HIGH)
|
||||||
|
{
|
||||||
|
delay(10);
|
||||||
|
}
|
||||||
|
generateNewGame(millis() - resetTimer > 150);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsigned long now = millis();
|
||||||
|
for (uint8_t i = 0; i < 18; i++) {
|
||||||
|
bool pressed = readButton(i);
|
||||||
|
|
||||||
|
if (pressed && !lastPressed[i] &&
|
||||||
|
(now - lastPressTime[i] > DEBOUNCE_TIME_MS)) {
|
||||||
|
|
||||||
|
lastPressTime[i] = now;
|
||||||
|
int8_t color = buttonAssignment[i];
|
||||||
|
|
||||||
|
if (color >= 0) {
|
||||||
|
pixelsButtons.setPixelColor(
|
||||||
|
i,
|
||||||
|
pixelsButtons.Color(
|
||||||
|
prideColors[color][0],
|
||||||
|
prideColors[color][1],
|
||||||
|
prideColors[color][2]
|
||||||
|
)
|
||||||
|
);
|
||||||
|
pixelsButtons.show();
|
||||||
|
ledOffTime[i] = now + 1000;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (color < 0 || color != expectedOrder[progressIndex]) {
|
||||||
|
progressIndex = 0;
|
||||||
|
} else {
|
||||||
|
progressIndex++;
|
||||||
|
if (progressIndex == 6) {
|
||||||
|
winAnimation();
|
||||||
|
progressIndex = 0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!winActive && ledOffTime[i] && now >= ledOffTime[i]) {
|
||||||
|
|
||||||
|
pixelsButtons.setPixelColor(i, 0);
|
||||||
|
pixelsButtons.show();
|
||||||
|
ledOffTime[i] = 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
lastPressed[i] = pressed;
|
||||||
|
}
|
||||||
|
}
|
||||||
5
terminal/puzzle_leftRight/.gitignore
vendored
Normal file
5
terminal/puzzle_leftRight/.gitignore
vendored
Normal file
@@ -0,0 +1,5 @@
|
|||||||
|
.pio
|
||||||
|
.vscode/.browse.c_cpp.db*
|
||||||
|
.vscode/c_cpp_properties.json
|
||||||
|
.vscode/launch.json
|
||||||
|
.vscode/ipch
|
||||||
15
terminal/puzzle_leftRight/platformio.ini
Normal file
15
terminal/puzzle_leftRight/platformio.ini
Normal 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
|
||||||
167
terminal/puzzle_leftRight/src/main.cpp
Normal file
167
terminal/puzzle_leftRight/src/main.cpp
Normal file
@@ -0,0 +1,167 @@
|
|||||||
|
#include <Arduino.h>
|
||||||
|
#include <Adafruit_NeoPixel.h>
|
||||||
|
|
||||||
|
/*
|
||||||
|
Slave Modul 1
|
||||||
|
- Taster an A0 und A1 (INPUT_PULLUP)
|
||||||
|
- 16 Neopixel an D4
|
||||||
|
- D3 -> Master
|
||||||
|
LOW = nicht gelöst
|
||||||
|
HIGH = gelöst (bleibt HIGH)
|
||||||
|
- D2 -> Master
|
||||||
|
HIGH = neue Sequenz generieren
|
||||||
|
*/
|
||||||
|
|
||||||
|
#define LED_PIN 4
|
||||||
|
#define NUM_LEDS 16
|
||||||
|
|
||||||
|
#define POWER_PIN 12
|
||||||
|
bool powerOnState = true;
|
||||||
|
|
||||||
|
#define BUTTON1_PIN A0
|
||||||
|
#define BUTTON2_PIN A1
|
||||||
|
#define austausch_master_pin 3
|
||||||
|
#define randomizer_master_pin 2
|
||||||
|
|
||||||
|
Adafruit_NeoPixel strip(NUM_LEDS, LED_PIN, NEO_RGB + NEO_KHZ800);
|
||||||
|
|
||||||
|
int sequence[NUM_LEDS];
|
||||||
|
int currentStep = 0;
|
||||||
|
bool gameWon = false;
|
||||||
|
|
||||||
|
int lastButton1State = HIGH;
|
||||||
|
int lastButton2State = HIGH;
|
||||||
|
|
||||||
|
int ledIndex(int logical) {
|
||||||
|
return (NUM_LEDS - 1) - logical;
|
||||||
|
}
|
||||||
|
|
||||||
|
void generateNewSequence(bool easy) {
|
||||||
|
for (int i = 0; i < NUM_LEDS; i++) {
|
||||||
|
if (easy)
|
||||||
|
{
|
||||||
|
sequence[i] = 0;
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
sequence[i] = random(0, 2);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void setAll(uint32_t color) {
|
||||||
|
for (int i = 0; i < NUM_LEDS; i++) {
|
||||||
|
strip.setPixelColor(i, color);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void resetGame() {
|
||||||
|
setAll(strip.Color(0, 0, 0));
|
||||||
|
strip.show();
|
||||||
|
currentStep = 0;
|
||||||
|
gameWon = false;
|
||||||
|
digitalWrite(austausch_master_pin, LOW);
|
||||||
|
}
|
||||||
|
|
||||||
|
void winAnimation() {
|
||||||
|
strip.show();
|
||||||
|
delay(250);
|
||||||
|
|
||||||
|
setAll(strip.Color(0, 0, 0));
|
||||||
|
strip.show();
|
||||||
|
delay(250);
|
||||||
|
|
||||||
|
for (int i = 0; i < NUM_LEDS; i++) {
|
||||||
|
strip.setPixelColor(
|
||||||
|
ledIndex(i),
|
||||||
|
strip.Color(35, 10, 0)
|
||||||
|
);
|
||||||
|
strip.show();
|
||||||
|
delay(20);
|
||||||
|
}
|
||||||
|
|
||||||
|
setAll(strip.Color(35, 10, 0));
|
||||||
|
strip.show();
|
||||||
|
}
|
||||||
|
|
||||||
|
void checkPress(int buttonID) {
|
||||||
|
if (buttonID == sequence[currentStep]) {
|
||||||
|
strip.setPixelColor(
|
||||||
|
ledIndex(currentStep),
|
||||||
|
strip.Color(35, 10, 0)
|
||||||
|
);
|
||||||
|
strip.show();
|
||||||
|
currentStep++;
|
||||||
|
|
||||||
|
if (currentStep >= NUM_LEDS) {
|
||||||
|
winAnimation();
|
||||||
|
gameWon = true;
|
||||||
|
digitalWrite(austausch_master_pin, HIGH);
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
resetGame();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void setup() {
|
||||||
|
pinMode(BUTTON1_PIN, INPUT_PULLUP);
|
||||||
|
pinMode(BUTTON2_PIN, INPUT_PULLUP);
|
||||||
|
pinMode(POWER_PIN, INPUT);
|
||||||
|
powerOnState = digitalRead(POWER_PIN) == HIGH;
|
||||||
|
pinMode(austausch_master_pin, OUTPUT);
|
||||||
|
pinMode(randomizer_master_pin, INPUT);
|
||||||
|
|
||||||
|
digitalWrite(austausch_master_pin, LOW);
|
||||||
|
|
||||||
|
strip.begin();
|
||||||
|
strip.show();
|
||||||
|
|
||||||
|
randomSeed(millis());
|
||||||
|
generateNewSequence(false);
|
||||||
|
resetGame();
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
void loop() {
|
||||||
|
//Detecting turn-off
|
||||||
|
if (powerOnState && digitalRead(POWER_PIN) == LOW) {
|
||||||
|
powerOnState = false;
|
||||||
|
resetGame();
|
||||||
|
}
|
||||||
|
//Detecting turn-on
|
||||||
|
if (!powerOnState && digitalRead(POWER_PIN) == HIGH) {
|
||||||
|
powerOnState = true;
|
||||||
|
}
|
||||||
|
if (!powerOnState) {
|
||||||
|
//We are turned-off and stop anything after here
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
// Master-D2 HIGH → neue Sequenz
|
||||||
|
if (digitalRead(randomizer_master_pin) == HIGH)
|
||||||
|
{
|
||||||
|
unsigned long resetTimer = millis();
|
||||||
|
while (digitalRead(randomizer_master_pin) == HIGH)
|
||||||
|
{
|
||||||
|
delay(10);
|
||||||
|
}
|
||||||
|
generateNewSequence(millis() - resetTimer > 150);
|
||||||
|
resetGame();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
int currentButton1State = digitalRead(BUTTON1_PIN);
|
||||||
|
int currentButton2State = digitalRead(BUTTON2_PIN);
|
||||||
|
|
||||||
|
if (!gameWon) {
|
||||||
|
if (lastButton1State == HIGH && currentButton1State == LOW) {
|
||||||
|
checkPress(0);
|
||||||
|
delay(200);
|
||||||
|
}
|
||||||
|
if (lastButton2State == HIGH && currentButton2State == LOW) {
|
||||||
|
checkPress(1);
|
||||||
|
delay(200);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
lastButton1State = currentButton1State;
|
||||||
|
lastButton2State = currentButton2State;
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user