Maths in ESPHome

Hello there!

This is my first post… So if i’m doing something wrong, let it me know.

I digitalize my old Kenwood Receiver with an digital potenziometer.

Everthing works fine, till i try to add Buttons for Volume up/down.
My Problem ist, i cant figure out, how to increment or decrement 1.

This is my code. at the bottom you can see my buttons.

.YAML

esphome:
  name: verstaerker
  includes:
    - CustomDigipotOutput.h
  

esp8266:
  board: d1_mini

# Enable logging
logger:

# Enable Home Assistant API
api:
  services:
    - service: control_pot
      variables:
        level: float
      then:
        - output.set_level:
            id: lautstaerke_digipoti
            level: !lambda 'return level / 100.0;'

ota:

wifi:
  ssid: ""
  password: ""

  # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: ""
    password: ""

captive_portal:


spi:
  clk_pin: D5
  mosi_pin: D7
  miso_pin: D6


output:
- platform: custom
  type: float
  lambda: |-
    auto custom_digipot_output = new CustomDigipotOutput();
    App.register_component(custom_digipot_output);
    return {custom_digipot_output};

  outputs:
    id: lautstaerke_digipoti

number:
  - platform: template
    name: "Lautstärke Anlage"
    id: lautsarke
    optimistic: true
    min_value: 0
    max_value: 100
    initial_value: 5
    step: 1
    mode: slider
    on_value:
      then:
         - output.set_level:
             id: lautstaerke_digipoti
             level: !lambda 'return x / 100.0;'

switch:
    - platform: gpio
      name: "Unmute Anlage"
      pin: D1
      
    - platform: gpio
      name: "Power Anlage"
      pin: D2
 
button:
    - platform: template
      name: Anlage lauter
      id: lautstaerke_plus
      on_press:
        then:
          - logger.log: Anlage lauter
          - output.set_level: 
              id: lautstaerke_digipoti
              level: !lambda 'return id(lautstaerke_digipoti) + 1;'

    - platform: template
      name: Anlage leiser
      id: lautstaerke_minus
      on_press:
        then:
          - logger.log: Anlage leiser
          - output.set_level: 
              id: lautstaerke_digipoti
              level: !lambda 'return id(lautstaerke_digipoti) - 1;'

And here ist my CustomDigipotOutput.h:

#include "esphome.h"
using namespace esphome;
#include <SPI.h>

const int shutdownPin = D1;
int CS= D8;

class CustomDigipotOutput : public Component, public FloatOutput {
	public:
		void setup() override {
			// This will be called by App.setup()
			pinMode(CS, OUTPUT);
			pinMode (shutdownPin, OUTPUT);
			digitalWrite(shutdownPin, HIGH);
			SPI.begin();
		}

		//write to Pot
		void digitalPotWrite(int value)
		{
			delay(50);
			digitalWrite(CS, LOW);
			delay(50);
			SPI.transfer(B00000000);
			SPI.transfer(value);
			delay(50);
			SPI.transfer(B00010000);
			SPI.transfer(value);
			delay(50);
			digitalWrite(CS, HIGH);
		}  

		void write_state(float state) override {
			// state is the amount this output should be on, from 0.0 to 1.0

			// we need to convert it to an integer first
			int value = state * 255;
			ESP_LOGD("CustomDigipotOutput", "write_state %d", value);
			digitalPotWrite(value);
		}
};

Some parts are in German, because I’m German :slight_smile:

What am I doing wrong?
Can someone tell me?

EDIT:
this is my acutall error:

Compiling .pioenvs\verstaerker\src\main.cpp.o
verstaerker.yaml: In lambda function:
verstaerker.yaml:89:35: error: cannot convert 'esphome::output::FloatOutput*' to 'float' in return
verstaerker.yaml: In lambda function:
verstaerker.yaml:99:35: error: cannot convert 'esphome::output::FloatOutput*' to 'float' in return
*** [.pioenvs\verstaerker\src\main.cpp.o] Error 1

i tried it with .state at the end of my variable but then i get the message “no member named state”

No one can help ne? :frowning:

Well, maybe you need to wait a bit longer than just 2 hours. This is a worldwide forum, and most posts see a response within about 24 hours.

The expression id(lautstaerke_digipoti) alone just gives you access to the entity, not its state. Try appending .state to retrieve the actual number value of that entity.

              level: !lambda 'return id(lautstaerke_digipoti).state + 1.0;'

And I think this error message confirms my suspicion: You get your custom FloatOutput, not a float value.

