How to make an old fashioned three way (three brightness) table lamp - smart?

My son think’s it over kill. He also suggested just using a smart bulb. I’m not a fan of smart bulbs as they don’t work with existing switches in the house. I always feel like smart bulbs result in a dumb house. If you don’t have your phone you’re out of luck for turning on the light. That said, the real issue for me is I need to keep the experience as close to the existing experience or my wife doesn’t like it.

If you’re not going to bother reading my entire response, I won’t bother writing it. Goodbye.

Sorry, I wasn’t suggesting your suggestion was bad, it just doesn’t work in my environment. Have a good one.

I did get the esp32 wroom to work with this configuration:

esphome:
  name: lamp-esp32-dim-touch
  friendly_name: lamp_esp32_dim_touch

esp32:
  board: esp32dev
  #framework:
  #  type: arduino

# Enable logging
logger:

# Enable Home Assistant API
api:
  encryption:
    key: !secret api_key

ota:
  password: !secret ota_password 

wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password

  # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: "Lamp-Esp32-Dim-Touch"
    password: !secret wifi_password

# Enable Web server.
web_server:
  port: 80
  
captive_portal:

# restart-button
button:
  - platform: restart
    name: "restart-esp32-dim-touch"

output:
  - platform: ac_dimmer
    id: dimmer1
    gate_pin: 21
    zero_cross_pin:
      number: 19
      mode: INPUT_PULLUP
      #  input: true
      inverted: yes

light:
  - platform: monochromatic
    output: dimmer1
    name: esp32 Dimmerized Light

I then switched from using the LED ceiling light to just a standard socket dimmable bulb and sadly I see the flicker problem that is mentioned across the web. I’m going to pick up a higher quality dimmable LED bulb and see if it still flickers a lower power settings.

I decided to try using the 5v pin instead of the 3.3 pin to drive the dimmer. Upon doing this the performance running on the ESP 32 was similar to the ESP 8266. At 5v the flicker was significantly reduced when the light was not at full power. However the remaining flicker makes the light unexceptionable when dimmed.

1 Like

I agree but then you have the scenario where if there is an issue with any motion detector etc., someone not familiar with the situation trying to turn the light on and actually turning it off, and it still won’t go on, etc. So - not ideal but may work for some people.

I agree, the WAF is important - particularly if you are in a situation like me where nyou wife doesn’t like it but tolerates it. Every once in a blue moon however, I do get the statement similar to “Hey that’s kind of cool.”

Hi, great work on this
Do you mind posting demo videos?
I’m leaning towards rotary encoder because my wife gets annoyed having to long press the wall switch to dim the smart lights

Once I try a couple of different LED bulbs to see if I can find a bulb that doesn’t flicker when dimmed I’ll try and capture and post a video.

Using the esp32 I did manage to get the lamp to work as a touch sensor. Some instructions were posted here. I picked up a GE 150W LED to give it a try. Sadly the flicker was terrible with the ESP32. I switched back to the esp8266 and the flicker was minimal with this bulb, however not perfect. The change in flicker indicates the ESP board has an impact on the signal being sent to the dimmer board. I’m not sure how to address this. I’ve order a few items to just try turning the lamp into a smart three way lamp, as I know the three way bulb works without flicker. The items are as follows:

Satco 3 way socket
DC 5V Relay Module 2-Channel Relay
ESP32-WROOM Development Board 2-channel WIFI Relay Module

The relay board and the ESP with relay are redundant. I hop to use the ESP with relay. The separate relay board is just a backup.

1 Like

The touch sensor is supported natively by the ESP32, ESP32-S2, and ESP32-S3 chips so you’ll have to use one of those to do the touch detection.

I have put my project on hold; I was able to get the touch detection working well, and independently I was able to get the triggering of the lamp’s capacitive touch sensor working, but so far I haven’t figured out how to get the two to work concurrently. The problem I’m running into is that I’m connected to the lamp’s body to detect touches, and I’m also connecting the lamp’s body to a capacitor and a SPST switch (controlled by the ESP) and then to the input of the lamp’s capacitive touch sensor. So I’m getting a feedback loop where I’m both trying to detect touches and simulate touches simultaneously.

My next thought is to break open the lamp’s capacitive touch device to see if I can trigger it some way other than a change in capacitance. It will probably be a month or more before I pick this back up though.

