Hi, I want to trigger multiple (4) outputs based on the ADC voltage being read.
What I have is a combination switch, this switch reads different resistances when pressed.
float = 100k
vol up = 1k
vol down = 3.1k
next track = 2ohms
prev track = 330ohms
I am using a voltage divider with a 1K resistor to the ESP32 ADC pin 34.
sensor:
- platform: adc
pin: 34
name: "VCC Voltage"
update_interval: 1s
attenuation: auto
filters:
- multiply: 3.3
Would it be possible to trigger different outputs or switches based on the following voltages read by the ADC?
float = 2.7v
vol up = 5.6v
vol down = 8.4v
next track = 0.25v
prev track = 2.7v
Thanks
So far, ive come up with something like this, but I cant seem to set more then one range for the above and below values.
sensor:
- platform: adc
pin: 34
name: "VCC Voltage"
update_interval: 1s
attenuation: auto
filters:
- multiply: 3.3
on_value_range:
below: 0.5
above: 1
then:
- switch.toggle: vol_up:
switch:
- platform: gpio
pin: GPIO4
id: vol_up
name: "Heart switch"
inverted: true
- platform: gpio
pin: GPIO5
id: vol_down
name: "Heart switch"
inverted: true
- platform: gpio
pin: GPIO12
id: next_track
name: "Heart switch"
inverted: true
- platform: gpio
pin: GPIO10
id: previous_track
name: "Heart switch"
inverted: true
Mikefila
(Mike Fila)
3
You will need to use a lambda, this is a snippet of something I use to control a fan but hopefully it give you a basis to create your own.
on_value:
then:
lambda: |-
if (id(hum_ezo).state < 23.0) {
id(fan_pwm).set_level(0.00);
}
else if ((id(hum_ezo).state >= 23.0) and (id(hum_ezo).state <= 24.0)) {
id(fan_pwm).set_level(0.05);
}
else if ((id(hum_ezo).state > 24.0) and (id(hum_ezo).state <= 25.0)) {
id(fan_pwm).set_level(0.1);
}
else if ((id(hum_ezo).state > 25.0) and (id(hum_ezo).state <= 26.0)) {
id(fan_pwm).set_level(0.2);
Damn, thanks.
But how can I use it to switch a switch. Looks like you’re controlling PWM output?
Mikefila
(Mike Fila)
6
If you go to the core component in the esp docs, it will show you the lambda calls for that component.
https://esphome.io/components/switch/#lambda-calls
Ah ok, so something like
on_value:
then:
lambda: |-
if (id(adc_sensor).state < 23.0) {
id(my_switch1).toggle();
}
else if ((id(adc_sensor).state >= 23.0) and (id(adc_sensor).state <= 24.0)) {
id(my_switch2).toggle();
}
else if ((id(adc_sensor).state > 24.0) and (id(adc_sensor).state <= 25.0)) {
id(my_switch3).toggle();
}
else if ((id(adc_sensor).state > 25.0) and (id(adc_sensor).state <= 26.0)) {
id(my_switch4).toggle();
Compiling fails
Compiling .pioenvs/car/src/main.cpp.o
/config/esphome/car.yaml: In lambda function:
/config/esphome/car.yaml:59:4: error: expected primary-expression before ')' token
^
/config/esphome/car.yaml: In function 'void setup()':
/config/esphome/car.yaml:73:2: error: expected ')' before 'void'
- platform: gpio
^
)
/config/esphome/car.yaml:75:1:
id: next_track
src/main.cpp:398:44: note: to match this '('
lambdaaction_id = new LambdaAction<float>([=](float x) -> void {
^
/config/esphome/car.yaml:77:1: error: no matching function for call to 'esphome::LambdaAction<float>::LambdaAction()'
inverted: true
^
In file included from src/esphome.h:49,
from src/main.cpp:3:
src/esphome/core/base_automation.h:172:12: note: candidate: 'esphome::LambdaAction<Ts>::LambdaAction(std::function<void(Ts ...)>&&) [with Ts = {float}]'
explicit LambdaAction(std::function<void(Ts...)> &&f) : f_(std::move(f)) {}
^~~~~~~~~~~~
src/esphome/core/base_automation.h:172:12: note: candidate expects 1 argument, 0 provided
src/esphome/core/base_automation.h:170:32: note: candidate: 'esphome::LambdaAction<float>::LambdaAction(const esphome::LambdaAction<float>&)'
template<typename... Ts> class LambdaAction : public Action<Ts...> {
^~~~~~~~~~~~
src/esphome/core/base_automation.h:170:32: note: candidate expects 1 argument, 0 provided
src/esphome/core/base_automation.h:170:32: note: candidate: 'esphome::LambdaAction<float>::LambdaAction(esphome::LambdaAction<float>&&)'
src/esphome/core/base_automation.h:170:32: note: candidate expects 1 argument, 0 provided
/config/esphome/car.yaml:77:1: error: expected '}' at end of input
inverted: true
^
src/main.cpp:41:14: note: to match this '{'
void setup() {
^
*** [.pioenvs/car/src/main.cpp.o] Error 1
========================== [FAILED] Took 3.27 seconds ==========================
Troon
(Troon)
9
Without your entire code, debugging is a guessing game. My guess is that you failed to close the brackets at the end of your lambda.
My full code, sorry.
sensor:
- platform: adc
pin: 34
name: "VCC Voltage"
id: adc_sensor
update_interval: 1s
attenuation: auto
filters:
- multiply: 3.3
on_value:
then:
lambda: |-
if (id(adc_sensor).state < 1.0) {
id(vol_up).toggle();
}
else if ((id(adc_sensor).state >= 1.5) and (id(adc_sensor).state <= 3.0)) {
id(vol_down).toggle();
}
else if ((id(adc_sensor).state > 3.5) and (id(adc_sensor).state <= 7.0)) {
id(next_track).toggle();
}
else if ((id(adc_sensor).state > 7.5) and (id(adc_sensor).state <= 9.5)) {
id(previous_track).toggle();
switch:
- platform: gpio
pin: GPIO16
id: vol_up
name: "volume_up"
inverted: true
- platform: gpio
pin: GPIO17
id: vol_down
name: "volume_down"
inverted: true
- platform: gpio
pin: GPIO21
id: next_track
name: "next_track"
inverted: true
- platform: gpio
pin: GPIO22
id: previous_track
name: "previous_track"
inverted: true
Troon
(Troon)
11
Then I was right. Look at the section before the switch:
— you’ve opened a {
but not closed it.
Also, you can use the magic value x
(docs):
on_value:
then:
lambda: |-
if (x < 1.0) {
id(vol_up).toggle();
}
else if ((x >= 1.5) and (x <= 3.0)) {
id(vol_down).toggle();
}
else if ((x > 3.5) and (x <= 7.0)) {
id(next_track).toggle();
}
else if ((x > 7.5) and (x <= 9.5)) {
id(previous_track).toggle();
}
1 Like
Damn, that is actually working.
However, I don’t want it to toggle, i want it to pulse for like 1 second.
Is that possible, damn that would change the labmda completely right
Troon
(Troon)
13
No way.
You’re going to need to work out what that means for the device. All possible though: start here, and especially look under Actions:
It’ll just be replacing the toggle
calls with something a bit more in-depth.
Mikefila
(Mike Fila)
14
If the switches will always be momentary, you can probably get away with adding an automation to the switches.
on_turn_on
then:
- delay: 200ms
- switch.turn_off: relay_1
Yea, this is what I was thinking too,
Do I have to create an automation for this of can I simply add this directly to the switch?
Something like,
- platform: gpio
pin: GPIO22
id: previous_trk
name: "previous_track"
inverted: true
on_turn_on
then:
- delay: 200ms
- switch.turn_off: relay_1
mulcmu
17
Here was an example using ‘on_value_range’ with multiple ranges.
1 Like
Mikefila
(Mike Fila)
18
Add it right under the switch entries.
edit: Like this but it needs the id of the switch it’s under
- platform: gpio
pin: GPIO22
id: previous_trk
name: "previous_track"
inverted: true
on_turn_on
then:
- delay: 200ms
- switch.turn_off: previous_track ##relay_1
Damn, I must be struggling with indentation then because it does not like it