Warum sich mit einer langweiligen, statischen Lampe zufrieden geben, wenn man ein Smart-Home-Meisterwerk haben kann, das auf Berührung reagiert? Heute nehme ich mir eine gewöhnliche Glaskugellampe vor und verpasse ihr ein massives „Gehirn-Transplantat“.

Mit einem D1 Mini (ESP8266), einem LIS3DH-Beschleunigungssensor und einem maßgefertigten 3D-gedruckten Sockel habe ich eine Lampe gebaut, die sich perfekt in Home Assistant integriert und – das Beste daran – einfach durch Antippen oder Klopfen auf das Glas gesteuert werden kann.

Vergiss teure Smart Lights aus dem Handel; so baust du dir deine eigene!

📺 Schau dir den kompletten Aufbau an

Sieh dir die Tap-Steuerung in Aktion an und verfolge den Aufbau Schritt für Schritt in meinem neuesten Video (Hinweis: Video auf Englisch):

YouTube Video

💡 Das Konzept: „Kinetische“ smarte Beleuchtung

Die meisten „Touch“-Lampen nutzen kapazitive Sensoren, die Metalloberflächen oder leitfähige Farbe benötigen. Da diese Lampe aus Glas und Kunststoff besteht, habe ich einen anderen Ansatz gewählt. Durch den Einsatz eines LIS3DH-Beschleunigungssensors erkennt die Lampe winzige Vibrationen, die entstehen, wenn du auf den Tisch oder die Kugel selbst tippst.

Das Gehirn der Operation ist der D1 Mini (ESP8266). Er liest die Sensordaten aus und führt ESPHome aus, was es uns ermöglicht, diese Vibrationen lokal zu verarbeiten und Lichteffekte sofort auszulösen.

🛠️ Teileliste

Hier ist genau das, was ich für den Bau verwendet habe (Affiliate-Links):

  • Die Lampe: Eine gewöhnliche Milchglas-Kugellampe (z. B. IKEA FADO oder ähnlich).
  • Mikrocontroller: D1 Mini ESP8266
  • Sensor: LIS3DH 3-Achsen-Beschleunigungssensor (I2C) – du könntest auch einen anderen Beschleunigungssensor verwenden.
  • LEDs: WS2812b LED-Ring (12, 16 oder 24 LEDs passen gut)
  • Stromversorgung: Micro-USB-Kabel und USB-Netzteil
  • Optional: Fotowiderstand zur Erkennung der Raumhelligkeit

🖨️ Der 3D-gedruckte Sockel

Der ursprüngliche Sockel der Lampe war zu klein, um die Elektronik sauber zu verstecken. Also habe ich meinen 3D-Drucker angeworfen und einen passenden Ersatzsockel entworfen.

Hier kannst Du die 3D Daten herunterladen:

https://www.printables.com/model/1521134-smart-ikea-fado-lamp

💻 Die Software: ESPHome Magie

Die wahre Magie passiert im Code. Ich nutze ESPHome, da es sich perfekt in Home Assistant integriert.

Hier ist ein Ausschnitt der YAML-Konfiguration, die ich zur Erkennung des Klopfens verwendet habe (inklusive meiner benutzerdefinierten Lichteffekte):


i2c:
  id: bus_a
  sda: D2
  scl: D1
  scan: true

globals:
  - id: lis_addr
    type: uint8_t
    initial_value: '0x18'  

esphome:
  name: ${name} 
  friendly_name: ${friendly_name} 
  name_add_mac_suffix: false
  on_boot:
    priority: 200   
    then:
      - delay: 300ms
      - lambda: |-
          auto* bus = id(bus_a);
          uint8_t addr = id(lis_addr);

          // Hilfsfunktionen zum Lesen/Schreiben der Register
          auto WR = [&](uint8_t reg, uint8_t val){ uint8_t d[2]={reg,val}; bus->write(addr,d,2); };
          auto RD = [&](uint8_t reg){ bus->write(addr,&reg,1,false); uint8_t v=0; bus->read(addr,&v,1); return v; };

          uint8_t who = RD(0x0F);
          ESP_LOGI("lis3dh","WHO_AM_I = 0x%02X (erwarte 0x33)", who);

          // 400 Hz, XYZ an
          WR(0x20, 0x5F);     // CTRL_REG1: ODR=400Hz, X/Y/Z aktiv
          WR(0x21, 0x04);     // CTRL_REG2: HPCLICK=1 (Hochpassfilter nur für Tap)
          (void) RD(0x26);    // REFERENCE lesen, HPF Referenz

          WR(0x23, 0x08);     // CTRL_REG4: High-Resolution = 1 (feinere Erkennung)
          WR(0x24, 0x00);     // CTRL_REG5: LIR_CLICK=0 (kein Latch)

          // Konfiguration der Tap-Empfindlichkeit
          WR(0x38, 0x15);     // CLICK_CFG: XS=1, YS=1, ZS=1 (alle Achsen Einzelklick)
          WR(0x3A, 0x0C);     // CLICK_THS: niedrigerer Wert -> empfindlicher
          WR(0x3B, 0x18);     // TIME_LIMIT: etwas länger -> zählt auch weichere Taps
          WR(0x3C, 0x30);     // TIME_LATENCY: Totzeit nach Tap (verhindert Doppeltreffer)
          WR(0x3D, 0x00);     // TIME_WINDOW: 0 (kein Doppeltippen nötig)

          // Klick auf INT1/INT2 routen (falls dein Breakout nur einen INT Pin hat)
          WR(0x22, 0x80);  // CTRL_REG3: I1_CLICK
          WR(0x25, 0x80);  // CTRL_REG6: I2_CLICK

          // Status lesen -> löschen
          uint8_t src0 = RD(0x39);
          ESP_LOGI("lis3dh","CLICK_SRC (nach init) = 0x%02X", src0);

      - light.turn_on:
          id: fado
          brightness: 0.3
          red: 1.0
          green: 0.66
          blue: 0.43

