ADC to trigger multiple outputs based on voltage

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

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?

id(vol_up).toggle();

…I’d have thought.

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 ==========================

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

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

No way. :no_mouth:

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.

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

Here was an example using ‘on_value_range’ with multiple ranges.

1 Like

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

Ah think I got it