Gå til innhold
  • Bli medlem
Støtt hjemmeautomasjon.no!

Mitt forsøk på "Prediktiv reduksjon av strømbruk"


Anbefalte innlegg

RVM skrev (12 timer siden):

Hvordan gikk du fram for å stille inn gains til PID-regulatoren din?


Jeg brukte omtrent 2 måneder i fjor på å stille inn parametre etter forsøk og feiling. Derivatleddet ble høyt fordi jeg ønsket en rask respons. Spesielt på slutten av en time. Men det som kanskje ikke kommer fram her er at jeg glatter ut det estimerte timesforbruket. Det baserer seg på de siste 5 minutters forbruk og da får jeg ikke slike store endringer som du ser. Varmekabel-termostatene mine slår av og på varme i 5 minutters intervaller så jeg ble nødt til å gjøre noe med den biten.

 

  - platform: derivative
    source: sensor.sensor_klepp_energi_effekt_integral
    name: real_time_consumption_gabriel_edlands_veg_16_integral_derivative
    round: 3
    unit_time: h
    time_window: "00:05:00"

 

OlavT skrev (6 timer siden):

Styrer dere for å holde timesforbruket under x kWh for en gitt time eller for å holde effekten under x Watt til enhver tid?

Siden det er antall kwh/h som er satt i grenseverdiene hos netteiere, så er det det jeg regulerer etter. Jeg kan fint bruke opp mot 10kW mot slutten av en time hvis jeg holder meg under 5kWh den timen.

Lenke til kommentar
Del på andre sider

11 minutes ago, stigvi said:

Siden det er antall kwh/h som er satt i grenseverdiene hos netteiere, så er det det jeg regulerer etter. Jeg kan fint bruke opp mot 10kW mot slutten av en time hvis jeg holder meg under 5kWh den timen.

 

Ja, det gir mening. Hovedutfordringen med denne styringen er at det er mulig å få en uventet høy last på slutten av timen (som en ikke har styring på) og som da kan medføre risiko for å ødelegge "regnskapet". Hvordan håndterer dere dette?

 

Dette er forøvrig slik jeg har implementert dette (i mitt eget system):

 

    {
      "if": {
        "ElectricityConsumptionCouldExceedHourlyLimit": {
          "hourlyConsumptionLimit": 4.9,  // in Kwh
          "totalPowerConsumptionProperty": "ElectricityMeter.PowerConsumption",
          "totalHourlyConsumedElectricityProperty": "ElectricityMeter.HourlyConsumedElectricity",
          "thisDevicePowerConsumptionProperty": "WaterHeater.PowerConsumption",
          "thisDeviceMaxPowerConsumption": 2500 // in Watts
        },
        "then": {
          "executeCommand": {
            "deviceGroupId": "ZWave",
            "deviceId": "6",
            "capabilityId": "SwitchBinary.000",
            "commandId": "SwitchOff"
          }
        }
      }
    }

Endret av OlavT
Lenke til kommentar
Del på andre sider

OlavT skrev (9 timer siden):

Ja, det gir mening. Hovedutfordringen med denne styringen er at det er mulig å få en uventet høy last på slutten av timen (som en ikke har styring på) og som da kan medføre risiko for å ødelegge "regnskapet". Hvordan håndterer dere dette?

Det håndteres ved at jeg ikke har noen last hjemme som er større enn 5kW og som jeg ikke kan kontrollere. Men summen av flere kan bli større enn 5kW. Jeg slår av alt annet som kan styres. Det er all varme, VVB og lading av biler. Men skulle oppvaskmaskin, vaskemaskin, stekeovn og koketopp bli satt på samtidig så får jeg heller ta kostnaden med det den måneden.

Lenke til kommentar
Del på andre sider

Da er PID via appdaemon på plass. Forsøker med input fra ditt pid-script @stigvi og jobber ut fra feilmeldingene der. Første feil;

