Joran — Binaire led puzzel
Deze puzzel, gemaakt door Joran, is een binaire led puzzel waarbij spelers een geheim getal moeten raden door middel van een potentiometer en een drukknop. De puzzel maakt gebruik van een 4-cijferig 7-segment display en 8 binaire leds om feedback te geven over de gekozen waarde.
#include <WiFi.h>
#include <esp_now.h>
#define SR_DATA 4
#define SR_LATCH 5
#define SR_CLOCK 6
#define SEG_D1 7
#define SEG_D2 8
#define SEG_D3 9
#define SEG_D4 10
const int BIN_PINS[8] = {35, 36, 37, 38, 39, 40, 41, 42};
#define RGB_R 45
#define RGB_G 48
#define RGB_B 47
#define SERVO_PIN 18
#define POT_PIN 1
#define BTN_PIN 14
#define POT_MAX 4095
const int LOCKED_ANGLE = 0;
const int UNLOCKED_ANGLE = 90;
uint8_t receiverMAC[] = {0x48, 0x3f, 0xda, 0x0c, 0x67, 0xbf};
enum Color { RED, GREEN, BLUE };
Color cableColor;
char StartPos[4] = {'O', 'H', 'L', 'C'};
typedef struct {
Color color;
bool reset;
} Message;
Message msg;
enum Phase { BINARY, DONE };
Phase phase = BINARY;
uint8_t selectedVal = 0;
uint8_t secretCodes[3];
uint8_t currentRound = 0;
unsigned long stableStart = 0;
bool wasStable = false;
const unsigned long STABLE_DURATION = 2000;
const uint8_t SEG_DIGITS[10] = {
0b00111111, // 0
0b00000110, // 1
0b01011011, // 2
0b01001111, // 3
0b01100110, // 4
0b01101101, // 5
0b01111101, // 6
0b00000111, // 7
0b01111111, // 8
0b01101111, // 9
};
const uint8_t L = 0b00111000;
const uint8_t O = 0b00111111;
const uint8_t C = 0b00111001;
const uint8_t H = 0b01110110;
const uint8_t SEG_BLANK = 0b00000000;
const uint8_t SEG_DASH = 0b01000000;
uint8_t segBuf[4] = {SEG_BLANK, SEG_BLANK, SEG_BLANK, SEG_BLANK};
void sendSegment(uint8_t data) {
digitalWrite(SR_LATCH, LOW);
shiftOut(SR_DATA, SR_CLOCK, MSBFIRST, data);
digitalWrite(SR_LATCH, HIGH);
}
void refreshDisplay() {
static uint32_t last = 0;
static uint8_t digit = 0;
if (micros() - last < 2000) return;
last = micros();
digitalWrite(SEG_D1, HIGH);
digitalWrite(SEG_D2, HIGH);
digitalWrite(SEG_D3, HIGH);
digitalWrite(SEG_D4, HIGH);
sendSegment(segBuf[digit]);
switch (digit) {
case 0: digitalWrite(SEG_D1, LOW); break;
case 1: digitalWrite(SEG_D2, LOW); break;
case 2: digitalWrite(SEG_D3, LOW); break;
case 3: digitalWrite(SEG_D4, LOW); break;
}
digit = (digit + 1) & 0x03;
}
void showNumber(uint8_t val) {
segBuf[0] = SEG_BLANK;
segBuf[1] = (val >= 100) ? SEG_DIGITS[val / 100] : SEG_BLANK;
segBuf[2] = (val >= 10) ? SEG_DIGITS[(val / 10) % 10] : SEG_BLANK;
segBuf[3] = SEG_DIGITS[val % 10];
}
void showRx(char tx) {
switch (tx) {
case 'O':
segBuf[0] = O; segBuf[1] = O; segBuf[2] = O; segBuf[3] = O;
break;
case 'H':
segBuf[0] = H; segBuf[1] = H; segBuf[2] = H; segBuf[3] = H;
break;
case 'L':
segBuf[0] = L; segBuf[1] = L; segBuf[2] = L; segBuf[3] = L;
break;
case 'C':
segBuf[0] = C; segBuf[1] = C; segBuf[2] = C; segBuf[3] = C;
break;
default:
segBuf[0] = SEG_BLANK;
break;
}
}
void showBinaryLEDs(uint8_t val) {
for (int i = 0; i < 8; i++)
digitalWrite(BIN_PINS[i], (val >> (7 - i)) & 1);
}
void setRGB(bool r, bool g, bool b) {
digitalWrite(RGB_R, r);
digitalWrite(RGB_G, g);
digitalWrite(RGB_B, b);
}
void sendColor(Color cableColor) {
msg.reset = false;
msg.color = cableColor;
esp_now_send(receiverMAC, (uint8_t *)&msg, sizeof(msg));
}
void setup() {
Serial.begin(9600);
pinMode(SR_DATA, OUTPUT);
pinMode(SR_CLOCK, OUTPUT);
pinMode(SR_LATCH, OUTPUT);
pinMode(SEG_D1, OUTPUT); digitalWrite(SEG_D1, HIGH);
pinMode(SEG_D2, OUTPUT); digitalWrite(SEG_D2, HIGH);
pinMode(SEG_D3, OUTPUT); digitalWrite(SEG_D3, HIGH);
pinMode(SEG_D4, OUTPUT); digitalWrite(SEG_D4, HIGH);
for (int i = 0; i < 8; i++) pinMode(BIN_PINS[i], OUTPUT);
pinMode(RGB_R, OUTPUT);
pinMode(RGB_G, OUTPUT);
pinMode(RGB_B, OUTPUT);
analogReadResolution(12);
analogSetPinAttenuation(POT_PIN, ADC_11db);
WiFi.mode(WIFI_STA);
esp_now_init();
esp_now_peer_info_t peer = {};
memcpy(peer.peer_addr, receiverMAC, 6);
peer.channel = 0;
peer.encrypt = false;
esp_now_add_peer(&peer);
randomSeed(analogRead(0));
for (int i = 0; i < 3; i++) secretCodes[i] = random(1, 256);
cableColor = (Color)random(0, 3);
showBinaryLEDs(secretCodes[0]);
setRGB(false, false, false);
}
void loop() {
refreshDisplay();
if (Serial.available()) {
char rx = Serial.read();
if (rx == 'M') {
sendColor(cableColor);
}
}
bool btn = digitalRead(BTN_PIN);
if (btn == HIGH) {
msg.reset = true;
msg.color = cableColor;
esp_now_send(receiverMAC, (uint8_t *)&msg, sizeof(msg));
msg.reset = false;
Serial.write('R');
currentRound = 0;
phase = BINARY;
wasStable = false;
stableStart = 0;
for (int i = 0; i < 3; i++) secretCodes[i] = random(1, 256);
cableColor = (Color)random(0, 3);
showBinaryLEDs(secretCodes[0]);
delay(200);
}
if (phase == BINARY) {
static int filtered = 0;
int raw = analogRead(POT_PIN);
filtered = (filtered * 7 + raw) / 8;
int clamped = constrain(filtered, 0, POT_MAX);
selectedVal = map(clamped, 0, POT_MAX, 0, 255);
showNumber(selectedVal);
uint8_t secret = secretCodes[currentRound];
int margin = max(1, secret * 5 / 100);
bool correct = abs(selectedVal - secret) <= margin;
int specialMargin = 5;
bool isSpecial = abs(selectedVal - 100) <= specialMargin;
if (correct) {
if (!wasStable) {
stableStart = millis();
wasStable = true;
} else if (millis() - stableStart >= STABLE_DURATION) {
currentRound++;
if (currentRound >= 3) {
char tx = StartPos[random(0, 4)];
Serial.write(tx);
showRx(tx);
phase = DONE;
} else {
showBinaryLEDs(secretCodes[currentRound]);
wasStable = false;
}
}
} else {
wasStable = false;
}
}
}