Licznik energii

Cześć,
Od kilku dni próbuję zbudować licznik na wemosie. Licznik ma zbierać impulsy z licznika 3 fazowego który ma wyjście impulsowe S0. Pomaga mi w tym chat gpt ale coś nie idzie. Licznik 3 fazowy w rozdzielni liczy zużycie na pompie ciepła ale chciałem to przenieść do HA. Pompa ciepła steruje dwoma obiegami CO i CWU. Podpiąłem się wemosem pod styki S0 na liczniku, podpiąłem się do pompy ciepła w wyjście zasilania na pompę CO i stąd podaję sygnał na przekaźnik a następnie na wemosa. Logika miała być taka:
-Wemos dostaje impulsy z licznika i działa pompa CO to licz zużycie dla CO

  • Wemos dostaje impulsy z licznika ale nie jest załączona pompa CO to licz do zużycia CWU.
    Jeżeli chodzi o przekaźnik i jego podłączenie do wemosa to jest ok bo widzę poprawnie stan pompa włączona/wyłączona natomiast nie dostaję danych z impulsów. Nie dostaję też danych z impulsów jeżeli pompa działa ale przekaźnik jest wyłączony, a wtedy powinienem dostawać dane do CWU. Nie wiem coś jest źle podłączone do licznika chyba ale nie radzę sobie.
    Poniżej zamieszczam kod wgrany do wemosa, schemat podłączenia tak jak potrafiłem narysować, wycinek z instrukcji licznika 3 fazowego. Bardzo proszę o pomoc co tu może być źle, podpowiedź, co sprawdzić.
esphome:
  name: licznik-pc

esp8266:
  board: d1_mini

wifi:
  ssid: "xxxxxxxx"
  password: "xxxxxx"
  min_auth_mode: WPA2

logger:

api:

ota:
  platform: esphome

time:
  - platform: homeassistant
    id: homeassistant_time

# LED wbudowana w Wemos D1 mini (GPIO2 / D4)
output:
  - platform: gpio
    pin: GPIO2
    id: led

# ===== PRZEKAŹNIK CO =====
binary_sensor:
  - platform: gpio
    pin:
      number: GPIO12
      mode: INPUT_PULLUP
      inverted: true
    name: "Pompa CO aktywna"
    id: pompa_co

# ===== LICZNIK ENERGII =====
sensor:
  - platform: pulse_counter
    pin:
      number: GPIO14   # D5 – S0
      mode: INPUT_PULLUP
      inverted: true
    name: "Moc chwilowa"
    id: moc_chwilowa
    unit_of_measurement: "kW"
    accuracy_decimals: 3
    update_interval: 1s
    filters:
      - multiply: 0.06   # 1000 imp/kWh → 0.06 kW
    internal_filter: 100ms
    on_value:
      then:
        - output.turn_on: led
        - delay: 50ms
        - output.turn_off: led

  # ===== MOC CO =====
  - platform: template
    name: "Moc CO"
    id: moc_co
    unit_of_measurement: "kW"
    accuracy_decimals: 3
    update_interval: 1s
    lambda: |-
      if (id(pompa_co).state) {
        return id(moc_chwilowa).state;
      } else {
        return 0.0;
      }

  # ===== MOC CWU =====
  - platform: template
    name: "Moc CWU"
    id: moc_cwu
    unit_of_measurement: "kW"
    accuracy_decimals: 3
    update_interval: 1s
    lambda: |-
      if (!id(pompa_co).state) {
        return id(moc_chwilowa).state;
      } else {
        return 0.0;
      }

  # ===== ENERGIA =====
  - platform: total_daily_energy
    name: "Energia CO"
    power_id: moc_co
    unit_of_measurement: "kWh"

  - platform: total_daily_energy
    name: "Energia CWU"
    power_id: moc_cwu
    unit_of_measurement: "kWh"

# ===== TEKSTOWY STAN POMPY CWU =====
text_sensor:
  - platform: template
    name: "Pompa CWU aktywna"
    update_interval: 1s
    lambda: |-
      if (id(moc_chwilowa).state > 0.0 && !id(pompa_co).state) {
        return std::string("Włączona");
      } else {
        return std::string("Wyłączona");
      }