pid = PID(40.0, 0.4, 2500.0, setpoint=float(input_select.nettleie_pristrinn) - 0.2)
NameError: name 'input_select' is not defined

 

Har opprettet nettleie_pristrinn i input_select.yaml

nettleie_pristrinn:
  name: Nettleie pristrinn
  options:
  - 5
  - 10
  - 15

 

Har du definert input_select.nettleie_pristrinn en annen plass kanskje? Eller klarer den ikke finne input_select.yaml filen?

 

Edit: erstattet pristrinn med 5, og da feiler scriptet videre på sensor.energy. Når jeg endrer denne til sensor.forbruk_denne_timen så finner den ikke sensoren. Tror det har noe med at jeg må importere inn sensorer slik at disse blir tilgjengelige i python koden.

Endret av hjemmedude
Lenke til kommentar
Del på andre sider

hjemmedude skrev (1 time siden):

Da er PID via appdaemon på plass. Forsøker med input fra ditt pid-script @stigvi og jobber ut fra feilmeldingene der. Første feil;

pid = PID(40.0, 0.4, 2500.0, setpoint=float(input_select.nettleie_pristrinn) - 0.2)
NameError: name 'input_select' is not defined

 

Har opprettet nettleie_pristrinn i input_select.yaml

nettleie_pristrinn:
  name: Nettleie pristrinn
  options:
  - 5
  - 10
  - 15

 

Har du definert input_select.nettleie_pristrinn en annen plass kanskje? Eller klarer den ikke finne input_select.yaml filen?

 

Edit: erstattet pristrinn med 5, og da feiler scriptet videre på sensor.energy. Når jeg endrer denne til sensor.forbruk_denne_timen så finner den ikke sensoren. Tror det har noe med at jeg må importere inn sensorer slik at disse blir tilgjengelige i python koden.



Appdeamon har en litt annen måte å referere til sensorer på enn det pyscript har. Kikk litt i dokumentasjonen til appdaemon. Store endringer er det ikke.

Lenke til kommentar
Del på andre sider

Ok, skal kikke på det. Jeg er på tynn is, denne fremgangsmåten med konstruktør og klasse er litt annerledes enn pyscriptet. Men begge deler vil funke?

https://community.home-assistant.io/t/pid-controller-in-appdeamon/251712/3

 

Fant også litt fra deg i søkinga, og ser her hvordan du har definert funksjoner for sjekking av passat_status i appdaemon og python, sammenlignet med pyscripting der du kan bruke state_trigger - som virker en del mer elegant

https://community.home-assistant.io/t/pyscript-new-integration-for-easy-and-powerful-python-scripting/215967/130

Lenke til kommentar
Del på andre sider

Gjør jeg noe riktig her?

Må jeg lage en funksjon for å erstatte state_trigger?

import appdaemon.plugins.hass.hassapi as hass
from simple_pid import PID

class PID(hass.Hass):
    def initialize(self):
        self.run_every(self.PIDrun, "now", 10)
        
    def PIDrun(self, kwargs):
        
        #pid = PID(40.0, 0.4, 2500.0, setpoint=float(input_select.nettleie_pristrinn) - 0.2)
        pid = PID(40.0, 0.4, 2500.0, setpoint=self.get_state("input_select.nettleie_pristrinn") - 0.2)
        
        pid.set_auto_mode(False)
        pid.sample_time = 1.9
        pid.output_limits = (0, 100)
        pid.proportional_on_measurement = False
        pid.set_auto_mode(True, last_output=100.0)
        last_c = 100.0
        turned_off_all = False
        
        #turned_off_car = False
        
        
        
#@state_trigger("sensor.energy")
        forbruk_state = self.entities.sensor.forbruk_denne_timen.state

 

Lenke til kommentar
Del på andre sider

hjemmedude skrev (8 timer siden):

Gjør jeg noe riktig her?

Må jeg lage en funksjon for å erstatte state_trigger?

import appdaemon.plugins.hass.hassapi as hass
from simple_pid import PID

class PID(hass.Hass):
    def initialize(self):
        self.run_every(self.PIDrun, "now", 10)
        
    def PIDrun(self, kwargs):
        
        #pid = PID(40.0, 0.4, 2500.0, setpoint=float(input_select.nettleie_pristrinn) - 0.2)
        pid = PID(40.0, 0.4, 2500.0, setpoint=self.get_state("input_select.nettleie_pristrinn") - 0.2)
        
        pid.set_auto_mode(False)
        pid.sample_time = 1.9
        pid.output_limits = (0, 100)
        pid.proportional_on_measurement = False
        pid.set_auto_mode(True, last_output=100.0)
        last_c = 100.0
        turned_off_all = False
        
        #turned_off_car = False
        
        
        
#@state_trigger("sensor.energy")
        forbruk_state = self.entities.sensor.forbruk_denne_timen.state

 

Alt som nå er under pidrun må du flytte til initialize.

Under pidrun som du kjører hvert 10 sekund må du ha noe som dette:

c = (0.9 * last_c) + (0.1 * pid(float(self.get_state("sensor.estimated_hourly_consumption"))))

if round(last_c, 0) != round(c, 0):

        self.set_state("sensor.et_eller_annet") = round(c, 0)

 

last_c = c

Endret av stigvi
  • Like 1
Lenke til kommentar
Del på andre sider

stigvi skrev (3 minutter siden):

(...)

c = (0.9 * last_c) + (0.1 * pid(float(self.get_state("sensor.estimated_hourly_consumption"))))

Jeg forsto ikke helt hvorfor du dro inn enda et IIR lavpassfilter her, så jeg fjernet det hos meg og justerte ned gains for å kompensere. Tenker det holder å filtrere effekt og ekstrapolert timesforbruk for mitt bruk.

Lenke til kommentar
Del på andre sider

OK, da er jeg så langt. Tror langt fra alt er riktig her..

1. global variabel løser en del feilmeldinger, men vet ikke om jeg bruker de riktig. Jeg tviler :)

2. state_trigger: denne er pyscript spesifikk, hva er ekvivalenten i vanlig python? Evt mistforstår jeg. 

