Ferraris-Zähler auslesen: Aktuelle Leistung, Stromausspeisung und Stromeinspeisung (durch BKW) mittels zweier TRCT5000

Wie man einen Ferrariszähler mittels TRCT5000 und ESP8266 ausliest, findet man im Netz öfter. Auch @Simon42 hat hierzu bereits einen Beitrag geschrieben: https://www.simon42.com/home-assistant-ferraris-zahler-ht-nt-tarif/.
Im Zusammenhang mit einem Balkonkraftwerk (BKW) kann die Drehscheibe auch mal rückwärts drehen. Hierzu habe ich keine Lösung im Netz gefunden. Ich bin noch in der glücklichen Lage, einen Ferrariszähler zu besitzen und erspare mir damit Überlegungen zum Anschluss eines Speichers. Nun möchte ich aber auch gerne wissen, wieviel Strom ich ins Netz “speichere”.
Hier also meine Lösung.

Um Rechts- und Linkslauf bestimmen zu können, benötigt man zwei Lichtschranken (LS1 und LS2).

Hier die schematische Darstellung mit zeitlichem Ablauf:

Hier der Schaltplan und Stückliste:

Nach dem Löten und Verkabeln sieht das Ganze so aus:

Den D1 mini habe ich im Gehäuse ausserhalb des Verteilerschranks angebracht, da sonst der WLAN-Empfang zu schwach wird.

Die LEDs der beiden TRCT5000 musste ich ein wenig zueinander biegen, damit die rote Markierung der Zählscheibe zeitgleich von beiden Lichtschranken erkannt wird.

Zur Befestigung der beiden TRCT5000 an den Stromzähler habe ich ein Stück HDF-Platte 3 mm Dicke genutzt, in dem ich einen Schlitz für die Leuchtdioden mit Bohrer und Feile eingebracht habe. Die beiden Löcher rechts und links der Lichtschranken dienen der Ausrichtung am Stromzähler. Dadurch kann ich beim Ausrichten die Drehscheibe orten.

Befestigt habe ich das Ganze mit Lochband und Gummiringe :slight_smile: .

Jetzt kommen wir zur Software:

Auf den D1 Mini habe ich über ESPHome folgende YAML geflasht:

esphome:
  name: esp-stromzaehler
  friendly_name: ESP-Stromzaehler

esp8266:
  board: d1_mini

# Enable logging
logger:
  level: DEBUG
  #level: NONE

# Enable Home Assistant API
api:
  encryption:
    key: "xxx"   # individuelles Password

ota:
  - platform: esphome
    password: "xxx"   # individuelles Password

wifi:
  ssid: !secret wifi_ssid
  password: !secret wifi_password

  # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: "Esp-Stromzaehler"
    password: "xxx"   # individuelles Password

captive_portal:

globals:

  - id: Rechtslauf   # true: Rechtslauf erkannt; false: Linkslauf erkannt
    type: bool
    restore_value: false
    initial_value: 'false'   # Initialwert bei Neustart (Spannung anlegen)

  - id: SaveRechtslauf   # Sicherung der letzten Drehrichtung für Sensor "Leistung"
                         # true: Rechtslauf; false: Linkslauf
    type: bool
    restore_value: false
    initial_value: 'false'   # Initialwert bei Neustart (Spannung anlegen)

  - id: FreigabeUmd   # Zählimpulserkennung für Ausspeisung bzw. Einsteisung, true: ist freigegeben; false: ist gesperrt
    type: bool
    restore_value: false
    initial_value: 'false'   # Initialwert bei Neustart (Spannung anlegen)

  - id: FreigabeLeistung   # Zählimpulserkennung für Leistungsberechnung, true: ist freigegeben; false: ist gesperrt
    type: bool
    restore_value: false
    initial_value: 'false'   # Initialwert bei Neustart (Spannung anlegen)

  - id: ImpulseRechts   # Anzahl der Impulse Rechtsdrehung (seit dem letzten Start)
    type: int
    restore_value: false
    initial_value: '0'   # Initialwert bei Neustart (Spannung anlegen)

  - id: ImpulseLinks   # Anzahl der Impulse Linksdrehung (seit dem letzten Start)
    type: int
    restore_value: false
    initial_value: '0'   # Initialwert bei Neustart (Spannung anlegen)

  - id: LS   # für LogAusgabe: Lichtschranke: "LS1" oder "LS2"
    type: std::string
  
  - id: aktion   # für LogAusgabe: Aktion, die die Lichtschranke "LS" ausgelöst hat: "on_press" oder "on_release"
    type: std::string

binary_sensor:
    # Lichtschranke "LS1"
  - platform: gpio
    id: LS1_Impuls
    name: LS1_Impuls   # Impuls von Lichtschranke "LS1"
    internal: true
    pin: 
      number: D5   # Lichtschranke "LS1"
      allow_other_uses: true
      mode: 
        input: true
        pullup: true

    filters:
      - delayed_on: 50ms

    on_press:   # Stromzählscheibe rot
      then:
        - lambda:
            id(LS) = "LS1";
            id(aktion) = "on_press";

        - script.execute: StromzaehlscheibeRot

    on_release:   # Stromzählscheibe silber
      then:
        - lambda:
            id(LS) = "LS1";
            id(aktion) = "on_release"; 

        - script.execute: StromzaehlscheibeSilber
      
  - platform: gpio
    # Lichtschranke "LS2"
    id: LS2_Impuls    
    name: LS2_Impuls   # Impuls von Lichtschranke "LS2"
    internal: true
    pin: 
      number: D2   # Lichtschranke "LS2"
      mode: 
        input: true
        pullup: true

    filters:
      - delayed_on: 50ms

    on_press:   # Stromzählscheibe rot
      then:
        - lambda:
            id(LS) = "LS2";
            id(aktion) = "on_press";

        - script.execute: StromzaehlscheibeRot

    on_release:   # Stromzählscheibe silber
      then:
        - lambda:
            id(LS) = "LS2";
            id(aktion) = "on_release";

        - script.execute: StromzaehlscheibeSilber

number:
    # Stromausspeisung
  - platform: template
    id: Stromausspeisung
    name: Stromausspeisung
    icon: "mdi:meter-electric"
    optimistic: true
    min_value: 0
    max_value: 9999999
    step: 1
    update_interval: 0s

    # Stromeinspeisung
  - platform: template
    id: Stromeinspeisung
    name: Stromeinspeisung
    icon: "mdi:meter-electric"
    optimistic: true
    min_value: 0
    max_value: 9999999
    step: 1
    update_interval: 0s

sensor:
    # Leistungsermittlung mittels Puls_meter
  - platform: pulse_meter
    pin: 
      number: D5   # Lichtschranke LS1
      allow_other_uses: true
    name: "Leistung"
    unit_of_measurement: 'W'
    device_class: power
    state_class: measurement
    accuracy_decimals: 0
    internal_filter: 100ms
    internal_filter_mode: PULSE
    timeout: 20min
    filters:
      #
      # Wenn "FreigabeLeistung" false, dann wird der Impuls nicht ausgewertet.
      # Wenn Drehrichtungsumkehr erkannt, dann 0 W zurückgeben.
      # Wenn "LS1" true und "LS2" false und "Rechtslauf", dann Leistung berechnen,
      # wenn "LS1" true und "LS2" true und "Linkslauf", dann Leistung berechnen,
      # ansonsten 0 W (Drehrichtungsumkehr) zurückgeben.
      #  
      # Impulsdauer [Impulse/min] multiplizieren mit
      #   800.0 = 60 Minuten pro Stunde / 75 Impulse pro 1000 Wh
      #   1.03  = für die Länge der roten Markierung 3% Zuschlag
      # positiver Wert: Stromausspeisung aus dem öffentlichen Netz
      # negativer Wert: Stromeinspeisung in das öffentlichen Netz
      - lambda: |-
          if (!id(FreigabeLeistung)) return {};
          id(FreigabeLeistung) = false;
          if (id(SaveRechtslauf) != id(Rechtslauf))
            {id(SaveRechtslauf) = id(Rechtslauf);
            return {0};
            }
          if (id(LS1_Impuls).state && !id(LS2_Impuls).state && id(SaveRechtslauf))
            {return x * 800.0 * 1.03;
            }
          else if (id(LS1_Impuls).state && id(LS2_Impuls).state && !id(SaveRechtslauf))
            {return x * 800.0 * -1.03;
            }
          else {
            return {0};
            }

script:
  - id: StromzaehlscheibeRot   # wird von beiden LSs aufgerufen, wenn "Rot" erkannt wird
    then:
          # wenn LS1 = high und LS2 = low dann Rechtslauf 

          # wenn LS1 = low und LS2 = high dann Linkslauf 

          # wenn beide LSs "rot" erkennen und Zählimpulserkennung ist freigegeben,
          # dann wird eine Umdrehung gezählt (entweder Rechtsumdrehung oder Linksumdrehung)
          #   und der Nummernsensor "Stromausspeisung" bzw. "Stromeinspeisung" gesetzt
      - lambda:
          if (id(LS1_Impuls).state && !id(LS2_Impuls).state)
            {if (id(FreigabeUmd) && !id(Rechtslauf)) 
              {id(FreigabeUmd)  = false;
              }         
              id(Rechtslauf) = true;
            };

          if (!id(LS1_Impuls).state && id(LS2_Impuls).state)
            {if (id(FreigabeUmd) && id(Rechtslauf)) 
              {id(FreigabeUmd)  = true;
              }
              id(Rechtslauf) = false;
            };

          if (id(LS1_Impuls).state && id(LS2_Impuls).state && id(FreigabeUmd))
            {id(FreigabeUmd) = false;

            if (id(Rechtslauf)) 
              {id(ImpulseRechts) += 1;
              auto call = id(Stromausspeisung).make_call();
              call.set_value(float(id(ImpulseRechts)));
              call.perform();         
              }
            else {id(ImpulseLinks) += 1;
              auto call = id(Stromeinspeisung).make_call();
              call.set_value(float(id(ImpulseLinks)));
              call.perform();                     
              }
            }

      - script.execute: LogAusgabe

  - id: StromzaehlscheibeSilber   # wird von beiden LSs aufgerufen, wenn "Silber" erkannt wird
    then:
          # wenn beide LSs "silber" erkennen, dann wird Zählimpulserkennung (FreigabeUmd) und
          # Leistungsmessung (FreigabeLeistung) wieder freigegeben

          # wenn "LS1" der Auslöser (on_release) ist, dann Linkslauf, sonst Rechtslauf
      - lambda:
          if (!id(LS1_Impuls).state && !id(LS2_Impuls).state)
            {id(FreigabeUmd) = true;
            id(FreigabeLeistung) = true;           

            if (id(LS) == "LS1")
              {id(Rechtslauf) = false;
              }
            else {id(Rechtslauf) = true;
              }
            }

      - script.execute: LogAusgabe

  - id: LogAusgabe
    then:
      - logger.log:
          format: "Lichtschranke: %s"
          args: ['id(LS).c_str()']
          level: INFO

      - logger.log:
          format: "Aktion: %s"
          args: ['id(aktion).c_str()']
          level: INFO

      - logger.log:
          format: "LS1_Impuls %i"
          args: ['id(LS1_Impuls).state']
          level: INFO

      - logger.log:
          format: "LS2_Impuls %i"
          args: ['id(LS2_Impuls).state']
          level: INFO

      - logger.log:
          format: "Rechtslauf %i"
          args: ['id(Rechtslauf)']
          level: INFO

      - logger.log:
          format: "ImpulseRechts %i"
          args: ['id(ImpulseRechts)']
          level: INFO

      - logger.log:
          format: "ImpulseLinks %i"
          args: ['id(ImpulseLinks)']
          level: INFO

      - logger.log:
          format: "FreigabeUmd %i"
          args: ['id(FreigabeUmd)']
          level: INFO

      - logger.log:
          format: "FreigabeLeistung %i"
          args: ['id(FreigabeLeistung)']
          level: INFO

Der Sensor “Leistung” ermittelt mittels “pulse_meter” die aktuelle Leistung des Stromzählers in [W], positive Werte bei Strombezug, negative Werte bei Stromeinspeisung.

In HomeAssistant auf dem Raspberry Pi müssen dann noch folgende Arbeiten ausgeführt werden:

Über das UI zwei Helfer als “Counter” anlegen:
“StromAusspeisung_Impulse”
“StromEinspeisung_Impulse”

Bei dem Helfer “StromAusspeisung_Impulse” kann man als Anfangswert den Zählerstand (in Impulse) angeben, bei mir also (Zählerstand * 75 U/kWh). Dann liefert der Helfer den aktuellen Zählerstand.

Sensoren in die “configuration.yaml” hinzufügen:

template:
  - sensor:
      - name: "StromEinspeisung"
        unique_id: 'sensor.stromeinspeisung'
        device_class: 'energy'
        unit_of_measurement: "kWh"
        state: "{{ (states('counter.stromeinspeisung_impulse')|int / 75) | round(3) }}"
        state_class: 'total_increasing'
        
      - name: "StromAusspeisung"
        unique_id: 'sensor.stromausspeisung'
        device_class: 'energy'
        unit_of_measurement: "kWh"
        state: "{{ (states('counter.stromausspeisung_impulse')|int / 75) | round(3) }}"
        state_class: 'total_increasing'
        
      - name: "StromZaehlerStand"
        unique_id: 'sensor.stromzaehlerstand'
        device_class: 'energy'
        unit_of_measurement: "kWh"
        state: "{{ (states('sensor.stromausspeisung')|float 
                  - states('sensor.stromeinspeisung')|float) | round(1) }}"
        state_class: 'total'
                

Für die Automationen folgenden Code in die “automations.yaml” einfügen (oder über das UI eingeben):

- id: '123'    # individuelle id
  alias: StromAusspeisungErhöhen
  description: Erhöht die Stromausspeisung um eine Umdrehung, also um 1/75 kWh = 0.01333
    kWh.
  trigger:
  - platform: state
    entity_id:
    - number.esp_stromzaehler_stromausspeisung
  condition: []
  action:
  - service: counter.increment
    metadata: {}
    data: {}
    target:
      entity_id: counter.stromausspeisung_impulse
  mode: queued

- id: '456'    # individuelle id
  alias: StromEinspeisungErhöhen
  description: Erhöht die Stromeinspeisung um eine Umdrehung, also um 1/75 kWh = 0.01333
    kWh.
  trigger:
  - platform: state
    entity_id:
    - number.esp_stromzaehler_stromeinspeisung
  condition: []
  action:
  - service: counter.increment
    target:
      entity_id:
      - counter.stromeinspeisung_impulse
    data: {}
  mode: queued

Bei mir funktioniert die Strommessung mit dem oben beschriebenen Aufbau jetzt seit ca 2 Wochen problemlos.

3 „Gefällt mir“

Das mit dem Finanzamt ist so nicht richtig.
Der Zähler darf rückwärts laufen.
Es kann bis zu 4 Monate dauern bis der Zähler getauscht wird.
Das ist aber das Problem vom Netzbetreiber.

Dann wohnst du wohl im falschen Bundesland.
Hier dauert das 3-4 Monate.
Dann hat man noch 4 Wochen Zeit um das BKW anzumelden.
Macht dann 4-5 Monate rückwärts laufenden Zähler. :grinning:

Das finde ich sehr spannend. Man betreibt also Steuerhinterziehung, wenn man sich an das aktuelle Gesetz hält, die so genannte “Steckerfertige Solaranlage” im Marktstammdatenregister anmeldet und der VNB den Zähler nicht innerhalb von vier Wochen austauscht? Bitte erläutere das mal etwas genauer, auch gerne mit nachprüfbaren Quellenangaben, sowohl bezüglich des Zeitraums als auch bezüglich der Steuerhinterziehung. Vielen Dank schon mal im voraus!

Einfach mal was in den Raum schmeißen und dies nicht belegen können.
Ohne Worte. :face_with_spiral_eyes:

Wobei hilfst du wem mit diesem Beitrag?

Das ist zwar ein älterer Thread, aber ich fand’ es “erfrischend” zu erfahren, das auch in anderen Haushalten noch diese Anno-Tobak-Technik (Ferraris-Zähler) für die abrechnungs-relevante Verbrauchs-Erfassung im Einsatz ist.

