Build Sheets

01 · Brief

The subspace beacon wall mount is both a signal and a receiver. A person can set their status proactively, or the status can be set remotely to get someone’s attention. That second part is how it is normally used. The 24-LED ring shows that room’s beacon state exactly as the dashboard draws it: available, busy, away, alert. Turning the encoder previews a state and pressing it commits the change to the server, which pushes it to every terminal and every other lamp over one event stream. A separate button toggles the light locally without touching state.

Only one fully flashed, printed, installed, and in use. More planned.

02 · System

USB 5VESP32WS2812 RING→ LCARS CORE
ENCODERBUTTONLCARS CORE→ ESP32

03 · Source

subspace_lamp.ino

  // Encoder: enter/extend select mode.
  int detents = takeDetents();
  if (detents != 0) {
    if (!selecting) {
      selecting = true;
      candidate = liveState;
    }
    candidate = ((candidate + detents) % NUM_STATES + NUM_STATES) % NUM_STATES;
    selectStart = millis();
    DBG("preview: %s\n", STATE_NAMES[candidate]);
  }
  if (selecting && millis() - selectStart >= SELECT_TIMEOUT_MS) selecting = false;

  // Encoder press: commit the previewed state.
  if (pressed(PIN_ENC_SW, swEdge, swLevel) && selecting) {
    selecting = false;
    commitState(candidate);
    liveState = candidate;  // optimistic; heartbeat reconciles within 5s
    displayOn = true;
    DBG("committed: %s\n", STATE_NAMES[candidate]);
  }
Lines 213–233 of 258 · Full source →

04 · Lessons

330 ohms on the ring data line and 1000 microfarads across the ring supply. No level shifter needed, but the capacitor on the ring is a pain to fit.

Dark will be the default state :)