3. jeg fant kjetilsn sin implementasjon av sensor.regulatory_usage_step så kopierte denne templaten, men jeg får unavailable når jeg sjekker den (med self.log(self.get_state("sensor.regulatory_usage_step")) etter pid kjører.

4. state_trigger igjen, siste to funksjonene i koden har jeg ikke gjort noe mer med.

import appdaemon.plugins.hass.hassapi as hass
from simple_pid import PID


class PIDcalc(hass.Hass):
    
    def initialize(self):
        global pid
        global last_c
        global turned_off_all
        global turned_off_car
        
        pristrinn = self.get_state("input_select.nettleie_pristrinn")
        pid = PID(40.0, 0.4, 2500.0, setpoint=float(self.get_state("input_select.nettleie_pristrinn")) - 0.2)
        pid.set_auto_mode(False)
        pid.sample_time = 1.9
        pid.output_limits = (0, 100)
        pid.proportional_on_measurement = False
        pid.set_auto_mode(True, last_output=100.0)
        last_c = 100.0
        turned_off_all = False
        turned_off_car = False
        
        self.run_every(self.PIDrun, "now", 10)
        
#@state_trigger("sensor.energy")

    def PIDrun(self, kwargs):    
        global last_c
        global turned_off_car
        global turned_off_all
        global pid
        
        self.log(pid)
        
        c = (0.9 * last_c) + (0.1 * pid(float(self.get_state("sensor.estimert_timeforbruk_filtrert"))))
        if round(last_c, 0) != round(c, 0):
          self.set_state("sensor.energy_regulator_usage_step") == round(c, 0)
        last_c = c 
        
        self.log(c)
        self.log(self.get_state("sensor.energy_regulator_usage_step"))
        
        
#p, i, d = pid.components
#state.set("sensor.regulator_p", round(p,1))
#state.set("sensor.regulator_i", round(i,1))
#state.set("sensor.regulator_d", round(d,1))
    
        if round(last_c, 0) != round(c, 0):
          sensor.regulator_energy_usage = round(c, 0)
        
        v = max(5 * round(c, 0) - 400, 0.0)
        #number.effekt_varmtvannsbereder.set_value(round(v,1))

        last_c = c

        if c < 10 and turned_off_car == False:
            #easee.set_charger_circuit_dynamic_limit(charger_id = "EH430587", currentP1 = "0")
            turned_off_car = True
            

        if c > 30 and turned_off_car == True:
            #easee.set_charger_circuit_dynamic_limit(charger_id = "EH430587", currentP1 = "16")
            turned_off_car = False

        if c < 2 and turned_off_all == False:
            #esphome.terrassevarmer_pause()
            #switch.heru_electric_heater_connected.turn_off()
            persistent_notification.create(title = "Strøm", message = "Effektbegrensing slo av alt.")

            turned_off_all = True
    
        if c > 5 and turned_off_all == True:
            #esphome.terrassevarmer_resume()
            #switch.heru_electric_heater_connected.turn_on()
            turned_off_all = False
    


#@state_trigger("input_select.nettleie_pristrinn")

    def setpoint(value=None):
        global pid
        pid.setpoint = float(value) - 0.2

#@state_trigger("input_number.consumption_lasthour")
    def hourly_usage(value=None):
        
        if float(value) >= float(self.get_state("input_select.nettleie_pristrinn")):
            script.turn_on(entity_id = "script.send_melding", variables = {'message': 'Strømforbruk var større enn grense', 'title': 'Strøm', 'channel': 'Info'})
        
2022-06-12 11:17:35.017546 INFO simple_pid: PID(Kp=40.0, Ki=0.4, Kd=2500.0, setpoint=4.8, sample_time=1.9, output_limits=(0, 100), auto_mode=True, proportional_on_measurement=False,error_map=None)
2022-06-12 11:17:35.024166 INFO simple_pid: 100.0
2022-06-12 11:17:35.044615 INFO simple_pid: unavailable
2022-06-12 11:17:45.016038 INFO simple_pid: PID(Kp=40.0, Ki=0.4, Kd=2500.0, setpoint=4.8, sample_time=1.9, output_limits=(0, 100), auto_mode=True, proportional_on_measurement=False,error_map=None)
2022-06-12 11:17:45.021810 INFO simple_pid: 100.0
2022-06-12 11:17:45.028622 INFO simple_pid: unavailable
2022-06-12 11:17:55.014203 INFO simple_pid: PID(Kp=40.0, Ki=0.4, Kd=2500.0, setpoint=4.8, sample_time=1.9, output_limits=(0, 100), auto_mode=True, proportional_on_measurement=False,error_map=None)
2022-06-12 11:17:55.020307 INFO simple_pid: 100.0
2022-06-12 11:17:55.027098 INFO simple_pid: unavailable

 

 

EDIT: fant plutselig en feilmelding i loggen;

det tyder på at mye eller noe fungerer da forbruket kl 18-19 var 5,17 kwh 🙂

Det er kult!

 

File "/config/appdaemon/apps/simple-pid.py", line 70, in PIDrun
    persistent_notification.create(title = "Strøm", message = "Effektbegrensing slo av alt.")
NameError: name 'persistent_notification' is not defined

 

Endret av hjemmedude
Lenke til kommentar
Del på andre sider

Ser ut som jeg må trikse mer med gains, men må nok leve med at regulatoren ikke nødvendigvis går mot en steady state så lenge jeg ikke kan gi trinnløst pådrag (bare av/på laster). Tenker å fortsette med en soft PI kontroller for å unngå veldig mye switching, og heller ha litt headroom mot effekttrinnsgrensa.regulator.png.2c672ecf51004e85306d42076d9547c8.png

 

timeforbruk.png.b12c9b3104fad71dff07e58fe57236d9.png

 

Lenke til kommentar
Del på andre sider

Er ikke algoritmen her egentlig ganske enkel? Regn ut hvor mye effekt en kan holde resten av timen uten å gå over grenseverdien for timen. Slå på laster til grensen er nådd. Sjekk på nytt etter en stund.

Lenke til kommentar
Del på andre sider

Update: fikk nok av appdaemon og installerte pyscript og la inn koden til @stigvi med mine variabler. Nå "funker" det, i alle fall ser det sånn ut i GUI :)