Schemat jest coś nie tego :slight_smile: Jakichkolwiek zmian możesz oczekiwać tylko na D6.
Pozostałe wejścia są trwale na GND.
Moim zdaniem D5 powinno być podłączone bezpośrednio do SO+

Nawet nie analizuję kodu - na schemacie te impulsy puszczasz do masy oraz niczym ich nie badasz, więc niby jak to ma działać.
na obrazku zamalowałem też przewód idący do +5V, aby nie spalić MCU powinien iść do +3.3V (a jeśli impulsy będą niewykrywalne to się pomyśli)


przekaźnik też jest podłączony w podejrzany sposób (jeśli to gotowy moduł przekaźnika to musi być jakoś zasilany i to NIE bezpośrednio z GPIO), ale może zrób zdjęcia bo tu za dużo niejasności.

D5 odłącz od masy bo to nie ma sensu, jeśli to on ma zliczać impulsy to podłacz do niego ten czerwony przewód, który dorysowałem do D3

Dzięki za zainteresowanie. Jeżeli chodzi o przekaźnik to cewka jest wyzwalana 230V z pompy ciepla, a to zamyka obwód NO. Ten obwód jest zasilany z wemosa i to działa. Widzę wtedy stan pompy CO w HA. A to nie jest tak że impulsy powinny w tym układzie iść i do masy i do D5?

1 polubienie

Ale instrukcja licznika podaje że licznik ma na SO+ dostać 5v. To dlatego 5v z wemosa idzie na SO+ z rezystorem ,a z SO- idzie na D5 i wspólną masę. A może błędem jest właśnie przewód z SO- na masę wemosa. Ja się nie znam ,ale czy masa nie kradnie impulsu?

Zrób tak jak narysował @szopen … tylko czerwony przewód SO+ podłącz do D5
zamiast D3 (albo zmień definicję pinu zliczającego na D3).
Aby zrozumieć - wyobraź sobie, że w liczniku pomiędzy SO- SO+ jest “styk”.

Jest też błąd w konfiguracji

  • update_interval (Optional, Time): The interval to check the sensor. Defaults to 60s.

Instrukcja podaje gwarantowany zakres działania, logika przemysłowa jest często 12V a logika TTL (do niedawna całkiem powszechna) to 5V, najwyraźniej nie przewidywano logiki 3.3V - LVCMOS/LVTTL, ale taką ma MCU Espressif (i większość współczesnych konkurencyjnych MCU) a podawanie na GPIO napięcia większego niż 3.6V grozi po prostu uszkodzeniem całego MCU lub wybranego pinu GPIO (nawet jeśli nie stanie się to od razu, to i tak jest gwarantowane drastyczne skrócenie żywotności układu).
De facto na wyjściu SO licznika jest fototranzystor będący częścią transoptora wyjściowego, więc pod warunkiem montażu układu tuż przy liczniku można nawet spróbować rozwiązanie wykorzystujące wewnętrzny pullup w MCU (takie samo jak używasz do wykrywania stanów styków beznapięciowych przekaźnika - zmyliłeś mnie tym oznaczeniem + i - na schemacie rzy przekaźniku - to jest styk beznapięciowy, a w ten sposób styki polaryzuje właśnie wbudowany w MCU pullup - możesz sobie zmierzyć to napięcie - powinno być w okolicach >3V, gdy styki są rozwarte).

