This tread provides details for converting a three way bulb lamp into a smart touch lamp. A less than one second touch turns the lamp on and off. A 1 to 10 second touch cycles through the three brightness levels.
The end product is controlled via an integrated esp32 board that includes two relays. If I could get the touch function working on the esp32-S3 I’d probable use one of the M5 products with a separate 2 relay board because it would be much smaller. I previously provided some input here about this effort as I was figuring out how to modify the lamp. This is the details for the first lamp I modified. I did figure out the esp32-S3 and built subsequent lamps with it. Details about that implementation are in a subsequent posted :
Originally, I was going to try and fit the electronics within the lamp but decided that was too big of a pain. In the end product the electronics are currently housed as part of the cord. Since the lamp needs both 110v and 5v, I’m currently feeding the product with two cords. One is a 110v line, the second is from a USB phone adaptor. This feeds power to the electronics box. Then from the electronics box I have a cord with three stands of 18 gauge wire and a small wire for the touch sensor.
The items used for this project are:
- ESP32 board with integrated relays.
- A replacement light socket that doesn’t have a knob
- Wire with 3 stands 18 gauge
- A box to hold the electronics
- The previous power cord from the lamp
- Low gauge wire that can be soldered to the ESP board and screwed to the lamp. I just used some old stuff I had sitting around.
- Wrap to make the 3 stand wire and touch sensor wire look like one wire
- Wire connectors
While the link for the ESP board is form amazon I actually found the board cheaper on both ebay, walmart and aliexpress. I got three feet of the 3 strand 18 gauge cord from home depot for $.75 per foot.
The first challenge was figuring out how to flash the ESP board. I started trying to do it via ESP home that is integrated with home assistant. This failed and only provided the error failed to connect. I was using a windows laptop with a USB TTL adaptor, attempting to use the install from the “Plug into this computer” option. To do the initial flash I installed the command line version of ESP home on my windows laptop, which worked without issue.
To put the ESP board in flash mode you have to hold the IO0 button when you apply power (plug in the USB TTL board). While still holding the IO0 button you tap the reset button (labeled EN). Finally, you release the IO0 button and the board should be ready to flash.
To use the esphome tool you need a text file with basic configuration. You can build this file in notepad. It should look something like the following:
substitutions:
esphome_name: touch-lamp
esphome:
name: "${esphome_name}"
platform: ESP32
board: esp32dev
# Enable Home Assistant API
api:
encryption:
key: "XXXXXXXXXXXXXXXXXXXXXXXXX"
ota:
password: "XXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX"
wifi:
ssid: "XXXXXXX"
password: "XXXXXXXXXXXXXXXXXXXXXXX"
# Enable fallback hotspot (captive portal) in case wifi connection fails
ap:
ssid: "${esphome_name} hotspot"
password: "whatever"
captive_portal:
time:
- platform: homeassistant
# Enable Web server.
web_server:
port: 80
logger:
# Text sensors with general information.
text_sensor:
# Expose ESPHome version as sensor.
- platform: version
name: "${esphome_name} ESPhome ver"
# Expose WiFi information as sensors.
- platform: wifi_info
ip_address:
name: "${esphome_name} IP"
ssid:
name: "${esphome_name} SSID"
sensor:
# General
- platform: uptime
name: "${esphome_name} - Uptime Sensor"
- platform: wifi_signal
name: "${esphome_name} - WiFi Signal"
update_interval: 60s
You need to replace the Xs above with a good encryption key, a good ota password, the ssid for you wifi and the password for your wifi. You will also use this same configuration in the HA integrated version of esphome. When using the stand alone version of ESPhome you will flash the board via the com port. This is the USB TTL adaptor simlar to this as it gives access to 5V and 3.3v. Once you’ve done the initial flashing you can then update the esp program via wifi from the integrated version of esphome.
This picture shows the USB to TTL adaptor connected to the board. I set the board in the orientation showed in the picture to help ensure I had a good connection on the pins. You need to connect 5V, ground, transmit data and receive data from the TTL adaptor to the ESP board. Transmit data from the TTL board goes to Receive data on the ESP board. These 4 pins are clearly labeled on the bottom of the board.
With the TTL board plugged into your windows machine and connected to the esp board you flash it running something like the following in a windows command prompt:
esphome run "Documents\touch_lamp.txt"
you need to update the file name touch_lamp.txt to the name of the file where you stored the initial configuration. The board will flash and then hang waiting for the board to reset. You have to tap the reset button (EN) for the board to boot the just installed program. When the board resets you will see the associated ESP log in your windows command prompt. Look at this output to find the IP address assigned to your board. Us the IP address in your web browser to access the web server provided by the ESP board. Assuming this all works then the board should be discovered by HA. I reset HA to kickoff the discovery action.
At this point you can fire up esphome within HA. You add a device with the same configuration above. Then try and install that configuration over wifi. Assuming that works you can then install a more complete version of the esp code via HA’s esphome interface. The code here is the code I originally used on my lamp, obviously your device name will be different. In a post below I’ve provided alternative code that looks to address the fact that the range of touch values seem to change over time. I’m now testing that new code and it appears to work better in handling the changing touch events.
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
#Readings calculated from espTouch sensors
- platform: template
name: "Touch Readings"
id: "touch_readings"
update_interval: 10s
accuracy_decimals: 0
lambda: |-
return ((uint32_t) id(touch_sensor)->get_value());
esp32_touch:
setup_mode: True
iir_filter: 10ms
low_voltage_reference: 0.5V
high_voltage_reference: 2.7V
voltage_attenuation: 1.5V
binary_sensor:
- platform: esp32_touch
name: "esp32 touch sensor"
id: touch_sensor
#pin: GPIO32
pin: GPIO27
threshold: 900
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:
switch.turn_off: power
- min_length: 500ms
max_length: 10s
# longer touch to change brightness
then:
- button.press: cycle_brightness
switch:
- platform: gpio
name: "low_level_filament"
pin: 17
id: low_level
internal: True
- platform: gpio
name: "high_level_filament"
pin: 16
id: high_level
internal: True
- platform: template
name: power
id: power
restore_mode: RESTORE_DEFAULT_OFF
lambda: |-
if (id(low_level).state || id(high_level).state) {
return true;
} else {
return false;
}
turn_on_action:
- select.set:
id: modus_mode
option: "low"
#- switch.turn_on:
turn_off_action:
- select.set:
id: modus_mode
option: "off"
select:
- platform: template
name: "brightness"
id: modus_mode
optimistic: true
options:
- "off"
- "low"
- "medium"
- "high"
initial_option: "off"
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();
}
button:
# button to cycle brightness
- 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: "medium"
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"
# restart-button
- platform: restart
name: "restart-esp32-dim-touch"
The esp32 web page should how look like this:
The configuration is set to print out the touch sensors value as you’ll need this information to set a threshold in the esp code appropriate for your lamp.
In HA this will look like this:
At this point it’s probably time to power the ESP board via the screw down power connectors on the board. I cut the end off a USB cable. Normally a USB cable contain 4 wires (some only have two power lines). The +5V DC is normally red and -DC is normally black. You connect these two wires to the 5V and GND screw down connectors on the board. Now you can power your board from you USB power adaptor. Make sure the board boots by verifying you can access the ESP web page.
For 110v you need to connect the 3 stand cord to your socket. If you look at the socket the screw in the center is neutral, while the screws to the right and left are hot. The two hot lines from this cord get connected to the ESP board at the NO1 and NO2 screw down connectors. The neutral stand from the 3 stand cord should be connected to the neutral side of the wall plug cord you’re using. In the US the larger prong of the cord is neutral. The hot side of the wall plug cord needs to be connected with two short wires that then get connected to the two screw down pins labeled COM1 and COM2 on the ESP board.
At this point if you plug in the 110v line you should be able to turn on the light from the ESP web page.
To control the lamp via touch you need to solder a thin gauge wire to one of the ESP capable touch pins (GPIO). I believe you have 10 pins you could use. The confirmation file I’ve provided uses GPIO pin 27. On the bottom of the ESP board this pin is labeled as G27. The other end of this wire need to be attached to your lamp. I drilled a small whole in the base of the lamp, under where the cord goes into the lamp and attached the wire with a screw here.
I put the electronics in a box. I used a step bit to make different size holes for the four wires. For the smaller wires I tied knots in them so they wouldn’t be pulled from the board. For the three strand cord I put a tie wrap on it to keep it in place.
Here we have all of the parts connected:
The lamp shade back on with the box cover in place:
You need to configure values so the touch sensor works consistently. Hopefully you only have to select a threshold value. In the configuration I provided you should see this threshold line:
threshold: 900
You pick the value by watching the log output from the ESP board. This shows typical output from my lamp’s esp log:
With out touching the lamp the value is above 900. When the lamp is touched it drops below 900. Thus I’ve selected 900 as my value. I had some problems where the touch would work while sitting on the couch, but if I was standing the touch didn’t work. I was going to look at the potential of trying to use an adaptive threshold. That’s why the esp code includes the sensor “Touch Readings”. I found some other suggestion in this thread for changing other touch related parameters. Setting the values:
low_voltage_reference: 0.5V
high_voltage_reference: 2.7V
voltage_attenuation: 1.5V
made it so the touch sensor worked both sitting and standing. Once you get a good touch threshold you need to change
setup_mode: True
to
setup_mode: False
You might also want to remove these lines as they send a message every 10 seconds to HA:
- platform: template
name: "Touch Readings"
id: "touch_readings"
update_interval: 10s
accuracy_decimals: 0
lambda: |-
return ((uint32_t) id(touch_sensor)->get_value());
I would really have liked to use the M5 StampS3 with a separate dual relay board as it’s a smaller solution. Sadly I couldn’t get the touch sensor to work with this esp32s3. If anyone has any insight into how to get touch to work with this version of the esp32 I welcome the input.
It was suggested that I set the light to present a monochromatic light so that it would work as a dimmer slider in HA. I’ll be looking at that next.