Best Swimming Pool monitoring solution: ORP, Ph, temp

Hello together,

I had also issues with the measuring of w2839. When the pump is switched of and a couple of minutes after measuring start the values are not accurated.

For this reason I have connected the peristaltic pump to a separate Tuya WIFI switch that also controls the filter pump.

All values can be ready easily with the tuya local integration.
For visalisation I have used pool monitor card.

YAML automation for pool dosing independent from W2839:

  • switch.schwimmbad_steuerung_schalter_1 = chlorine dosing
  • switch.schwimmbad_steuerung_schalter_2 = PH minus dosing
  • switch.schwimmbad_steuerung_schalter_3 = Filter Pump control

YAML Code

alias: Schwimmbad Automatik Dosierung
description: PH und ORP Regelung
triggers:
  - entity_id:
      - switch.schwimmbad_steuerung_schalter_3
    trigger: state
    from: "off"
    to: "on"
actions:
  - action: switch.turn_off
    metadata: {}
    target:
      entity_id:
        - switch.schwimmbad_steuerung_schalter_1
        - switch.schwimmbad_steuerung_schalter_2
    data: {}
  - alias: 15min Warten um die Messung zu stabilisieren
    delay:
      hours: 0
      minutes: 15
      seconds: 0
      milliseconds: 0
  - repeat:
      while:
        - condition: state
          entity_id: switch.schwimmbad_steuerung_schalter_3
          state: "on"
      sequence:
        - choose:
            - conditions:
                - condition: or
                  conditions:
                    - condition: numeric_state
                      entity_id: sensor.schwimmbad_monitor_orp
                      above: 1000
                    - condition: numeric_state
                      entity_id: sensor.schwimmbad_monitor_orp
                      below: 200
                    - condition: numeric_state
                      entity_id: sensor.schwimmbad_monitor_ph
                      below: 3
                    - condition: numeric_state
                      entity_id: sensor.schwimmbad_monitor_ph
                      above: 9
              sequence:
                - data:
                    title: Schwimmbad Alarm
                    message: >
                      Ungültige Messwerte erkannt. PH={{
                      states('sensor.schwimmbad_monitor_ph') }} ORP={{
                      states('sensor.schwimmbad_monitor_orp') }} Temperatur={{ 
                      states('sensor.schwimmbad_monitor_temperatur') }}
                    notification_id: schwimmbad_warnung_sensor
                  action: persistent_notification.create
              alias: Fehlerprüfung Wertebereich
            - conditions:
                - condition: numeric_state
                  entity_id: sensor.schwimmbad_monitor_ph
                  below: 7
              sequence:
                - action: persistent_notification.create
                  data:
                    title: Schwimmbad Warnung
                    message: >
                      pH-Wert zu niedrig: {{
                      states('sensor.schwimmbad_monitor_ph') }}. Keine
                      Chlor-Dosierung aktiv.
                    notification_id: schwimmbad_warnung_ph
              alias: Wenn ph < 7.0 - Dosierung inaktiv
            - conditions:
                - condition: numeric_state
                  entity_id: sensor.schwimmbad_monitor_orp
                  above: 780
              sequence:
                - data:
                    title: Schwimmbad Warnung
                    message: >
                      ORP ist hoch: {{states('sensor.schwimmbad_monitor_orp') }}
                      mV
                    notification_id: schwimmbad_warnung_orp
                  action: persistent_notification.create
              alias: Warnung wenn ORP zu hoch
            - conditions:
                - condition: numeric_state
                  entity_id: sensor.schwimmbad_monitor_ph
                  above: 7.3
              sequence:
                - condition: state
                  entity_id: switch.schwimmbad_steuerung_schalter_3
                  state: "on"
                - target:
                    entity_id: switch.schwimmbad_steuerung_schalter_2
                  action: switch.turn_on
                  data: {}
                - delay:
                    seconds: 15
                - target:
                    entity_id: switch.schwimmbad_steuerung_schalter_2
                  action: switch.turn_off
                  data: {}
              alias: Wenn ph > 7.3 ZUERST PH senken
            - conditions:
                - condition: and
                  conditions:
                    - condition: numeric_state
                      entity_id: sensor.schwimmbad_monitor_ph
                      above: 7.1
                      below: 7.3
                    - condition: numeric_state
                      entity_id: sensor.schwimmbad_monitor_orp
                      below: 700
                    - condition: numeric_state
                      entity_id: sensor.schwimmbad_monitor_temperatur
                      above: 15
              sequence:
                - condition: state
                  entity_id: switch.schwimmbad_steuerung_schalter_3
                  state: "on"
                - target:
                    entity_id: switch.schwimmbad_steuerung_schalter_1
                  action: switch.turn_on
                - delay:
                    seconds: 10
                - target:
                    entity_id: switch.schwimmbad_steuerung_schalter_1
                  action: switch.turn_off
              alias: Wenn PH OK (7.1 - 7.3) und ORP<700, dann ORP heben
        - alias: >-
            20min warten um die Dosierung zu stabilisieren bzw. Neumessung
            durchzuführen.
          delay:
            hours: 0
            minutes: 20
            seconds: 0
            milliseconds: 0
  - alias: Dosierung deaktivieren - Sicherheitsfunktion
    repeat:
      while:
        - condition: switch.is_on
          target:
            entity_id:
              - switch.schwimmbad_steuerung_schalter_1
              - switch.schwimmbad_steuerung_schalter_2
          options:
            for: "00:00:00"
            behavior: any
      sequence:
        - action: switch.turn_off
          metadata: {}
          target:
            entity_id:
              - switch.schwimmbad_steuerung_schalter_1
              - switch.schwimmbad_steuerung_schalter_2
          data: {}
        - delay:
            hours: 0
            minutes: 0
            seconds: 1
            milliseconds: 0
