Here’s how I monitor a gas stove (Bosch HGS8655UC) with 6 stovetop burners and an oven. I’m using esphome and a M5Stamp S3 controller. The complete system is installed inside the front panel of the stove so that there is no indication from the outside that this is now a smart stove.
I found a hollow shaft rotary potentiometer that fits on the shaft of the stove’s knobs: Pre-Wired Hollow Shaft Potentiometer | RH24PC | P3 America. For the 6 burner knobs, this potentiometer is slim enough to fit on the shaft inside the panel without pushing the knob out so they can be installed without any external visible changes. These potentiometers allows for knowing the exact position of each of the knobs.
All the black wires of the rotary pots were connected to 0V and all the red wires to 3.3V on the esp. Each of the center white wires were connected to an ADC pin. The controller will see a voltage between 0 and 3.3V depending on the position of the knob. The pots need to be tied down so they dont’t spin freely. I used magnetic zip tie mounts. The magnet attaches to the inside panel and zip ties to the flanges on the pots. Before tying down each pot, I aligned each so that it would be easier to map knob position to burner status. For each burner, as you turn the knob, it goes from off to max on to min on. So I set up the pots so that when the knob was in the off position, the voltage would be slightly above 0V. As it rotates a little bit, it would cross over 0 and hit max 3.3V and then the voltage would continue to go down. Thus, the voltage level would map to the burner level.
For the oven knob, there is less extra space on the shaft so using the above potentiometer would cause the knob to noticeably stick out. To monitor the oven, I instead used the existing electrical wiring. The oven knob assembly has 3 connected switches. With a multimeter, I determined the functionality of each. One is the ignition switch and triggered when the knob is pushed in. Another is switched when the broiler is turned on. The last switch is normally open and closed when the oven is on. Specifically, it’s switched on as long as the oven fan is running so it remains on for awhile after the oven is turned off until the temperature cools down. I tapped into this switch to monitor the oven by using a piggy back spade connector. I used an optocoupler to detect 120V AC on these wires and to convert it to a 3.3V DC signal to be fed into the esp.
To make the installation clean, I wanted to put everything inside the space available from the front panel between the stove top and oven. To enable this, I wanted to power the esp from the wires inside the stove itself. The front panel clock is powered by 12V AC. I tapped into these wires and hooked it up to an AC to DC step down voltage converter to output 5V DC which was then used to power the esp. So the entire system works from within the stove and no wires needed to be run outside.
I also added a Dallas temperature sensor DS18B20 to monitor the temperature inside the stove.
Here’s the esphome config. For the burner sensors, I mapped input voltages to 0-100% by measuring the voltage at the extreme end for each knob and set that to 10%. I included an additional aggregate binary sensor ‘stove’ which is on if any burner or oven is on.
one_wire:
- platform: gpio
pin: 44
sensor:
- platform: dallas_temp
address: 0x153ce1e380431828
name: 'internal temperature'
- platform: adc
pin: 1
attenuation: 12db
name: "back middle burner"
device_class: ""
id: "burner_back_middle"
icon: mdi:gas-burner
unit_of_measurement: '%'
accuracy_decimals: 0
update_interval: 1s
filters:
- calibrate_linear: # convert voltage to percent
datapoints:
- 1.66 -> 10 # set the lowest on to 10%
- 3 -> 100
- clamp:
min_value: 0
max_value: 100
- or:
- throttle: 180s
- delta: 1
- platform: adc
pin: 2
attenuation: 12db
name: "front middle burner"
device_class: ""
id: "burner_front_middle"
icon: mdi:gas-burner
unit_of_measurement: '%'
accuracy_decimals: 0
update_interval: 1s
filters:
- calibrate_linear: # convert voltage to percent
datapoints:
- 1.66 -> 10 # set the lowest on to 10%
- 3 -> 100
- clamp:
min_value: 0
max_value: 100
- or:
- throttle: 180s
- delta: 1
# pin 3 is strapping pin, don't use
- platform: adc
pin: 4
attenuation: 12db
name: "back left burner"
device_class: ""
id: "burner_back_left"
icon: mdi:gas-burner
unit_of_measurement: '%'
accuracy_decimals: 0
update_interval: 1s
filters:
- calibrate_linear: # convert voltage to percent
datapoints:
- 1.69 -> 10 # set the lowest on to 10%
- 3 -> 100
- clamp:
min_value: 0
max_value: 100
- or:
- throttle: 180s
- delta: 1
- platform: adc
pin: 5
attenuation: 12db
name: "back right burner"
device_class: ""
id: "burner_back_right"
icon: mdi:gas-burner
unit_of_measurement: '%'
accuracy_decimals: 0
update_interval: 1s
filters:
- calibrate_linear: # convert voltage to percent
datapoints:
- 1.64 -> 10 # set the lowest on to 10%
- 3 -> 100
- clamp:
min_value: 0
max_value: 100
- or:
- throttle: 180s
- delta: 1
- platform: adc
pin: 6
attenuation: 12db
name: "front right burner"
device_class: ""
id: "burner_front_right"
icon: mdi:gas-burner
unit_of_measurement: '%'
accuracy_decimals: 0
update_interval: 1s
filters:
- calibrate_linear: # convert voltage to percent
datapoints:
- 1.74 -> 10 # set the lowest on to 10%
- 3 -> 100
- clamp:
min_value: 0
max_value: 100
- or:
- throttle: 180s
- delta: 1
- platform: adc
pin: 7
attenuation: 12db
name: "front left burner"
device_class: ""
id: "burner_front_left"
icon: mdi:gas-burner
unit_of_measurement: '%'
accuracy_decimals: 0
update_interval: 1s
filters:
- calibrate_linear: # convert voltage to percent
datapoints:
- 1.67 -> 10 # set the lowest on to 10%
- 3 -> 100
- clamp:
min_value: 0
max_value: 100
- or:
- throttle: 180s
- delta: 1
binary_sensor:
- platform: gpio
icon: mdi:stove
pin: 43
name: 'oven'
id: 'oven'
# on/off sensor for entire stove (if any burner or the oven is on)
- platform: template
name: 'stove'
id: 'stove'
icon: mdi:stove
lambda: |-
return id(oven).state ||
id(burner_back_left).state > 0 || id(burner_back_middle).state > 0 || id(burner_back_right).state > 0 ||
id(burner_front_left).state > 0 || id(burner_front_middle).state > 0 || id(burner_front_right).state > 0;