89 lines
3.6 KiB
Arduino
89 lines
3.6 KiB
Arduino
|
|
// Townhouse dollhouse lighting, Arduino Uno R3, discrete zone outputs (no addressable data line).
|
||
|
|
// Each zone = one PWM pin -> 1k -> PN2222 base; transistor sinks that zone's LEDs to ground.
|
||
|
|
// Each LED has its own ~200-220 ohm series resistor: +5V -> LED -> R -> transistor collector.
|
||
|
|
// FIRE zone uses a RED LED; all other zones warm-white/white. (Color is hardware only, no code change.)
|
||
|
|
// No library needed.
|
||
|
|
|
||
|
|
#define PIN_GF 3 // ground-floor interior (living + kitchen ceilings) -> Q1 base via 1k
|
||
|
|
#define PIN_UP 5 // upstairs interior (bedrooms + attic) -> Q2 base via 1k
|
||
|
|
#define PIN_EXT 6 // exterior (porch, entry, deck, balcony) -> Q3 base via 1k
|
||
|
|
#define PIN_FIRE 9 // fireplace / hearth (red) -> Q4 base via 1k
|
||
|
|
#define BTN_PIN 2 // momentary button to GND: cycles scenes / wakes
|
||
|
|
#define BTN_SECT 4 // momentary button to GND: spotlight one zone at a time (GF->UP->EXT->FIRE->off)
|
||
|
|
#define IDLE_OFF_MS (20UL * 60UL * 1000UL) // cordless: fade dark after 20 min idle
|
||
|
|
|
||
|
|
// Per-zone brightness 0-255. Dollhouse rooms read best DIM, this is your knob
|
||
|
|
// (or raise the LED series resistors to knock brightness back in hardware).
|
||
|
|
uint8_t gGF, gUP, gEXT;
|
||
|
|
bool fireOn;
|
||
|
|
|
||
|
|
// ---- Scenes ---------------------------------------------------------------
|
||
|
|
void sceneEvening(){ gGF = 60; gUP = 40; gEXT = 140; fireOn = true; } // cozy, fire lit
|
||
|
|
void sceneAllOn() { gGF = 90; gUP = 90; gEXT = 120; fireOn = true; }
|
||
|
|
void sceneNight() { gGF = 0; gUP = 0; gEXT = 30; fireOn = true; } // porch + embers
|
||
|
|
void sceneOff() { gGF = 0; gUP = 0; gEXT = 0; fireOn = false; }
|
||
|
|
|
||
|
|
typedef void (*Scene)();
|
||
|
|
Scene scenes[] = {sceneEvening, sceneAllOn, sceneNight, sceneOff};
|
||
|
|
const uint8_t N_SCENES = sizeof(scenes) / sizeof(scenes[0]);
|
||
|
|
uint8_t sceneIdx = 0;
|
||
|
|
unsigned long lastActive = 0;
|
||
|
|
|
||
|
|
// ---- Section spotlight ----------------------------------------------------
|
||
|
|
// BTN_SECT lights exactly ONE zone at a time, then all off, then repeats.
|
||
|
|
uint8_t sectIdx = 0; // 0=GF 1=UP 2=EXT 3=FIRE 4=all off
|
||
|
|
const uint8_t N_SECT = 5;
|
||
|
|
void applySpotlight(uint8_t i){
|
||
|
|
gGF = (i == 0) ? 90 : 0;
|
||
|
|
gUP = (i == 1) ? 90 : 0;
|
||
|
|
gEXT = (i == 2) ? 120 : 0;
|
||
|
|
fireOn = (i == 3);
|
||
|
|
}
|
||
|
|
|
||
|
|
void setup() {
|
||
|
|
pinMode(PIN_GF, OUTPUT); pinMode(PIN_UP, OUTPUT);
|
||
|
|
pinMode(PIN_EXT, OUTPUT); pinMode(PIN_FIRE, OUTPUT);
|
||
|
|
pinMode(BTN_PIN, INPUT_PULLUP);
|
||
|
|
pinMode(BTN_SECT, INPUT_PULLUP);
|
||
|
|
// Power-on self-check: pulse each output in turn, so a dead zone shows itself immediately.
|
||
|
|
const uint8_t pins[] = {PIN_GF, PIN_UP, PIN_EXT, PIN_FIRE};
|
||
|
|
for (uint8_t i = 0; i < 4; i++) { analogWrite(pins[i], 120); delay(220); analogWrite(pins[i], 0); }
|
||
|
|
scenes[sceneIdx]();
|
||
|
|
lastActive = millis();
|
||
|
|
}
|
||
|
|
|
||
|
|
void loop() {
|
||
|
|
// Button: cycle scene + reset idle timer.
|
||
|
|
static bool prev = HIGH;
|
||
|
|
bool now = digitalRead(BTN_PIN);
|
||
|
|
if (prev == HIGH && now == LOW) {
|
||
|
|
sceneIdx = (sceneIdx + 1) % N_SCENES;
|
||
|
|
scenes[sceneIdx]();
|
||
|
|
lastActive = millis();
|
||
|
|
delay(30); // debounce
|
||
|
|
}
|
||
|
|
prev = now;
|
||
|
|
|
||
|
|
// Section button: spotlight one zone at a time (GF -> UP -> EXT -> FIRE -> off).
|
||
|
|
static bool prevS = HIGH;
|
||
|
|
bool nowS = digitalRead(BTN_SECT);
|
||
|
|
if (prevS == HIGH && nowS == LOW) {
|
||
|
|
sectIdx = (sectIdx + 1) % N_SECT;
|
||
|
|
applySpotlight(sectIdx);
|
||
|
|
lastActive = millis();
|
||
|
|
delay(30); // debounce
|
||
|
|
}
|
||
|
|
prevS = nowS;
|
||
|
|
|
||
|
|
// Cordless battery saver.
|
||
|
|
if (millis() - lastActive > IDLE_OFF_MS) sceneOff();
|
||
|
|
|
||
|
|
analogWrite(PIN_GF, gGF);
|
||
|
|
analogWrite(PIN_UP, gUP);
|
||
|
|
analogWrite(PIN_EXT, gEXT);
|
||
|
|
// Fireplace: amber-ish flicker around a low base when on.
|
||
|
|
analogWrite(PIN_FIRE, fireOn ? (55 + random(0, 130)) : 0);
|
||
|
|
|
||
|
|
delay(30); // ~33 Hz, smooth flicker, snappy button
|
||
|
|
}
|