A couple days ago I converted a 3way bulb lamp to a smart touch controlled 3way bulb lamp. After doing that I realized we had a lamp on our desk that was made smart using an smart outlet and a smart button.
The wife wasn’t crazy about the button laying around, so I figured I should convert this lamp to a touch lamp. I’d just received a couple of M5stampS3 with the esp32-S3 chip. I originally looked to use them on the 3way bulb lamp but failed to get the touch sensor to work. I posted the issue and fortunately peter-s had the answer.
So with the S3 chip and the smallest single channel relay I had sitting around I started out converting the lamp. For the most part I left the lamp intact. The only modification was to cut the hot wire and run it through the relay connected to the esp chip and to attach a touch sensor wire to the lamp.
I picked up these small boxes from amazon. The inside of the box had 4 elevated mounts screw spots on the top and bottom of the box. These took away too much room so I needed to cut them out of the box. I had to put three holes in the box, two for the lamp cord and one for the USB cable that powers the esp chip. It was tight in the box but I managed to get it all to fit.
I put tie-wraps on the lamp cord to keep it from shifting in the case. The esp had pins on both sides. I cut the pins off the side I wasn’t using to make it easier to slide the chip into the box. I put the extra cable running from the esp to the relay between them to keep the devices separated. I ran the touch wire out the same slot as the lamp cord. I actually had to cut of the slotted edge off the box top of part of the box because it was hitting the ESP and preventing the box from closing. As you can see I got it all in the box.
I drilled a hole in the lamp and put a screw in it to hold the touch wire in place.
Last thing to do was to burn the following program into the chip from HA ESPHOME add-on. I use a widows laptop with the esp connected to the laptop USB port. In the ESPHOME interface I
used the “Plug into this computer” option to write the esp flash. I’ve recently updated this code to include a switch that allows disabling the touch feature on the lamp and the ability to report a long press to HA. So the code below is an update. Details on these features were also added to the end of this post.
esphome:
name: "lamp-computer-room"
friendly_name: Lamp comp room
esp32:
board: esp32-s3-devkitc-1
framework:
type: arduino
# Enable logging
logger:
level: info
# level: debug
# 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: 3s
internal: True
text_sensor:
- platform: template
name: "comp room lamp"
id: comp_room_lamp
icon: "mdi:toggle-switch"
on_value:
then:
- if:
condition:
text_sensor.state:
id: comp_room_lamp
state: ""
else:
- delay: 200ms
- text_sensor.template.publish:
id: comp_room_lamp
state: !lambda 'return "";'
esp32_touch:
setup_mode: false
measurement_duration: 0.25ms
binary_sensor:
- platform: esp32_touch
name: "Touch Pad Pin 13"
pin: GPIO13
threshold: 550000
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:
- logger.log:
level: info
format: "Touch turn switch on"
- if:
# test to ignore random event on boot and when touch is disabled
condition:
- lambda: 'return (id(time_since_boot).raw_state > 1 && (!(id(touch_disabled).state)));'
then:
if:
condition:
# if light is off
- switch.is_off: power_switch
then:
# then we turn it on
- switch.turn_on: power_switch
- logger.log:
level: info
format: "Touch turn switch on"
else:
# else it's on so we turn it off
- switch.turn_off: power_switch
- logger.log:
level: info
format: "Touch turn switch off"
- min_length: 500ms
max_length: 2000ms
then:
- logger.log: "${devicename} long click"
- if:
# test to ignore random event on boot and when touch is disabled
condition:
- lambda: 'return (id(time_since_boot).raw_state > 1 && (!(id(touch_disabled).state)));'
then:
text_sensor.template.publish:
id: comp_room_lamp
state: !lambda 'return "long_press";'
# restart-button
button:
- platform: restart
name: "restart-esp32-dim-touch"
switch:
- platform: gpio
name: power_switch
id: power_switch
restore_mode: RESTORE_DEFAULT_OFF
pin: GPIO7
- platform: template
name: "touch disabled"
id: touch_disabled
restore_mode: ALWAYS_OFF
optimistic: true
At this point the last thing to do is set the touch detection value. Up above the lines:
logger:
# level: info
level: debug
and
esp32_touch:
setup_mode: true
This result in esphome logging the values being detected by the touch sensor. You have to look at the values being reported without touch and with touch. You want to select a value some where in the middle of these two reading to set the threshold value under the binary_sensor esp32_touch platform:
binary_sensor:
- platform: esp32_touch
name: "Touch Pad Pin 13"
pin: GPIO13
threshold: XXXXXX
You’ll burn your update to flash again. Once you’ve done the initial burn you can do all subsequent burns via wifi.
Once you have a threshold value set to something that gives a good touch response you need to change “logging” to info and set “setup_mode” to false and reinstall the ESP code.
I like the touch sensor on the esp32-s3. It works a lot better than the older esp32 that I used on the 3 way bulb lamp. I have a couple more three way bulb lamps I’m going to convert and I’m planning on using the M5stamp chip for those. If you look at the thread for the 3 way bulb lamp you’ll see I actually had to write some lambda code to get a satisfactory touch response.
My wife is very satisfied with this update. I hope the write-up is useful.
The ESP32 code listed above has been updated with a couple of features. First It includes a switch that can be used to disable the touch feature on the lamp. This is so that HA can have an automation that will disable the touch feature of all of the touch lamp so the lamps can be moved around during cleaning, and you don’t have to worry you’ll turn the lights on and off by this movement. The second update includes a text sensor that will report “long_press” if you hold your touch on the lamp for a few seconds. The room this lamp sits in also has an overhead lamp that is controlled by a Sonoff T0 G2 switch. I use this with an HA automation to toggle the overhead light by doing a long touch on the lamp.
Here’s the HA automation that toggles the touch feature on all of the touch enabled lamps before and after a cleaning session. This automation handles short, medium and long press events from the bottom touch pad of a Sonoff T0 G2 switch that controls multiple lights in the family room. The long touch on the Sonoff touch pad will flash the light in the family room so I know I’ve toggled this option and then it toggles the disable touch feature in the touch lamps. A short press will toggle the touch lamp in the family room on and off. A medium press will change the brightness of the family room touch lamp.
alias: Family room bottom switch toggle bs lamp
description: ""
trigger:
- platform: state
entity_id:
- sensor.family_room_lamps_ctrl_bottom_pad_event
condition: []
action:
- if:
- condition: state
entity_id: sensor.family_room_lamps_ctrl_bottom_pad_event
state: short
then:
- service: light.toggle
metadata: {}
data: {}
target:
entity_id: light.bs_family_room_lamp
else:
- if:
- condition: state
entity_id: sensor.family_room_lamps_ctrl_bottom_pad_event
state: medium
then:
- service: button.press
metadata: {}
data: {}
target:
entity_id: button.fr_lamp_touch_bs_brightness_step
else:
- if:
- condition: state
entity_id: sensor.family_room_lamps_ctrl_bottom_pad_event
state: long
then:
- service: light.toggle
target:
entity_id: light.bs_family_room_lamp
data: {}
- delay:
hours: 0
minutes: 0
seconds: 1
milliseconds: 0
- service: light.toggle
target:
entity_id: light.bs_family_room_lamp
data: {}
- delay:
hours: 0
minutes: 0
seconds: 1
milliseconds: 0
- service: light.toggle
target:
entity_id: light.bs_family_room_lamp
data: {}
- delay:
hours: 0
minutes: 0
seconds: 1
milliseconds: 0
- service: light.toggle
target:
entity_id: light.bs_family_room_lamp
data: {}
- service: switch.toggle
target:
entity_id: switch.fr_lamp_touch_bs_touch_disabled
data: {}
- service: switch.toggle
metadata: {}
data: {}
target:
entity_id: switch.master_bed_touch_lamp_touch_disabled
- service: switch.toggle
metadata: {}
data: {}
target:
entity_id: switch.lamp_computer_room_touch_disabled
mode: single
Here’s the HA automation that handles the long_press event from the lamp, toggling the overhead light:
alias: computer room light toggle on lamp long press
description: ""
trigger:
- platform: state
entity_id:
- sensor.lamp_computer_room_comp_room_lamp
to: long_press
condition: []
action:
- service: switch.toggle
target:
entity_id: switch.light_relay1_comp_room
data: {}
mode: single
For completeness I’m including the Sonoff T0 G2 code for the family room switch so you can see the complete thread tied to toggling the touch feature. While the Sonoff includes two relays, I do not use them with this wall switch. The Switch is used as a dumb switch that simply reports short, medium and long press events for the two touch pads. Automation in HA then determine what to do with these touches. About I included the automation that handles the bottom touch pad events.
esphome:
name: "family-room-lamps-ctrl"
friendly_name: "family room lamps ctrl"
esp8266:
board: esp8285
wifi:
ssid: !secret wifi_ssid
password: !secret wifi_password
# Enable fallback hotspot (captive portal) in case wifi connection fails
ap:
ssid: "Fam-Room-Switch"
password: !secret wifi_password
captive_portal:
api:
encryption:
key: !secret api_key
# Enable logging
logger:
level: info
ota:
password: !secret ota_password
# Enable Web server.
web_server:
port: 80
text_sensor:
- platform: template
name: "top_pad_event"
id: top_pad_event
icon: "mdi:toggle-switch"
on_value:
then:
- if:
condition:
text_sensor.state:
id: top_pad_event
state: ""
else:
- delay: 200ms
- text_sensor.template.publish:
id: top_pad_event
state: !lambda 'return "";'
- platform: template
name: "bottom_pad_event"
id: bottom_pad_event
icon: "mdi:toggle-switch"
on_value:
then:
- if:
condition:
text_sensor.state:
id: bottom_pad_event
state: ""
else:
- delay: 200ms
- text_sensor.template.publish:
id: bottom_pad_event
state: !lambda 'return "";'
# restart-button
button:
- platform: restart
name: "restart_switch"
binary_sensor:
- platform: gpio
internal: True
pin:
number: GPIO0
mode:
input: true
pullup: true
inverted: true
name: "top_touch_pad"
on_click:
- min_length: 50ms
max_length: 500ms
then:
- text_sensor.template.publish:
id: top_pad_event
state: !lambda 'return "short";'
- logger.log:
level: info
format: "short - FR top touch"
- min_length: 500ms
max_length: 1500ms
then:
- text_sensor.template.publish:
id: top_pad_event
state: !lambda 'return "medium";'
- logger.log:
level: info
format: "medium - FR top touch"
- min_length: 1500ms
max_length: 10000ms
then:
- text_sensor.template.publish:
id: top_pad_event
state: !lambda 'return "long";'
- logger.log:
level: info
format: "long - FR top touch"
- platform: gpio
internal: True
pin:
number: GPIO9
mode:
input: true
pullup: true
inverted: true
name: "bottom_touch_pad"
on_click:
- min_length: 50ms
max_length: 500ms
then:
- text_sensor.template.publish:
id: bottom_pad_event
state: !lambda 'return "short";'
- logger.log:
level: info
format: "short - FR bottom touch"
- min_length: 500ms
max_length: 1500ms
then:
- text_sensor.template.publish:
id: bottom_pad_event
state: !lambda 'return "medium";'
- logger.log:
level: info
format: "medium - FR bottom touch"
- min_length: 1500ms
max_length: 10000ms
then:
- text_sensor.template.publish:
id: bottom_pad_event
state: !lambda 'return "long";'
- logger.log:
level: info
format: "long - FR bottom touch"
output:
# Register the blue LED as a dimmable output ....
- platform: esp8266_pwm
id: blue_led
pin: GPIO13
inverted: true
# Example configuration entry
light:
- platform: status_led
id: status_light
name: "family_room_Switch_led"
output: blue_led