Neste på planen er å følge @kjetilsn schedy-eksempel som vist under her 🙂

Jeg har ca 10 termostater å styre, så kanskje 10 steps er tingen?

Hvor la du inn 5 min tidsintervall for å slå på igjen termostatene dine @stigvi? Er sikkert et sted på forumet her men.

Takk for hjelp og god input underveis her!

 

 rooms:
 
    living:
      actors:
        climate.stue:
      schedule:
      - v: 21
        rules:
          - rules:
            - x: "Next() if is_off('binary_sensor.terassedor') else Break()"
            - x: "Add(-4) if state('sensor.energy_regulator_usage_step') < '5' else Next()"
            - x: "Add(-1) if is_on ('binary_sensor.dyreste_4_timer') else Next()"
            - x: "Add(-1) if is_on ('input_boolean.energy_cost_extreme') else Next()"
            - x: "Add(-5) if is_on ('input_boolean.varmt_ute') else Next()"
            - x: "Add(-5) if is_off ('input_boolean.oppe_hjemme') else Next()"
            - x: "Add(-10) if is_on ('input_boolean.ferie') else Next()"
Lenke til kommentar
Del på andre sider

hjemmedude skrev (8 timer siden):

Update: fikk nok av appdaemon og installerte pyscript og la inn koden til @stigvi med mine variabler. Nå "funker" det, i alle fall ser det sånn ut i GUI :)

Neste på planen er å følge @kjetilsn schedy-eksempel som vist under her 🙂

Jeg har ca 10 termostater å styre, så kanskje 10 steps er tingen?

Hvor la du inn 5 min tidsintervall for å slå på igjen termostatene dine @stigvi? Er sikkert et sted på forumet her men.

Takk for hjelp og god input underveis her!

 

 rooms:
 
    living:
      actors:
        climate.stue:
      schedule:
      - v: 21
        rules:
          - rules:
            - x: "Next() if is_off('binary_sensor.terassedor') else Break()"
            - x: "Add(-4) if state('sensor.energy_regulator_usage_step') < '5' else Next()"
            - x: "Add(-1) if is_on ('binary_sensor.dyreste_4_timer') else Next()"
            - x: "Add(-1) if is_on ('input_boolean.energy_cost_extreme') else Next()"
            - x: "Add(-5) if is_on ('input_boolean.varmt_ute') else Next()"
            - x: "Add(-5) if is_off ('input_boolean.oppe_hjemme') else Next()"
            - x: "Add(-10) if is_on ('input_boolean.ferie') else Next()"

Jeg bruker ikke schedy. 5 minutters "pause" på ovnene la jeg inn i pyscript kode som jeg har for å styre varmen i huset.

OlavT skrev (9 timer siden):

Er ikke algoritmen her egentlig ganske enkel? Regn ut hvor mye effekt en kan holde resten av timen uten å gå over grenseverdien for timen. Slå på laster til grensen er nådd. Sjekk på nytt etter en stund.

Poenget med pid regulator er nettopp at det er enkelt. Det finnes knapt noe så enkelt som det. Men det kan være litt jobb å justere den inn.

RVM skrev (10 timer siden):