Edit:
here’s what I’ve done so far, which doesn’t work. If you disconnect the black wire from the base of the lamp but leave purple connected, it detects touches perfectly. If you disconnect purple but leave black connected, it simulates touches and controls the dimmer perfectly. If you have both connected, it goes crazy. If you have neither connected, nothing works.


I’m using a triple 2-channel multiplexer chip because that’s just what I happened to have on hand. Any sort of SPST switch would work in its place.

1 Like

I received the dual relay board that doesn’t have an integrated ESP. I ran a test with this board and esp32-wroom board. The code below appears to work. I say appears as I don’t have the new three way socket yet so I just watched the relay response. The lamp is converted to a touch lamp. The only issue is the touchpad code runs at boot, so every time the device reboots the light would be turned on to lowest power. Hopefully I can find a fix as I don’t want the lamps to be on after a power outage.

esphome:
  name: lamp-esp32-dim-touch
  friendly_name: lamp_esp32_dim_touch

esp32:
  board: esp32dev

# Enable logging
logger:

# Enable Home Assistant API
api:
  encryption:
    key: !secret api_key

ota:
  password: !secret ota_secret

wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password

  # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: "Lamp-Esp32-Dim-Touch"
    password: !secret wifi_password

# Enable Web server.
web_server:
  port: 80
  
captive_portal:

# restart-button
button:
  - platform: restart
    name: "restart-esp32-dim-touch"

switch:
  - platform: gpio
    name: "low_level_filament"
    pin: 12
    id: low_level
  - platform: gpio
    name: "high_level_filament"
    pin: 13
    id: high_level

esp32_touch:
  setup_mode: false
  iir_filter: 10ms

binary_sensor:
  - platform: esp32_touch
    name: "ESP32 Touch Pad GPIO4"
    pin: GPIO4
    threshold: 320
    filters:
      # Small filter, to debounce the spurious events.
      - delayed_on: 10ms
    on_click:
    - min_length: 10ms
      max_length: 500ms
      then:
        if:
          condition:
            and:
              - switch.is_off: low_level
              - switch.is_off: high_level
          then:
            - switch.turn_on: low_level
            - switch.turn_off: high_level
          else:
            - switch.turn_off: low_level
            - switch.turn_off: high_level
    - min_length: 500ms
      max_length: 10s
      then:
        if:
          condition:
            and:
              - switch.is_off: low_level
              - switch.is_off: high_level
          then:
            - switch.turn_on: low_level
            - switch.turn_off: high_level
          else:
            if:
              condition:
                and:
                  - switch.is_on: low_level
                  - switch.is_off: high_level
              then:
                - switch.turn_off: low_level
                - switch.turn_on: high_level
              else:
                if:
                  condition:
                    and:
                      - switch.is_off: low_level
                      - switch.is_on: high_level
                  then:
                    - switch.turn_on: low_level
                    - switch.turn_on: high_level
                  else:
                    - switch.turn_on: low_level
                    - switch.turn_off: high_level