Spójrz na parametry typowego transoptora do takich zastosowań (nie twierdzę, że jest tam konkretnie ten model, ale ten i jego odpowiedniki są najbardziej popularne na świecie, gdy w grę wchodzi zakres VCE właśnie rzędu 5V-50V - jak widać przy 3V3 też działa OK

Czyli tak.

SO+ ----- (rezystor 1K) -----------> 3.3V wemos
SO+ -----------------------------------> D5 wemos

SO- ------------------------------------> GND wemos

W kodzie nic nie zmieniam? Dobrze rozumiem?

Tak, i akurat D3 nie było szczęśliwym wyborem, tylko nie spojrzałem w dokumentację (niżej bryk), że to jest GPIO0

Jeśli przewody będą realnie krótkie (maks. do kilkudziesięciu cm) można zrezygnować z rezystora i wypróbować czy działa na wewnętrznym pullupie (mode: INPUT_PULLUP).

Kodu po AI nigdy nie chce mi się czytać, ani modyfikować, niech AI się tym zajmie (na pierwszy rzut oka nie wygląda źle, ale szkoda mi czasu na analizę czy to w ogóle działa, sprawdzisz organoleptycznie).

Sprawdzę rano, przewody będą max 30cm. Pullup już jest włączony na tym pinie, rezystor też jest na przewodzie.
Nurtuje mnie tylko jak w zasadzie działa to złącze SO tym bardziej że przewody 3.3v i GPIO idą w to samo złącze SO+ na liczniku. Możesz to łopatologicznie wytłumaczyć?

Już pisałem
update_interval: 60s
Dlaczego tak
W jednej godzinie jest 3600s czyli Podłączając odbiornik 1kW w jednej godzinie jest 1000 impulsów czyli dokładnie co 3,6s . czyli 16,666 impulsów przeciągu 1 minuty
Gdy update_interval: 1s to liczba impulsów przeciągu 1 s jest 0

1 polubienie

Jakbyś zajrzał do dokumentacji transoptora, to byś tam zobaczył taki schemat, tu dorysowałem do niego szczegóły z twojego rozwiązania.


skośne strzałeczki symbolizują sprzężenie optyczne
RL to jest rezystor pullupu (jeśli masz programowo włączony wewnętrzny pullup, to jego odpowiednik pojawia się podłączony wewnątrz MCU do tego GPIO i wtedy ten fizyczny rezystor może będzie zbędny (to jest zbyt skomplikowane by opisywać jak się to faktycznie dzieje, bo w MCU wcale nie rezystor jest pulupem, ale jego dostatecznie dobrym przybliżeniem jest rezystor rzędu kilkudziesięciu kiloomów, tu pozostaje eksperyment - w ciemno nie zgadnę czy takie odciągniecie do zasilania jest wystarczające, ALE jeśli używasz fizycznego rezystora nie musisz włączać wbudowanego w MCU pullupu)
kolektor tego fototranzystora to złącze SO+, a emiter to SO-.

Jeśli LED NIE świeci, to fototranzystor NIE przewodzi (jego rezystancja jest kilka rzędów wielkości większa od pullupu, czyli w praktycznym znaczeniu jest niemal nieskończenie większa, więc nie ma wpływu) i na GPIO masz praktycznie napięcie VCC doprowadzone przez rezystor, czyli GPIO ma stan wysoki (w logice dodatniej).

Jeśli LED świeci, to fototranzystor przewodzi i jego rezystancja jest bardzo niska (ze względu na budowę na nim odkłada się niezerowe napięcie, ale jeśli będziesz się uczył w technikum elektronicznym albo na odpowiednich studiach to się dowiesz dlaczego), więc w dużym uroszczeniu zakładamy, że zwiera on to napięcie dostarczane pullupem do masy, realnie nie jest to 0V, ale napięcie jest wystarczająco niskie by GPIO uznało je za stan niski.

1 polubienie

Dziękuję za szczegółowe wyjaśnienie l.

Hej,
Pięknie działa :slight_smile:

[14:57:40.223][D][sensor:135]: 'Moc CO': Sending state 0.00000 kW with 3 decimals of accuracy
[14:57:40.238][D][sensor:135]: 'Energia CO': Sending state 0.00000 kWh with 5 decimals of accuracy
[14:57:42.047][D][sensor:135]: 'Moc CWU': Sending state 2.94000 kW with 3 decimals of accuracy
[14:57:42.060][D][sensor:135]: 'Energia CWU': Sending state 0.81599 kWh with 5 decimals of accuracy
[14:57:43.015][D][text_sensor:097]: 'Pompa CWU aktywna': Sending state 'włączono'
[14:57:44.314][D][pulse_counter:188]: 'Moc chwilowa': Retrieved counter: 49.00 pulses/min
[14:57:44.332][D][sensor:135]: 'Moc chwilowa': Sending state 2.94000 kW with 3 decimals of accuracy
[14:58:40.228][D][sensor:135]: 'Moc CO': Sending state 0.00000 kW with 3 decimals of accuracy
[14:58:40.239][D][sensor:135]: 'Energia CO': Sending state 0.00000 kWh with 5 decimals of accuracy
[14:58:42.033][D][sensor:135]: 'Moc CWU': Sending state 2.94000 kW with 3 decimals of accuracy
[14:58:42.039][D][sensor:135]: 'Energia CWU': Sending state 0.86499 kWh with 5 decimals of accuracy
[14:58:43.024][D][text_sensor:097]: 'Pompa CWU aktywna': Sending state 'włączono'
[14:58:44.323][D][pulse_counter:188]: 'Moc chwilowa': Retrieved counter: 49.00 pulses/min
[14:58:44.332][D][sensor:135]: 'Moc chwilowa': Sending state 2.93985 kW with 3 decimals of accuracy

Kod i schemat dla potomnych jak trzeba będzie to udostępnię.
Dziękuję @szopen , @marek_k , @RobinI30 .

Kod daj od razu (jeśli jesteś pewien, że działa dobrze), a schemat po doprecyzowaniach stał się całkiem jasny, ale jeśli masz wersję ostateczną, to z pewnością pomoże początkującym.

Hej,
Kod sprawdzony. Działa poprawnie, można korzystać.

esphome:
  name: licznik-pc

esp8266:
  board: d1_mini

wifi:
  ssid: "ZZZZ"
  password: "XXXXXXXX"
  min_auth_mode: WPA2

 

logger:

api:

ota:
  platform: esphome

time:
  - platform: homeassistant
    id: homeassistant_time
    on_time:
      - seconds: 0
        minutes: 0
        hours: 0
        then:
          - lambda: |-
              if (id(homeassistant_time).now().day_of_year !=
                  id(homeassistant_time).now().day_of_year - 1) {
                id(pc_start_count) = 0;
              }


# ================= GLOBAL =================
globals:
  - id: pc_start_count
    type: int
    restore_value: yes
    initial_value: '0'
    

# ================= LED =================
output:
  - platform: gpio
    pin: GPIO2   # D4
    id: led

# ================= POMPA CO =================
binary_sensor:
  - platform: gpio
    pin:
      number: GPIO12
      mode: INPUT_PULLUP
      inverted: true
    name: "Pompa CO aktywna"
    id: pompa_co

  # ===== POMPA CIEPŁA PRACUJE (Z MOCY) =====
  - platform: template
    name: "Pompa ciepła pracuje"
    id: pc_pracuje
    lambda: |-
      return id(moc_chwilowa).state > 0.10;
    on_press:
      then:
        - lambda: |-
            id(pc_start_count)++;

# ================= LICZNIK ENERGII =================
sensor:
  - platform: pulse_counter
    pin:
      number: GPIO14   # D5 – S0
      mode: INPUT_PULLUP
      inverted: true
    name: "Moc chwilowa"
    id: moc_chwilowa
    unit_of_measurement: "kW"
    accuracy_decimals: 3
    update_interval: 60s
    internal_filter: 100ms
    filters:
      - multiply: 0.06   # 1000 imp/kWh
    on_value:
      then:
        - output.turn_on: led
        - delay: 40ms
        - output.turn_off: led

  # ===== MOC CO =====
  - platform: template
    name: "Moc CO"
    id: moc_co
    unit_of_measurement: "kW"
    accuracy_decimals: 3
    update_interval: 60s
    lambda: |-
      return id(pompa_co).state ? id(moc_chwilowa).state : 0.0;

  # ===== MOC CWU =====
  - platform: template
    name: "Moc CWU"
    id: moc_cwu
    unit_of_measurement: "kW"
    accuracy_decimals: 3
    update_interval: 60s
    lambda: |-
      return (!id(pompa_co).state) ? id(moc_chwilowa).state : 0.0;

  # ===== ENERGIA =====
  - platform: total_daily_energy
    name: "Energia CO"
    power_id: moc_co
    unit_of_measurement: "kWh"

  - platform: total_daily_energy
    name: "Energia CWU"
    power_id: moc_cwu
    unit_of_measurement: "kWh"

  # ===== LICZNIK STARTÓW =====
  - platform: template
    name: "Załączenia pompy ciepła dzisiaj"
    unit_of_measurement: "x"
    accuracy_decimals: 0
    update_interval: 60s
    lambda: |-
      return id(pc_start_count);

# ================= STAN CWU =================
text_sensor:
  - platform: template
    name: "Pompa CWU aktywna"
    update_interval: 60s
    lambda: |-
      if (id(moc_chwilowa).state > 0.10 && !id(pompa_co).state) {
        return std::string("włączona");
      } else {
        return std::string("wyłączona");
      }

1 polubienie