Ser ut som jeg må trikse mer med gains, men må nok leve med at regulatoren ikke nødvendigvis går mot en steady state så lenge jeg ikke kan gi trinnløst pådrag (bare av/på laster). Tenker å fortsette med en soft PI kontroller for å unngå veldig mye switching, og heller ha litt headroom mot effekttrinnsgrensa.

Du har i alle fall veldig mye mer svingninger enn det jeg har. Hvis du tok vekk D leddet så er det naturlig med ustabilitet hvis du samtidig ikke reduserer P og I leddet. D leddet er stabiliserende, spesielt når det er så høyt som 2500 som det jeg brukte.

Lenke til kommentar
Del på andre sider

On 12/06/2022 at 11:18, hjemmedude said:
switch.heru_electric_heater_connected.turn_off()

@stigvi, er dette en funksjon du har laget for å slå av varmtvannsbereder? I såfall kan du ta vise meg den?

Jeg bruker switch.bryter_varmvannsbereder.turn_off uten parentes. Har ikke lest Pyscript dokumentasjonen fra perm til perm så det kan være noe jeg har oversett.

Lenke til kommentar
Del på andre sider

haraldov skrev (17 minutter siden):

@stigvi, er dette en funksjon du har laget for å slå av varmtvannsbereder? I såfall kan du ta vise meg den?

Jeg bruker switch.bryter_varmvannsbereder.turn_off uten parentes. Har ikke lest Pyscript dokumentasjonen fra perm til perm så det kan være noe jeg har oversett.

Heru er mitt ventilasjonsanlegg og dette er en helt vanlig "switch" i HA. I pyscript er .turn_off() og .turn_on() standard måte å sette en bryter.

Lenke til kommentar
Del på andre sider

Python - Invoking Functions with and without Parentheses - GeeksforGeeks

Nei, jeg har ikke noen pause på VVB. Den er styrt av en SSR. Termostatene har et mekanisk rele og de regulerer varmen ved å slå av og på i et forhold ut i fra effektbehov og de gjør det i 5 minutters intervaller. Så det er årsaken til at jeg ikke skifter modus på de mellom away, eco og normal oftere enn hvert 5. minutt. Jeg vil ikke slite ut releet.

  • Like 1
Lenke til kommentar
Del på andre sider

  • 3 uker senere...

Her kommer en annen tanke om hvordan effektbegresningen kan styres. 

 

Jeg har gjort det "relativt" enkelt ved bruk av eksisterende automasjonfilosofi i home assistant.

En kwh_est_hour som beregner effektforbruket for den inneværende timen, samtidig med en on/off sensor som setter i gang effektbegrenser. 

Ved frigjøring av effekttrinn sjekkes det opp mot det forrige trinnet om hva maks effekt er der. 

 

På elbil laderen kalkuleres hvor mange A den må stilles ned for å komme seg under effektgrensen. 

 

Samtidig en input_number som settes til maks kwh pr time. 

 

Så kan en bare lage automasjoner som trigges ved endring av input_text.effektbegrenser_pri

 

#sensor.yaml
- trigger:
  - platform: time_pattern
    #hours: 0
    minutes: "/1"
    seconds: 15
  sensor:
    - name: kwh_est_hour
      unit_of_measurement: "kwh"
      state: "{{ (((states('sensor.power_avg_20s')|int(default=0) / 1000|int)/60*(60-now().minute))|round(2) + states('sensor.hour_total_kwh')|float(default=0))|round(3)}}"

- binary_sensor:
    - name: "Effektbegrenser"
      delay_on:
        minutes: 4
      delay_off:
        minutes: 4
      state: >
          {% if states('sensor.kwh_est_hour')|float(default=0) > states('input_number.effekttariff_max_kwh')|float(default=0) and now().minute|int(default=0) >= 15 %}
            on
          {% else %}
            off
          {% endif %}

