Need Help - setting optimal times for heat pump based on Temperature, electricity price and Solar

Hi everyone,

I am currently waiting for my heat pump to be installed. To make it run as efficient and cost effective as possible, I would like to set it to run in a kind of “boost mode” for hot water and/or heating/cooling at certain times.

What I would like is to create is a “binary sensor” that checks the energy price, temperature forecast and maybe solar forecast (although I would exclude that for now) and then determine the optimal xx hours (I would say 3-4 hours is a good timeframe) to set the room temp and flow temp higher and then return it to the normal level.

I have nordpool, entso-e, tibber data and of course the HA built-in weather forecast and Solcast solar forecast.

I already found a “cheapest hours” template/binary sensor for energy prices, but would like to combine it with the temperature, since the outside temp makes a big difference for heat pump efficiency.

Essentially, the template, sensor, script, whatever would need to find the best compromise between temperature and price for the chosen number of consecutive hours.
Sadly my skills fall far short and I have no clue how to even start doing this, so I hope someone more skilled than me can help me create this.

Thanks!

You might try a Bayesian sensor.

This observes the state of several other sensors and generates a binary sensor which turns on when the conditions you want are likely to be optimal. You can set the probability of conditions being right at any level you like.

I have one that triggers when the house is “probably” empty, based on phone locations, lack of movement, times when I’m likely to be asleep, etc. It’s pretty accurate.

1 Like

Thanks. I will try to figure out what that is and whether it does what I need…:innocent:

Takes a bit of head scratching :tired_face:, but it’s a interesting idea.

1 Like

I have looked into it a bit, and I don’t think it does what I need. My problem is actually far simpler…in graphical terms I simply have two curves and am looking for the area where both are closest to each other…

It’s probably a fairly simple formula, but I was always terrible at math and am no good at yaml either…:grin:

The challenge is

  1. looking at the right values since we are talking about "future events) here. This is already quite complicated and I don’t understand the “cheapest hours” sensor I use for that really…but it works.
  2. finding the “min” for one sensor and the “max” for the other and then the area where both is true…:see_no_evil:

Ok, so I think I might be making a little progress here…

I discovered a custom component that is called “average” and it allows me to create an entity that calculates the average over a certain time.
I have now used this to create and average temperature for the day. Working from there, I should now be able to implement a rudimentary form of what I want, using the deviation from the average temp (above or below) as a condition Just like I can use the below or above average price. There is still a long way to go before this actually turns into something useful, but it’s (perhaps) a starting point.

I have a very similar situation here and have settled for a rather simple approach to begin with.

From the Nordpool integration, you have the average, min and max prices for the day. Using these, I have calculated levels halfway between max and average, calling that “expensive” level and similarly for “cheap” level - red and green in the following graph:
bild

The objective is to move your consumption away from the expensive hours and into the cheap hours. This will not reduce your consumption (it will, in fact, increase slightly because of increased losses), but it will reduce your cost - which is what you are after.

There are many ways to move consumption, but let’s focus on hot water production and heat - the biggies. I have found that in my house, increasing the heat in the basement during the cheap hours has little effect. It’s back to normal after about half an hour. Your conditions may be different. But hot water production is a good thing to start with.

To keep things simple, I have automations to step up the set value for hot water temperature, when the price is “cheap”, step it down when “expensive” and step back to normal when the price is intermediate. You can see on the graph below what it looks like. The upper curves are the hot water set and actual temperatures:

It’s hard to measure how much is saved, but success is when hot water production starts after the expensive period is over. The family members testify that a shower during the most expensive hours is not a degradation in comfort. Since the water is only heated back as little as possible, the cost impact is minimized.

The lower part of the graph are the radiator return set and actuals. I try to do something similar with them, but in quite small increments, as not to affect comfort noticeably.

This is complicated enough, but still manageable. With a bit of more logic, you could try to force the heat pump to make a last hot water cycle just before the cheap period ends.

It’s hard to know how much this has saved, but together with metering plugs, automations and presentations in HA, my energy consumption is down by about 20-25% compared with last year and I don’t think this winter was significantly warmer than last year’s. And still, reducing energy consumption wasn’t the objective - reducing costs was.

//

2 Likes

Great to hear it is working so well for you! My heat pump will be installed in a few weeks, and then winter is essentially over so I will only be using the hot water and maybe the “floor cooling” for a while, so it will take some time until I fan test my ideas.
However, I still plan on combining the cost effective (Tibber price) and the efficiency (temperature) to hopefully get the best of both worlds. Just need to learn an entirely new set of skills (math, yaml) or find someone to help me with the formulas…:grin:

Here is a little snippet of what I have currently got. This is just a preview, the action would currently just set the Thermostat up by 2 Degrees. Have a look and tell me what you think.

alias: Heating Optimisation Alpha
description: ""
trigger:
  - platform: state
    entity_id:
      - sensor.electricity_price_xxx
    to: cheap
    attribute: price_level
  - platform: state
    entity_id:
      - sensor.electricity_price_xxx
    attribute: price_level
    to: very_cheap