esp8266:
  board: d1_mini   

script:
  - id: toggle_fado
    then:
      - light.toggle: fado

light:
  - platform: neopixelbus
    id: fado
    name: "FADO"
    pin: D4                
    num_leds: 16
    type: GRB
    variant: WS2812
    method: ESP8266_UART1 
    default_transition_length: 300ms
    gamma_correct: 2.2

    effects:
      # --- STANDARD EFFEKTE ---
      - pulse:
          name: "Langsames Pulsieren"
          transition_length: 2s
          update_interval: 2s
      - addressable_rainbow:
          name: "Regenbogen Loop"
          speed: 10
          width: 16
      - addressable_color_wipe:
          name: "Farbwischen"

      # --- BENUTZERDEFINIERTE LAMBDA EFFEKTE ---

      # 1. KERZENFLACKERN
      - addressable_lambda:
          name: "Kerzenflackern"
          update_interval: 16ms
          lambda: |-
            static int state = 0;
            static int phase = 0;
            int r = 255; 
            int g = 120; 
            int b = 0; 

            int flick = random(0, 80); 
            int intensity = 180 - flick; 

            for (int i = 0; i < it.size(); i++) {
              it[i] = Color(r * intensity / 255, g * intensity / 255, b * intensity / 255);
            }

      # 2. POLIZEILICHT / SIRENE
      - addressable_lambda:
          name: "Polizeilicht"
          update_interval: 100ms
          lambda: |-
            static int step = 0;
            step++;
            if (step >= it.size()) step = 0;

            for (int i = 0; i < it.size(); i++) {
              if ((i + step) % 16 < 8) {
                it[i] = Color(255, 0, 0); // Rot
              } else {
                it[i] = Color(0, 0, 255); // Blau
              }
            }

      # 3. STERNENFUNKELN / GLITTER
      - addressable_lambda:
          name: "Sternenfunkeln"
          update_interval: 30ms
          lambda: |-
            // FIX: .get() nutzen um Farbe zu holen, skalieren und zurückschreiben
            for (int i = 0; i < it.size(); i++) {
              Color c = it[i].get();
              it[i] = c * 0.9f; 
            }

            if (random(0, 10) < 3) { 
              int pos = random(0, it.size());
              it[pos] = Color(255, 255, 255);
            }

      # 4. LAVALAMPE (PLASMA)
      - addressable_lambda:
          name: "Lavalampe"
          update_interval: 50ms
          lambda: |-
            static float phase = 0.0;
            phase += 0.1; 
            if (phase > 2 * 3.14159) phase -= 2 * 3.14159;

            for (int i = 0; i < it.size(); i++) {
              float hue = phase + (float)i / it.size() * 3.14159;
              int r = (sin(hue) + 1.0) * 127.5;
              int g = (sin(hue + 2.094) + 1.0) * 127.5; 
              int b = (sin(hue + 4.188) + 1.0) * 127.5; 
              it[i] = Color(r, g, b);
            }

interval:
  - interval: 10ms
    then:
      - lambda: |-
          static bool last_ia = false;         // letzter IA-Status
          static uint32_t last_tap_ms = 0;     // Sperrzeit-Timer
          const uint32_t REFRACTORY_MS = 400;  // Sperrzeit nach Tap

          auto* bus = id(bus_a);
          uint8_t addr = id(lis_addr);
          uint8_t reg = 0x39;                   // CLICK_SRC
          bus->write(addr, &reg, 1, false);
          uint8_t src = 0; bus->read(addr, &src, 1);

          bool ia = src & 0x40;                 // Interrupt Active
          bool any_axis = src & 0x15;           // XS|YS|ZS (irgendeine Achse Single)

          uint32_t now = millis();
          if (!last_ia && ia && any_axis && (now - last_tap_ms > REFRACTORY_MS)) {
            last_tap_ms = now;
            ESP_LOGI("lis3dh","Tap! CLICK_SRC=0x%02X", src);
            id(toggle_fado).execute();          // sicheres Toggeln
          }
          last_ia = ia;

sensor:
  - platform: adc
    pin: A0
    name: "Raumhelligkeit"
    update_interval: 5s
    filters:
      - lambda: |-
          return (1.0 - x) * 100;
    unit_of_measurement: "%"

🏠 Home Assistant Integration

Sobald der ESP geflasht ist, wird die Lampe automatisch von Home Assistant erkannt (via Native API). Das bedeutet, du kannst:

  • Die Lampe an- und ausschalten.
  • Die Farbe und Helligkeit direkt über dein Dashboard steuern.
  • Den Raumhelligkeitssensor für Automatisierungen nutzen (z.B. „Wenn Raum dunkel, mach Licht an“).

🎉 Fazit

Dieses Upgrade verändert die Atmosphäre im Raum komplett. Es ist ein lustiges, interaktives Gadget, mit dem Gäste gerne spielen. Wenn du einen 3D-Drucker und einen Lötkolben hast, ist das ein Pflicht-Projekt fürs Wochenende.

Hast du schon etwas Ähnliches gebaut? Schreib es mir unten in die Kommentare!

Categories:

No responses yet

Schreibe einen Kommentar

Deine E-Mail-Adresse wird nicht veröffentlicht. Erforderliche Felder sind mit * markiert