Hierzu ein kleines “Schmankerl” aus dem juristischen Dschungel: Alle die noch einen solchen Zähler bei sich am Hausanschluss haben, sollten das Eich-Jahr checken. Stromzähler sind i.d.R. “ab Werk” für maximal 6 Jahre geeicht. Zwar ist theoretisch eine Verlängerung auf bis zu 12 Jahre möglich, aber dazu ist - anders als bei anderen Zähler-Typen - eine Einzelprüfung des Geräts notwendig, da es kein von der PTB anerkanntes Stichproben-Verfahren zur bauart-basierten Verlängerung der Eichgültigkeit gibt!

Wenn ihr also - so wie wir - z.B. ein Ferraris-Zähler mit Baujahr 2018 oder älter habt, bei dem nicht kürzlich jemand durch eine Prüfung des Einzelgeräts die Eichfrist verlängert hat, solltet ihr euren Netzbetreiber an die §§ 25, 33 und 34 MessEG erinnern und einen zeitnahen Austausch des Zählers verlangen. Damit könnte man die Wartezeit für den Einbau eines ja mittlerweile gesetzlich vorgeschriebenen moderneren, leichter auslesbaren Zählers verkürzen :slight_smile:

1 „Gefällt mir“

Interessante Info. Wir haben so einen Drehstromzähler. Eine Jahreszahl kann ich nicht erkennen. Neben „Drehstromzähler“ steht 20.14- wir wohnen seit 2011 in diesem Haus und er wurde noch nie geeicht bzw. gewechselt soweit ich mich erinnern kann. BJ vom Haus ist 2002…
Also könnte ich meinen Netzbetreiber jetzt dazu auffordern, den Zähler zu wechseln?
Kann ich mit einem Digitalenzähler auslesen, wie mein Verbrauch ist via HA oder braucht man dennoch so einen Smartmeter dafür?
Was ist der Vorteil des Digitalen Zählers?

Danke

Korrekt. Einfach innerhalb von 4 Wochen beim Marktstammdatenregister anmelden, der Rest ist dann Sache des Netzbetreibers. Bei uns ging es auch ca 4 Monate bis er den Zähler getauscht und solange kann auch fleißig eingespeist werden

Über die von Simon im oben erwähnten Video beschriebene Lösung kann man auch von solch einem “antiken” Ferraris-Zähler mit etwas Geduld bei der Einrichtung zumindest mal den Netzbezug erfassen und rel. konkrete Werte für das “Verbrauchsprofil” bekommen.

Ich hab’ jetzt mal meinen Netzbetreiber angeschrieben und mit Verweis auf die Rechtslage (unser Zähler ist Bj 2010, ein Iskra T3F-01S1) aufgefordert mir innerhalb von 14 Tagen einen Termin für den Austausch zu nennen bzw. nachvollziehbar darzulegen, warum er meint, dieser Zähler “sei noch gut” :slight_smile:

Einstweilen habe ich - mehr interessehalber - die Lösung mit einem Wemos D1 mini und einem TCRT50000 in Verbindung mit ESPhome gebaut. Das kalibrieren der Infrarot-LED und die korrekt Ausrichtung vor dem Zähler-Rad waren aber schon arg fummelig und wesentlich zeitaufwendiger, als die Komponenten zusammenzudengeln. Den Halter für den TCRT5000 und das Gehäuse für den D1 Mini hab’ ich mir von einem 3D-Druck-Dienst anfertigen lassen. Ohne Werbung machen zu wollen, erschienen mir die Preise bei https://fdm-druckservice.de/ doch recht attraktiv, um einfach mal “hands-on” Erfahrungen mit ESPs und ESPhome zu sammeln :wink:

Da aber hier die Anschaffung einer “ausgewachsenen” PV-Anlage ansteht, kommen die um einen Austausch des Zählers ohnehin nicht herum und somit war das eher “Spielerei” - wenn auch eine erstaunlich gut funktionierende und hinreichend genaue…

Der Vorteil, wenn man diese “Auslese-Krücke” einsetzt - und diese ausreichend genau misst - ist, das man in HA über das Energie-Dashboard dann schön tracken kann, wo denn der Strom im Haus hinfließt und wo man nicht erfassten Verbrauch hat…

1 „Gefällt mir“