condition:
  - condition: numeric_state
    entity_id: weather.home_hourly
    attribute: temperature
    above: sensor.average_temperature
action:
  - service: script.temperatur_2
    data: {}
mode: single

What I would like is to create is a “binary sensor” that checks the energy price, temperature forecast and maybe solar forecast

I use the Emhass addon for getting optimal times for heating from Nordpool electricity price, Solar forecast and historical power data EMHASS: An Energy Management for Home Assistant.

You can also adjust the heat pump temperature from temperature forecast Example configurations — emhass 0.7.8 documentation.

2 Likes

Emhass is an amazing Tool and is being actively developed and improved all the time. However, I have so far been unable to set it up properly so I have no first hand experience. It’s on my to-do list though…:see_no_evil:

Maybe I can help you.

  1. Install Emhass addon if you use hassos: EMHASS add-on: An energy management optimization add-on for Home Assistant OS and supervised

  2. In the emhass addon configuration use the default values.
    If you use Nordpool price data change “optimization_time_step”: 30, to “optimization_time_step”: 60,
    If you have Solar panels change to the correct sensor which output Watt produced:
    “sensor_power_photovoltaics”: “sensor.ecu_current_power”,

You must make a template sensor which output total consumed power in Watt without the deferral loads you want to control. My template is like this:

template:

  - sensor:      

      - name: "Power load no var loads"

        unique_id: fbfeef21-1aa3-4a54-b781-426f46fef597

        unit_of_measurement: W

        device_class:  power

        state: >

          {% set powerload = states('sensor.power_toraldasen_32') | float(default=0) %}

          {% set vvb = states('sensor.bryter_varmvannsbereder_electric_consumption_w') | float(default=0) %}

          {% set varmekabler = states('sensor.power_varmekabler') | float(default=0) %}

          {% set varmepumpe = states('sensor.strombryter_varmepumpe_electric_consumption_w') | float(default=0) %}

          {% set value = ( powerload - vvb - varmekabler - varmepumpe) | round(1,default=0) %}

          {{ value }}

which I use in Emhass config:
“sensor_power_load_no_var_loads”: “sensor.power_load_no_var_loads”,

This should give you a basic emhass config.

If you want to import the price data from Nordpool you must use the HA shell command Shell Command - Home Assistant. It is very easy to have wrong shell command. I use HA File editor to edit my shell command. Visual Studio are trying to fix without fixing the shell command.
Here are my shell commands:

shell_command:

  publish_data: "curl -i -H \"Content-Type:application/json\" -X POST -d '{\"custom_deferrable_forecast_id\": [

    {\"entity_id\": \"sensor.p_deferrable0\",\"unit_of_measurement\": \"W\", \"friendly_name\": \"Varmtvannsbereder\"},

    {\"entity_id\": \"sensor.p_deferrable1\",\"unit_of_measurement\": \"W\", \"friendly_name\": \"VKNystue-Varmepumpe\"},

    {\"entity_id\": \"sensor.p_deferrable2\",\"unit_of_measurement\": \"W\", \"friendly_name\": \"VKGmlstue-Bad2etg\"},

    {\"entity_id\": \"sensor.p_deferrable3\",\"unit_of_measurement\": \"W\", \"friendly_name\": \"VKBad1etg-Kjøkken-Gang\"}

    ]}' http://localhost:5000/action/publish-data"  

   

  trigger_nordpool_forecast: "curl -i -H \"Content-Type: application/json\" -X POST -d '{

    \"load_cost_forecast\":{{((state_attr('sensor.nordpool', 'raw_today') | map(attribute='value') | list  + state_attr('sensor.nordpool', 'raw_tomorrow') | map(attribute='value') | list))[now().hour:][:24] }},

    \"prod_price_forecast\":{{((state_attr('sensor.nordpool_uten_avgifter', 'raw_today') | map(attribute='value') | list  + state_attr('sensor.nordpool_uten_avgifter', 'raw_tomorrow') | map(attribute='value') | list))[now().hour:][:24]}}

    }' http://localhost:5000/action/dayahead-optim"

   

  ml_forecast_fit: "curl -i -H \"Content-Type:application/json\" -X POST -d '{\"num_lags\": 24}' http://localhost:5000/action/forecast-model-fit"

  ml_forecast_tune: "curl -i -H \"Content-Type:application/json\" -X POST -d '{}' http://localhost:5000/action/forecast-model-tune"

The shell command gives you services which you can use in automations:

service: shell_command.trigger_nordpool_forecast
data: {}

Here is my automation for the heat pump:

alias: "Emhass: Endre temperatur på varmepumpe. Sjekker hvert 5 minutt."
description: ""
trigger:
  - platform: time_pattern
    minutes: /5
condition:
  - condition: time
    before: "22:00:00"
    after: "05:00:00"
  - condition: state
    entity_id: binary_sensor.effektbegrenser
    state: "off"
action:
  - if:
      - condition: numeric_state
        entity_id: sensor.p_deferrable1
        above: 0.1
    then:
      - service: climate.set_temperature
        data:
          temperature: 23
          hvac_mode: heat
        target:
          entity_id:
            - climate.varmepumpe
    else:
      - service: climate.set_temperature
        data:
          temperature: 22
          hvac_mode: heat
        target:
          entity_id:
            - climate.varmepumpe
mode: single

David have done a great work with the emhass documentation. I recommend you read it before starting trying to use emhass. EMHASS: Energy Management for Home Assistant — emhass 0.4.8 documentation
If you need assistant I can help you more.

Here is my full emhass config: option.json · GitHub

2 Likes

Thanks. I will definitely look into all the config options when I have time. It was mostly things like not being able to just plug an entity like nordpool in there that put me off. But also time constraints…too much going on to delve deeply into setting this up. But I will get there eventually once I have more free time.

1 Like

OK, so I did a little more fiddling before work and this is what I am planning to test next…
I already had the electricity price sensor in my configuration.yaml and simply repurposed it to work as a temp sensor. What it does is classify deviations from the average temp in various levels. Take a look and let me know what you think.
I am still unsure about the “Cheap” and “Warm” parameters…the default was 90% of average and I changed it to 80% which might be too steep.
Next stept is to line them all up against each other and then create actions to go along with them. Since the heat pump isn’t here yet this will have to wait. I am not sure yet if I can use the myVaillant integration or will have to rely on the SG Ready interface. In any case, I will create “scenes” for my room Thermostats and define different levels for heating and cooling within those that I can call in automations.

- name: "Strompreise"
        unique_id: "strompreise"
        state: >-
          {% if states('sensor.current_electricity_market_price')|float(0.5) >= states('sensor.average_electricity_price_today')|float(0.5) *0.8
              and states('sensor.current_electricity_market_price')|float(0.5) < states('sensor.average_electricity_price_today')|float(0.5) *1.15 %}
              NORMAL
          {% elif states('sensor.current_electricity_market_price')|float(0) >= states('sensor.average_electricity_price_today')|float(0) *0.6
              and states('sensor.current_electricity_market_price')|float(0) < states('sensor.average_electricity_price_today')|float(0) *0.8 %}
              CHEAP
          {% elif states('sensor.current_electricity_market_price')|float(0) < states('sensor.average_electricity_price_today')|float(0) *0.6 %}
              VERY_CHEAP
          {% elif states('sensor.current_electricity_market_price')|float(0) >= states('sensor.average_electricity_price_today')|float(0) *1.15
              and states('sensor.current_electricity_market_price')|float(0) < states('sensor.average_electricity_price_today')|float(0) *1.4 %}
              EXPENSIVE
          {% elif states('sensor.current_electricity_market_price')|float(0) >= states('sensor.average_electricity_price_today')|float(0) *1.4
              and states('sensor.current_electricity_market_price')|float(0) < states('sensor.average_electricity_price_today')|float(0) *2.0 %}
              VERY_EXPENSIVE
          {% elif states('sensor.current_electricity_market_price')|float(0) >= states('sensor.average_electricity_price_today')|float(0) *2.0 %}
              EXTREMELY_EXPENSIVE
          {% endif %}
      
      - name: "Temperature Level"
        unique_id: "Temperature_Level"
        state: >-
          {% if state_attr('weather.home_hourly', 'temperature')|float(0.5) >= states('sensor.average_temperature')|float(0.5) *0.8
              and state_attr('weather.home_hourly', 'temperature')|float(0.5) < states('sensor.average_temperature')|float(0.5) *1.15 %}
              Normal
          {% elif state_attr('weather.home_hourly', 'temperature')|float(0) >= states('sensor.average_temperature')|float(0) *0.6
              and state_attr('weather.home_hourly', 'temperature')|float(0) < states('sensor.average_temperature')|float(0) *0.8 %}
              Cold
          {% elif state_attr('weather.home_hourly', 'temperature')|float(0) < states('sensor.average_temperature')|float(0) *0.6 %}
              Very_Cold
          {% elif state_attr('weather.home_hourly', 'temperature')|float(0) >= states('sensor.average_temperature')|float(0) *1.15
              and state_attr('weather.home_hourly', 'temperature')|float(0) < states('sensor.average_temperature')|float(0) *1.4 %}
              Mild
          {% elif state_attr('weather.home_hourly', 'temperature')|float(0) >= states('sensor.average_temperature')|float(0) *1.4
              and state_attr('weather.home_hourly', 'temperature')|float(0) < states('sensor.average_temperature')|float(0) *2.0 %}
              Warm
          {% elif state_attr('weather.home_hourly', 'temperature')|float(0) >= states('sensor.average_temperature')|float(0) *2.0 %}
              Very_Warm
          {% endif %}
     ```