mode: single

Have fun! Improvements and ideas are welcome!

Thanks Willian for your work. :blush:

I have ported your project to use the cb3s instead of replacing it with an esp32.

Github Repo W218

ran it through MS Copilot, here´s what i got:

template:
  - sensor:
      - name: "Pool Chlor"
        unique_id: pool_chlor
        unit_of_measurement: "ppm"
        device_class: water
        state: >
          {% set ph = states('sensor.sonda_piscina_ph') | float(0) | round(1) %}
          {% set orp = states('sensor.sonda_piscina_orp') | float(0) %}
 
          {% set werte = {
            6.5: [740.04, 141.14],
            6.6: [734.99, 139.02],
            6.7: [729.97, 136.80],
            6.8: [725.01, 134.64],
            6.9: [720.04, 132.43],
            7.0: [714.99, 130.28],
            7.1: [710.02, 128.09],
            7.2: [704.95, 125.88],
            7.3: [700.03, 123.72],
            7.4: [695.18, 121.41],
            7.5: [689.94, 119.47],
            7.6: [685.00, 117.25],
            7.7: [680.00, 115.10],
            7.8: [675.03, 112.91],
            7.9: [670.03, 110.75],
            8.0: [665.01, 108.61]
          } %}
 
          {% if ph < 6.5 %}
            {% set ph = 6.5 %}
          {% elif ph > 8.0 %}
            {% set ph = 8.0 %}
          {% endif %}
 
          {% set a = werte[ph][0] %}
          {% set b = werte[ph][1] %}
 
          {% set chlor = e ** ((orp - a) / b) %}
 
          {{ [chlor, 0] | max | round(2) }}

benefits should be:
only one final sensor, source sensors get read only once, negative values are capped to 0 and easier maintenance and readabilty through the table and less if statements.

cant test it atm as my W218 still waits installation but maybe someone can test it.
big thx for your initial work!

copilot adviced, interpolation would be even better then linear approach:

      - name: "Pool Chlor"
        unique_id: pool_chlor
        unit_of_measurement: "ppm"
        device_class: water
        state: >
          {% set ph = states('sensor.wifi_smart_online_8_in_1_tester_ph') | float(7.2) %}
          {% set orp = states('sensor.wifi_smart_online_8_in_1_tester_oxidation_reduction_potential') | float(0) %}

          {% set werte = {
            6.5: [740.04, 141.14],
            6.6: [734.99, 139.02],
            6.7: [729.97, 136.80],
            6.8: [725.01, 134.64],
            6.9: [720.04, 132.43],
            7.0: [714.99, 130.28],
            7.1: [710.02, 128.09],
            7.2: [704.95, 125.88],
            7.3: [700.03, 123.72],
            7.4: [695.18, 121.41],
            7.5: [689.94, 119.47],
            7.6: [685.00, 117.25],
            7.7: [680.00, 115.10],
            7.8: [675.03, 112.91],
            7.9: [670.03, 110.75],
            8.0: [665.01, 108.61]
          } %}

          {% set ph = [8.0, [6.5, ph] | max] | min %}

          {% set ph_unten = (ph * 10) | round(0, 'floor') / 10 %}
          {% set ph_oben  = [8.0, ph_unten + 0.1] | min %}

          {% set faktor = (ph - ph_unten) / (ph_oben - ph_unten) if ph_oben != ph_unten else 0 %}

          {% set a =
            werte[ph_unten][0] +
            (werte[ph_oben][0] - werte[ph_unten][0]) * faktor
          %}

          {% set b =
            werte[ph_unten][1] +
            (werte[ph_oben][1] - werte[ph_unten][1]) * faktor
          %}

          {% set chlor = e ** ((orp - a) / b) %}

          {{ [chlor, 0] | max | round(2) }}

feel free to test it

I will see if I can source that here in the US. I finally installed my Atlas Scientific PMP Bx pump with ESP Home integration and I’m dosing manually based on historical data. Now to determine whether an ORP setup or Waterguru (for ease of use) is better. Quite frankly, I’d like to avoid third party stuff, but need a system that works consistently in the Florida heat.

hy, did you have any manual or how to, for flashing the device?

i did not find any useful information.

thx for your help

After 6 months of almost fulltime tinkering I have it all setup:

  • Inver Hero Variable speed pump
  • Yieryi ph W218 (updated probes)
  • Sundream LC400A Chloride elecrtolyse unit
  • Sundream TS100 Water Quality/pH pump

All monitored in HA, for now automation still running via Tuya, all available in Tuya Local.
The W218 and the TS100 differ on ORP, but the spread is stable


really nice.
how you integrate the big multi testing sonde?
can you tell me witch components are used

thx