#automation.yaml
- id: "231120212212"
  alias: "Tariff effektbegrenser begrens effekt"
  trigger: 
    - platform: state
      entity_id: binary_sensor.effektbegrenser
      to: 'on'
  action: 
    repeat:
      while: 
      - condition: state
        entity_id: binary_sensor.effektbegrenser
        state: 'on'
      - condition: template
        value_template: "{{ states('input_text.effektbegrenser_pri')|int <= 7}}"
      sequence: 
        - service: input_text.set_value
          entity_id: input_text.effektbegrenser_pri
          data_template:
            value: "{{ states('input_text.effektbegrenser_pri')|int + 1|int }}"
        - delay: "00:05:00"

- id: "241120212101"
  alias: "Tariff effektbegrenser frigi"
  mode: queued
  trigger: 
    - platform: state
      entity_id: binary_sensor.effektbegrenser
      to: 'off'
    - platform: template
      value_template: "{{ now().minute is in [0,10,20,30,40,50] and states('input_text.effektbegrenser_pri')|int > 0}}"
  action: 
    repeat:
      while: 
      - condition: template
        value_template: >
          {% set begrenser = states('input_text.effektbegrenser_pri') %}
          {% if begrenser|int == 0 %}
            {% set effektbegrenser = 700 %} #Trinn 1 maks effekt 700
          {% elif begrenser|int == 1 %}
            {% set effektbegrenser = 1000 %} #Trinn 2 maks effekt 1000
          {% elif begrenser|int == 2 %}
            {% set effektbegrenser = states('sensor.easee_new_kw')|float*1000 %} #Les aktiv effekt uttak elbil lader
          {% elif begrenser|int == 3 %}
            {% set effektbegrenser = 2000 %} #Trinn 4 maks effekt 2000
          {% elif begrenser|int == 4 %}
            {% set effektbegrenser = 1300 %} #Trinn 5 maks effekt 1300
          {% elif begrenser|int > 4 %}
            {% set effektbegrenser = 0 %} #Trinn 6 push varsel mobil
          {%endif%}
          {% if (states('input_number.effekttariff_max_kwh')|float - states('sensor.kwh_est_hour')|float) - (((effektbegrenser|int / 1000|int)/60*(60-now().minute))|round(2)) > 0 %}
            true
          {%else%}
            false
          {%endif%}
      sequence: 
        - service: input_text.set_value
          entity_id: input_text.effektbegrenser_pri
          data_template:
            value: >
              {% if states('input_text.effektbegrenser_pri')|int > 0  %}
                {{ states('input_text.effektbegrenser_pri')|int - 1|int }}
              {%else%}
                0
              {%endif%}
        - delay: "00:05:00"

 

 

 

  • Like 4
Lenke til kommentar
Del på andre sider

Kim123 skrev (8 timer siden):

Jeg har gjort det "relativt" enkelt ved bruk av eksisterende automasjonfilosofi i home assistant.

Men allikevel helt sikkert effektivt og veldig nærme det jeg har lagd med en pid-regulator. Du har jo egentlig implementert en PI (eller P) regulator med din automasjon.

PS. Linjene ble litt lange og det er ikke alt jeg ser fordi det forsvinner ut høyre kant.

Lenke til kommentar
Del på andre sider

I det siste har jeg har lekt med tanken på å gjøre reguleringen mer prediktiv ved å innføre et slags feed forward-ledd ved å regne ut tidspunktet for framtidige forutsigbare laster, i mitt tilfelle gulvvarme.

 

Det ser jo tilsynelatende ut som temperaturen faller fint ihht. Newton's law of cooling (altså med en eksponensiell decay, se bilde under), så jeg tenkte jeg kunne bruke curve_fit fra Scipy-biblioteket inni Pyscript til å modellere temperatur som T = T0 + c*e-kt, men resultatet jeg får fra curve_fit er altfor sensitivt for hvilke datapunkter jeg tar utgangspunkt i. For de første 4-6 datapunktene får jeg konsekvent en T0 som er mye høyere enn omgivelsestemperaturen, så det kan ikke være en særlig god fysisk løsning, og gir ikke riktig tidspunkt for når temperaturen faller ned til setpunkt. Skal prøve å finne en temperaturfunksjon som gir et bedre estimat en eller annen gang. Målet er selvfølgelig at det beregnes kontinuerlig i Home Assistant, ikke at jeg modellerer temperaturfallet med hardkodede parametre utenfra.

 

image.thumb.png.6142129113c0bd28722939c14776287d.png

Lenke til kommentar
Del på andre sider

RVM skrev (2 timer siden):

Det ser jo tilsynelatende ut som temperaturen faller fint ihht. Newton's law of cooling (altså med en eksponensiell decay, se bilde under)

Interessant, men mine termostater er pi regulatorer som ikke har slike innkoblingspunkt som du har på dine. Mine slår seg av og på i et forhold avhengig av effektbehov og med en fast periodetid på 5 minutter.
Edit: som er glimrende mht det å holde seg under en effektgrense


Hos meg har jeg rutiner som gjør at vi får et høyt forbruk rett før vi reiser på jobb. Da står bil på lading og jeg har gjerne på en stråleovn for å varme opp den lille delen av huset vi spiser frokost. Dette skjer hver arbeidsdag mellom 06:00 og 06:20. Fra 06:20 er huset tomt og strømforbruk på et minimum. Derfor blir det helt meningsløst å regulere ned effekten mellom 06:00 og 06:20.

Endret av stigvi
Lenke til kommentar
Del på andre sider

On 29/06/2022 at 22:24, Kim123 said:

På elbil laderen kalkuleres hvor mange A den må stilles ned for å komme seg under effektgrensen. 

 

 

Jeg ser i scriptet ditt at du leser ut aktivt effekt uttak på elbil, men hvordan kalkuleres hvor mange A den må stilles ned for å komme seg under effektgrensen?

{% elif begrenser|int == 2 %}
            {% set effektbegrenser = states('sensor.easee_new_kw')|float*1000 %} #Les aktiv effekt uttak elbil lader

 

Lenke til kommentar
Del på andre sider

Jeg trigger scriptet under. Av en eller annen grunn stopper ladingen når man setter den til under 9A. Aner ikke hvorfor, tipper bug eller noe på easee sin side. 

 

 
tariff_elbil:
  mode: restart
  alias: "Tariff. Juster ladefart kontinuerlig. "
  sequence:
    - alias: "Repeat loop"
      repeat:
        sequence:
          - service: input_number.set_value
            entity_id: input_number.easee_set_current
            data_template: 
              value: >
                {% set P = ((states('input_number.effekttariff_max_kwh')|float - states('sensor.kwh_est_hour')|float)*1000)/1.73 / 240 %}
                {% if P >= 32 %}
                  32
                {%elif P <= 9 %}
                  9
                {% else %}
                  {{ P|int }}
                {%endif%}
          - delay: 
              seconds: 60
        until:
          - condition: or
            conditions: 
              - condition: template
                value_template: "{{ states('input_text.effektbegrenser_pri') != '3' }}"

 

  • Like 1
Lenke til kommentar
Del på andre sider

Bli med i samtalen

Du kan publisere innhold nå og registrere deg senere. Hvis du har en konto, logg inn nå for å poste med kontoen din.

Gjest
Skriv svar til emnet...

×   Du har limt inn tekst med formatering.   Lim inn uten formatering i stedet

  Du kan kun bruke opp til 75 smilefjes.

×   Lenken din har blitt bygget inn på siden automatisk.   Vis som en ordinær lenke i stedet

×   Tidligere tekst har blitt gjenopprettet.   Tøm tekstverktøy

×   Du kan ikke lime inn bilder direkte. Last opp eller legg inn bilder fra URL.

×
×
  • Opprett ny...

Viktig informasjon

Vi har plassert informasjonskapsler/cookies på din enhet for å gjøre denne siden bedre. Du kan justere dine innstillinger for informasjonskapsler, ellers vil vi anta at dette er ok for deg.