For purposes of reboots, on bootup you can check the last state from an input helper possibly (whihc would have to be updated as things change so it is ‘ready’ to be read at bootup - ?

Found a way to avoid processing the short event that happens at boot on the touch sensor. The implemented ignores short touches for 30s after boot.

esphome:
  name: lamp-esp32-dim-touch
  friendly_name: lamp_esp32_dim_touch

esp32:
  board: esp32dev

# Enable logging
logger:

# Enable Home Assistant API
api:
  encryption:
    key: !secret api_key

ota:
  password: !secret ota_password

wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password

  # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: "Lamp-Esp32-Dim-Touch"
    password: !secret wifi_password

# Enable Web server.
web_server:
  port: 80
  
captive_portal:

sensor:
  - platform: uptime
    name: Uptime Sensor
    id: time_since_boot
    update_interval: 30s

# restart-button
button:
  - platform: restart
    name: "restart-esp32-dim-touch"

switch:
  - platform: gpio
    name: "low_level_filament"
    pin: 12
    id: low_level
  - platform: gpio
    name: "high_level_filament"
    pin: 13
    id: high_level

esp32_touch:
  setup_mode: false
  iir_filter: 10ms

binary_sensor:
  - platform: esp32_touch
    name: "ESP32 Touch Pad GPIO4"
    pin: GPIO4
    threshold: 320
    filters:
      # Small filter, to debounce the spurious events.
      - delayed_on: 10ms
      - delayed_off: 10ms
    #on_press:
    on_click:
    - min_length: 10ms
      max_length: 500ms
      # Short touch to turn light on and off
      then:
        if:
          # test to ignore random event on boot
          condition:
            - lambda: 'return  id(time_since_boot).raw_state > 10;'
          then:
            if:
              condition:
                and:
                  # if light is off
                  - switch.is_off: low_level
                  - switch.is_off: high_level
              then:
                # then we turn it on
                - switch.turn_on: low_level
                - switch.turn_off: high_level
              else:
                # else it's on so we turn it off
                - switch.turn_off: low_level
                - switch.turn_off: high_level
    - min_length: 500ms
      max_length: 10s
      # longer touch to change brightness
      then:
        if:
          condition:
            and:
              # if light is off 
              - switch.is_off: low_level
              - switch.is_off: high_level
          then:
            # set to lowest level
            - switch.turn_on: low_level
            - switch.turn_off: high_level
          else:
            if:
              condition:
                and:
                  # if at low bright
                  - switch.is_on: low_level
                  - switch.is_off: high_level
              then:
                # go to medium bright
                - switch.turn_off: low_level
                - switch.turn_on: high_level
              else:
                if:
                  condition:
                    and:
                      # if at medium bright
                      - switch.is_off: low_level
                      - switch.is_on: high_level
                  then:
                    # go to high bright
                    - switch.turn_on: low_level
                    - switch.turn_on: high_level
                  else:
                    # finally if at high bright go to low bright
                    - switch.turn_on: low_level
                    - switch.turn_off: high_level

Got my parts in and I’m happy to say it works. I still need to package the added electronics and install the thing in the lamp housing. At this point things look good. You can control the three light level and turn the thing on and off. I’m using the integrated esp32 with 2 relays and the light socket that I mentioned above. In the picture below the metal box is just a testing substitute for the lamp housing to act as the touch sensor.

In home assistance the device looks like this:

The esphome code is:

esphome:
  name: "fr-lamp-touch-bs"
  friendly_name: fr brian side lamp


esp32:
  board: esp32dev
  #framework:
  #  type: arduino

# Enable logging
logger:

# Enable Home Assistant API
api:
  encryption:
    key: !secret api_key

ota:
  password: !secret ota_password

wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password

  # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: "FR-Lamp-Touch"
    password: !secret wifi_password

# Enable Web server.
web_server:
  port: 80
  
captive_portal:

sensor:
  # hack so the touch sensor doesn't kick off at power on
  - platform: uptime
    name: Uptime Sensor
    id: time_since_boot
    update_interval: 30s


esp32_touch:
  setup_mode: False
  iir_filter: 10ms

binary_sensor:
  - platform: esp32_touch
    name: "ESP32 Touch Pad GPIO4"
    #pin: GPIO33
    pin: GPIO32
    threshold: 290
    filters:
      # Small filter, to debounce the spurious events.
      - delayed_on: 10ms
      - delayed_off: 10ms
    #on_press:
    on_click:
    - min_length: 10ms
      max_length: 500ms
      # Short touch to turn light on and off
      then:
        if:
          # test to ignore random event on boot
          condition:
            - lambda: 'return  id(time_since_boot).raw_state > 10;'
          then:
            - button.press: pwr_btn
    - min_length: 500ms
      max_length: 10s
      # longer touch to change brightness
      then:
        - button.press: cycle_brightness

select:
  - platform: template
    name: "Template select"
    id: modus_mode
    optimistic: true
    options:
      - "off"
      - "low"
      - "med"
      - "high"
    initial_option: "off"
#    set_action:
#      - logger.log:
#          format: "Chosen option: %s"
#          args: ["x.c_str()"]
    on_value:
      then:
        - lambda: |-
            if (id(modus_mode).active_index() == 0) {
              id(low_level).turn_off();
              id(high_level).turn_off();
            } else if (id(modus_mode).active_index() == 1) {
              id(low_level).turn_on();
              id(high_level).turn_off();
            } else if (id(modus_mode).active_index() == 2) {
              id(low_level).turn_off();
              id(high_level).turn_on();
            } else if (id(modus_mode).active_index() == 3) {
              id(low_level).turn_on();
              id(high_level).turn_on();
            }         

# restart-button
button:
  - platform: restart
    name: "restart-esp32-dim-touch"

  - platform: template
    name: pwr btn
    id: pwr_btn
    on_press:
      then:
        if:
          condition:
            and:
              # if light is off
              - switch.is_off: low_level
              - switch.is_off: high_level
          then:
            # then we turn it on
            - select.set:
                id: modus_mode
                option: "low"
          else:
            # else it's on so we turn it off
            - select.set:
                id: modus_mode
                option: "off"

  - platform: template
    name: cycle brightness
    id: cycle_brightness
    on_press:
      then:
        if:
          condition:
            and:
              # if light is off 
              - switch.is_off: low_level
              - switch.is_off: high_level
          then:
            # set to lowest level
            - select.set:
                id: modus_mode
                option: "low"
          else:
            if:
              condition:
                and:
                  # if at low bright
                  - switch.is_on: low_level
                  - switch.is_off: high_level
              then:
                # go to medium bright
                - select.set:
                    id: modus_mode
                    option: "med"
              else:
                if:
                  condition:
                    and:
                      # if at medium bright
                      - switch.is_off: low_level
                      - switch.is_on: high_level
                  then:
                    # go to high bright
                    - select.set:
                        id: modus_mode
                        option: "high"
                  else:
                    # finally if at high bright go to low bright
                    - select.set:
                        id: modus_mode
                        option: "low"



switch:
  - platform: gpio
    name: "low_level_filament"
    pin: 16
    id: low_level
    #inverted: true
  - platform: gpio
    name: "high_level_filament"
    pin: 17
    id: high_level

Will need to figure out a way to have a nice control inside of HA. Should be something like a ceiling fan control. If anyone has knowledge on how to do the HA side please provide some suggestions.

Burning the code to the integrated esp32/relay board required me to use the offline esphome code. The GUI version failed to establish communications with the device. Once I get the build finished in the lamp with the electronics protected I’ll write everything up as a share your project item.

Someone asked for a video of the device working. I tried to add one but it doesn’t appear this forum allows the posting of videos. So if you still want a video just let me know where you want it posted.

enjoy.

Just installed everything in the lamp. Used 18 gauge x 3 strands wire that I got from home depot for $.75 per foot between the 3 way socket to the electronics. The electronics are in a small box outside the lamp. For power I have a USB adaptor providing 5V and the old plug providing 110 to the electronics box. Coming out the other side is the 18x3 gauge wire and a much thinner wire connected to the lamp as the touch sensor. Glad to say I now I have smart 3 bulb lamp that can be enabled by touch or from HA. Still need to work the presentation on the HA side to provide a better way to select brightness. Right now just using the power button in HA to turn lamp on and off.

I would set up the esp code to present a monochromatic light as the only external device, and everything else would be internal only. That would result a light with a dimmer slider in home assistant. You can set up the code so that it turns on the low element between 0-33%, the high element between 33-66%, and both elements between 66-100%. When you touch the lamp you can set the brightness internally to 33, 66, or 100 and that will update the slider in HA. You’ll need to use gamma_correct: 1 to get the percentages to work correctly.

This is fantastic, keep going!

With regards To your ceiling fan comment I have a pull chain ceiling fan with three speeds and I would love it if it could be controlled by the chain or by Home Assistant - both - seamlessly as can be done for example with a Shelley relay and a wall switch set as edge. (Foe example, if you use the chain to make it medium speed then HA knows that - and if you make it medium speed through HA then the chain switch “knows” that and another pull of the chain would make it go corectrly to the next speed expected…

I did enter a question about that on this forumn some time ago, but got a kooky answer that I should use three relays - one for each speed… LOL

Have you looked at the SONOFF iFan04-L. I’ve used them on ceiling fans. If you can fit it under the cover they work well. I used some heavy duty tie wraps to hold them in place. The chain doesn’t work but you can use the remote instead of the chain. The ones I have I flashed with TASMOTA.

Just did the clean up job on the lamp. Here’s the final product.

Going to write it up and then I’ll drop a link here to cross reference it.

I got it worked out and will post an update shortly. The updated is the second configuration in this post.

You can find a write up on the build here.

1 Like