Yeah, I’m sorry!
IT wasn’t meant mean, just asking ^^
Next time I’ll wait longer :slight_smile:

I tried It before, then I’ll get the Error ‘state’ isn’t a member.
I told before

Entity Not variable*

This is the full Error:

verstaerker.yaml: In lambda function:
verstaerker.yaml:89:36: error: 'class esphome::output::FloatOutput' has no member named 'state'
verstaerker.yaml: In lambda function:
verstaerker.yaml:99:36: error: 'class esphome::output::FloatOutput' has no member named 'state'
*** [.pioenvs\verstaerker\src\main.cpp.o] Error 1

Oh, sorry, didn’t see that FloatOutput doesn’t actually has a state that can be accessed.

I was just looking through some code examples, and it appears as if each component implements their own state method or variable, like for example the Sensor does. And because FloatOutput itself does not appear to keep the internal state, you may need to implement this yourself in your custom component.

Or, as an alternative, I am wondering if it would be possible to implement an increment() and decrement() method in your custom component, and call that instead?

Can u help me with this?
I can’t figure out how I can do this.

Maybe when I’m able to send a bool state on button press.
If this is possible (can’t find something like this in the Docs) i could use an if to increment or decrement in my CustomDigipotOutput class?
Or am I totally wrong?

Sorry for the questions. normally I only programm in C++. I’m not the best in C :upside_down_face:
And what kind of language is this esphome config?

Nevermind, i got it after my search of increment in epshome.
I found my solution here: Increment

After the button worked, i changed the lamba’s in “number”, so everytime i change the value over the slider, my global variable gets the new value

Here the new code:

esphome:
  name: verstaerker
  includes:
    - CustomDigipotOutput.h
  

esp8266:
  board: d1_mini

# Enable logging
logger:

# Enable Home Assistant API
api:
  services:
    - service: control_pot
      variables:
        level: float
      then:
        - output.set_level:
            id: lautstaerke_digipoti
            level: !lambda 'return level / 100.0;'

ota:

wifi:
  ssid: "xxx"
  password: "xxx"

  # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: "Verstaerker Fallback Hotspot"
    password: "dbDxnz4MSAja"

captive_portal:


spi:
  clk_pin: D5
  mosi_pin: D7
  miso_pin: D6

globals:
   - id: my_global
     type: float
     restore_value: no
  
  
output:
  - platform: custom
    type: float 
    lambda: |-
      auto custom_digipot_output = new CustomDigipotOutput();
      App.register_component(custom_digipot_output);
      return {custom_digipot_output};

    outputs:
      id: lautstaerke_digipoti
    
number:
  - platform: template
    name: "Lautstärke Anlage"
    id: lautsarke
    optimistic: true
    min_value: 0
    max_value: 100
    initial_value: 5
    step: 1
    mode: slider
    on_value:
      then:
        - lambda: 'id(my_global) =  x / 100.0;'
        - output.set_level:
            id: lautstaerke_digipoti
            level: !lambda 'return x / 100.0;'

switch:
    - platform: gpio
      name: "Unmute Anlage"
      pin: D1
      
    - platform: gpio
      name: "Power Anlage"
      pin: D2
 
button:
    - platform: template
      name: Anlage lauter
      id: lautstaerke_plus
      on_press:
        then:
          - logger.log: Anlage lauter
          - lambda: 'id(my_global) += 0.01;'
          - output.set_level:
              id: lautstaerke_digipoti
              level: !lambda 'return id(my_global);'

    - platform: template
      name: Anlage leiser
      id: lautstaerke_minus
      on_press:
        then:
          - logger.log: Anlage leiser
          - lambda: 'id(my_global) -= 0.01;'
          - output.set_level:
              id: lautstaerke_digipoti
              level: !lambda 'return id(my_global);'

But thank you a lot, your idea with increment brought me on the right way.
I guess it’s not what u thought of, but it works now :slight_smile:

Thank you!!

1 Like

Okay… Last Thing.

Technically everything works fine.
When i change the value over my Buttons, the value Next to the slider is the old.

How is it possibly to update These value, When i change the loudness with the Buttons?

I am wondering if the global variable my_global and the number entity could be merged? After all, that number entity already represents a float value. So when you press one of the buttons, you would increase/decrease the number entity, and set the output’s value to the number entity’s value.

I’m not Sure.
I would have to Look in the docs of ‘number’
When i can create a variable in entity ‘number’ this could work.

But for now i haven’t the time, i celebrate my birthday :slight_smile:
Maybe thuesday i would have time ^^