Skip to content

Instantly share code, notes, and snippets.

@kwdowicz
Created March 23, 2026 07:36
Show Gist options
  • Select an option

  • Save kwdowicz/e0d97a6dd66de913bf32fa53e1a7ba5c to your computer and use it in GitHub Desktop.

Select an option

Save kwdowicz/e0d97a6dd66de913bf32fa53e1a7ba5c to your computer and use it in GitHub Desktop.
// PIN CONFIGURATION: ROOMS
const int flickerPin1 = 3;
const int flickerPin2 = 5;
const int flickerPin3 = 6;
const int stablePin1 = 9;
const int stablePin2 = 10;
const int stablePin3 = 11;
// PIN CONFIGURATION: ELEVATOR (Digital pins without PWM)
const int elevPin1 = 4;
const int elevPin2 = 7;
const int elevPin3 = 8;
const int elevPin4 = 12;
// PIN CONFIGURATION: BUZZER
const int buzzerPin = A0;
// BRIGHTNESS SETTINGS
const int defaultBrightness = 25;
const int peakBrightness = 255;
// BASE BRIGHTNESS FLUCTUATION (Rooms only)
const int minBaseBrightnessPct = 10;
const int maxBaseBrightnessPct = 80;
const unsigned long minBaseChangeTime = 5000;
const unsigned long maxBaseChangeTime = 30000;
// ELEVATOR SETTINGS (Toddler Mode)
const unsigned long elevStableMin = 15000; // Minimum time stable (15 seconds)
const unsigned long elevStableMax = 45000; // Maximum time stable (45 seconds)
const unsigned long elevTantrumDurationMin = 200; // Very short chaos burst
const unsigned long elevTantrumDurationMax = 1500; // Longer chaos burst
const unsigned long elevToggleMin = 20; // Fastest blink inside a burst
const unsigned long elevToggleMax = 100; // Slowest blink inside a burst
// BOOT SEQUENCE PARAMETERS
const unsigned long bootFadeInTime = 15000;
const unsigned long bootSpikeHoldTime = 3000;
const unsigned long bootFadeOutTime = 10000;
const unsigned long bootStableTime = 30000;
// PROBABILITIES FOR ROOMS (0 to 100)
const int chanceToFadeOut = 15;
const int chanceForDeepDip = 15;
const int chanceForFastBurst = 20;
const int chanceForUnstableWait = 20;
// TIMING SETTINGS FOR ROOMS
const int timeStableMin = 3000;
const int timeStableMax = 10000;
const int fadeOutDuration = 6000;
const int timeDeadMin = 2000;
const int timeDeadMax = 6000;
const int timeMicroFlickerMin = 10;
const int timeMicroFlickerMax = 45;
const int timeDeepDipMin = 100;
const int timeDeepDipMax = 350;
const int timeFastBurstMin = 10;
const int timeFastBurstMax = 60;
const int timeUnstableWaitMin = 100;
const int timeUnstableWaitMax = 400;
// INTERNAL VARIABLES: ROOMS
unsigned long nextChangeTime1 = 0, nextChangeTime2 = 0, nextChangeTime3 = 0;
unsigned long nextBaseChange1 = 0, nextBaseChange2 = 0, nextBaseChange3 = 0;
int ledState1 = 1, ledState2 = 1, ledState3 = 1;
int currentBright1 = defaultBrightness, currentBright2 = defaultBrightness, currentBright3 = defaultBrightness;
int targetBright1 = defaultBrightness, targetBright2 = defaultBrightness, targetBright3 = defaultBrightness;
// INTERNAL VARIABLES: ELEVATOR
unsigned long nextElevChange1 = 0, nextElevChange2 = 0, nextElevChange3 = 0, nextElevChange4 = 0;
unsigned long elevTantrumEnd1 = 0, elevTantrumEnd2 = 0, elevTantrumEnd3 = 0, elevTantrumEnd4 = 0;
int elevState1 = 1, elevState2 = 1, elevState3 = 1, elevState4 = 1; // 1 means STABLE, 0 means TANTRUM
void setup() {
// Set room pins
pinMode(flickerPin1, OUTPUT); pinMode(flickerPin2, OUTPUT); pinMode(flickerPin3, OUTPUT);
pinMode(stablePin1, OUTPUT); pinMode(stablePin2, OUTPUT); pinMode(stablePin3, OUTPUT);
// Set elevator pins
pinMode(elevPin1, OUTPUT); pinMode(elevPin2, OUTPUT); pinMode(elevPin3, OUTPUT); pinMode(elevPin4, OUTPUT);
// Set buzzer pin
pinMode(buzzerPin, OUTPUT);
// START BOOT SEQUENCE
// 1. Fade UP rooms (Elevator stays OFF in the dark)
digitalWrite(elevPin1, LOW); digitalWrite(elevPin2, LOW); digitalWrite(elevPin3, LOW); digitalWrite(elevPin4, LOW);
int stepTimeIn = bootFadeInTime / defaultBrightness;
for (int i = 0; i <= defaultBrightness; i++) {
analogWrite(flickerPin1, i); analogWrite(flickerPin2, i); analogWrite(flickerPin3, i);
analogWrite(stablePin1, i); analogWrite(stablePin2, i); analogWrite(stablePin3, i);
delay(stepTimeIn);
}
// 2. Sudden SPIKE (Elevator hard ON)
digitalWrite(elevPin1, HIGH); digitalWrite(elevPin2, HIGH); digitalWrite(elevPin3, HIGH); digitalWrite(elevPin4, HIGH);
analogWrite(flickerPin1, peakBrightness); analogWrite(flickerPin2, peakBrightness); analogWrite(flickerPin3, peakBrightness);
analogWrite(stablePin1, peakBrightness); analogWrite(stablePin2, peakBrightness); analogWrite(stablePin3, peakBrightness);
// Continuous beep during the overload spike
digitalWrite(buzzerPin, HIGH);
delay(bootSpikeHoldTime);
digitalWrite(buzzerPin, LOW);
// 3. Fade DOWN rooms (Elevator stays ON)
int stepsOut = peakBrightness - defaultBrightness;
int stepTimeOut = bootFadeOutTime / stepsOut;
for (int i = peakBrightness; i >= defaultBrightness; i--) {
analogWrite(flickerPin1, i); analogWrite(flickerPin2, i); analogWrite(flickerPin3, i);
analogWrite(stablePin1, i); analogWrite(stablePin2, i); analogWrite(stablePin3, i);
delay(stepTimeOut);
}
// 4. Stable WAIT
delay(bootStableTime);
// 5. Initialize timers
unsigned long currentTime = millis();
nextChangeTime1 = currentTime + random(0, 2000);
nextChangeTime2 = currentTime + random(0, 2000);
nextChangeTime3 = currentTime + random(0, 2000);
nextBaseChange1 = currentTime + random(minBaseChangeTime, maxBaseChangeTime);
nextBaseChange2 = currentTime + random(minBaseChangeTime, maxBaseChangeTime);
nextBaseChange3 = currentTime + random(minBaseChangeTime, maxBaseChangeTime);
nextElevChange1 = currentTime + random(elevStableMin, elevStableMax);
nextElevChange2 = currentTime + random(elevStableMin, elevStableMax);
nextElevChange3 = currentTime + random(elevStableMin, elevStableMax);
nextElevChange4 = currentTime + random(elevStableMin, elevStableMax);
}
void updateRoom(int pin, unsigned long &nextChangeTime, int &state, int &currentBrightness, int &targetBrightness, unsigned long &nextBaseChangeTime) {
if (millis() > nextBaseChangeTime) {
int randomPct = random(minBaseBrightnessPct, maxBaseBrightnessPct + 1);
targetBrightness = (randomPct * 255) / 100;
nextBaseChangeTime = millis() + random(minBaseChangeTime, maxBaseChangeTime);
if (state == 1) {
currentBrightness = targetBrightness;
analogWrite(pin, currentBrightness);
}
}
if (millis() > nextChangeTime) {
if (state == 1) {
if (random(100) < chanceToFadeOut) {
state = 2; currentBrightness = targetBrightness;
int stepTime = fadeOutDuration / targetBrightness;
if (stepTime < 1) stepTime = 1;
nextChangeTime = millis() + stepTime;
} else {
analogWrite(pin, 0); state = 0;
if (random(100) < chanceForDeepDip) {
nextChangeTime = millis() + random(timeDeepDipMin, timeDeepDipMax);
} else {
nextChangeTime = millis() + random(timeMicroFlickerMin, timeMicroFlickerMax);
}
}
}
else if (state == 2) {
currentBrightness--; analogWrite(pin, currentBrightness);
if (currentBrightness <= 0) {
state = 3; nextChangeTime = millis() + random(timeDeadMin, timeDeadMax);
} else {
int stepTime = fadeOutDuration / targetBrightness;
if (stepTime < 1) stepTime = 1;
nextChangeTime = millis() + stepTime;
}
}
else if (state == 3) {
currentBrightness = targetBrightness; analogWrite(pin, currentBrightness);
state = 1; nextChangeTime = millis() + random(timeStableMin, timeStableMax);
}
else if (state == 0) {
currentBrightness = targetBrightness; analogWrite(pin, currentBrightness);
state = 1;
int chance = random(100);
if (chance < chanceForFastBurst) {
nextChangeTime = millis() + random(timeFastBurstMin, timeFastBurstMax);
} else if (chance < chanceForFastBurst + chanceForUnstableWait) {
nextChangeTime = millis() + random(timeUnstableWaitMin, timeUnstableWaitMax);
} else {
nextChangeTime = millis() + random(timeStableMin, timeStableMax);
}
}
}
}
void updateElevator(int pin, unsigned long &nextChangeTime, unsigned long &tantrumEndTime, int &state) {
unsigned long currentMillis = millis();
if (state == 1) {
// STABLE STATE
if (currentMillis > nextChangeTime) {
state = 0; // Trigger the tantrum
tantrumEndTime = currentMillis + random(elevTantrumDurationMin, elevTantrumDurationMax);
nextChangeTime = currentMillis;
}
} else {
// TANTRUM STATE
if (currentMillis > tantrumEndTime) {
state = 1; // Calm down, back to stable
digitalWrite(pin, HIGH);
nextChangeTime = currentMillis + random(elevStableMin, elevStableMax);
} else if (currentMillis > nextChangeTime) {
// Toggle LED randomly inside the burst
int currentLedState = digitalRead(pin);
digitalWrite(pin, !currentLedState);
nextChangeTime = currentMillis + random(elevToggleMin, elevToggleMax);
}
}
}
void loop() {
updateRoom(flickerPin1, nextChangeTime1, ledState1, currentBright1, targetBright1, nextBaseChange1);
updateRoom(flickerPin2, nextChangeTime2, ledState2, currentBright2, targetBright2, nextBaseChange2);
updateRoom(flickerPin3, nextChangeTime3, ledState3, currentBright3, targetBright3, nextBaseChange3);
updateElevator(elevPin1, nextElevChange1, elevTantrumEnd1, elevState1);
updateElevator(elevPin2, nextElevChange2, elevTantrumEnd2, elevState2);
updateElevator(elevPin3, nextElevChange3, elevTantrumEnd3, elevState3);
updateElevator(elevPin4, nextElevChange4, elevTantrumEnd4, elevState4);
// Logika iskrzenia pradu dla buzzera
if (ledState1 == 0 || ledState2 == 0 || ledState3 == 0) {
if (millis() % 15 < 2) {
digitalWrite(buzzerPin, HIGH);
} else {
digitalWrite(buzzerPin, LOW);
}
} else {
digitalWrite(buzzerPin, LOW);
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment