Pool Monitor Device Yieryi BLE-YC01

My device never had a stable connection, but recently it would not stay on for more than a few minutes even right next to the proxy. Then the power button stopped working, so could not turn it on or turn Bluetooth on. I opened it up and noticed the 4-pin power button was very corroded. I cut the button out by snipping the 4 legs. Next, I turned it on by tapping a wire between the top two contacts, then long held the wire to turn BT on. Whalla! It has been a stable for a couple days, but I have it two inches from a ESP32 proxy. There must have been a voltage leak in the corroded button, which was triggering it off. I need to solder on a new button, luckily, I have some from another project. I will solder only the top two connections and put some electrical tape under the button to avoid additional groundings. Iā€™ll report back if still stable in the pool once fixed. You can notice from the picture the Hold/Temp button is a little corroded too. If having connection issues, check the buttons!

I calibrated the PH and it is giving sensible readings. Ordered some TDS and ORP calibration solution. I hope it makes those readings accurate as well.

Thanks all for the PRs to the integration.

Edit: Device still got waterlogged and died. Even used tape and silicone in bottom. I will keep the integration posted, but obviously will not be updating it anymore, unless people submit PRs.

Thanks for sharing. My device started misbehaving a week ago after having been stable for months. Iā€™l have to disassemble and see whether there is a similar problemā€¦

My ORP value is still negative about -300mV. All other values are fine (pH is 7,1), only chlorine is still 0. This is probably due to the negative ORP value. Have you experienced a similar problem? Do you know what to do? Thanks.

Does your device also gives you ā€” for chlorine?

No. There is still 0.0 mg/l.
Current values are: ORP -139 mV, TDS 576ppm, pH 7.2, Salt 633,6 ppm, EC 1 152 ĀµS/cm, Temp 30,8 Ā°C.

yeah, ORP is indeed to low, i i have 130 , added some chlorine a few minuts ago, it should increase then :slight_smile:

i also have ā€” for CH reading

image

But how to increase the ORP from negative to positive. According to another measurement I have the right amount of chlorine in my water - 3ppm (3mg/l).

not sure, i never looked at it :slight_smile:
i just added some CH an hour ago, and increased from 190 to 307 :slight_smile:
but CH still 0 , need to wait a little more

I think there is no other way than to recalibrate - I had the same problem and after recalibration itā€™s fine. You need to get an ORP solution for it.

I tried calibrating the ORP, but it didnā€™t work at all. pH calibration without problem. After switching to ORP and dipping into the reference solution, I pressed the Mode/Cal button for 5 seconds as instructed, but the ORP values could not be adjusted. The Up button did nothing and the Down (Mode/Cal) button switched the display mode. I tried 3 - 5 - 7 - 10 seconds, but nothing. The temperature of the solution was about 25 degrees. And when dipped in the reference solution, the readings were between 40 and 0. My pool water is still about -140. So it looks like a sensor malfunction.

If you canā€™t adjust the orp value, it looks more like some electronic malfunction. I had to try twice because there is no feedback when you have pressed long enough. But after pressing so 5-7 seconds, I think ā€œCALā€ flashed for a second, and then I could use up/down until it reached 256, and then it was finished. You do have an ORP ref solution, right?

Yes, I have. I prepared new calibration solutions for pH and for ORP (I needed to wait for new one, which I had orderedā€¦). Now I think, the problem is electronic.

Well, I tried again today, and ran in to the same problem. It worked 2 out of 20 times, but then I didnā€™t have it in the correct solutionā€¦ really weirdā€¦

it seems my device is leaking again. sealed top and interior again, but worked only a day. now but a lot more silicone inside in the bottom, letā€™s see.
The device has really abysmal water resistance. Also ordered some hemp to get a tight seal on the top cover.

One thing Iā€™ve found, is that while I donā€™t have issues with leaking, I do have the issues some have had where it works for a while, then stops working. Iā€™m currently using the ESPHome version, rather than the integration. Both seem to do the same thing; work a few times, or for a day or so and then nothing (even when itā€™s physically close to the ESP device). If I try the app that does always work however, so Iā€™m not 100% sure itā€™s the device. What Iā€™ve found now though is that ESPHome will always make a good reading the first time after it restarts. So, knowing this I could just do an automation to restart the ESP every half hour or whatever, but I was wondering if that info would help someone figure out what the issue was, as Iā€™d have thought each connection would be a ā€˜freshā€™ one from the deviceā€™s point of view, but it seems not since restarting make it work so there must be something that the ESPHome does differently the first time vs subsequent times.

Make sure the ESP device is very close to the pool monitor, I have the same issue, when itā€™s like 4 meters away, itā€™s always reliable, if the monitor is like 6-7 meters away, it starts droppingā€¦ So I have now fixed the monitor with a cord, so itā€™s not on the other side of the pool

I think I finally got the device sealed tightly enough so that it continuously sends data.

However, Iā€™ve run into the next problem: I canā€™t calibrate pH anymore!

It has become so decalibrated, that for both the 4 and 9ph-solution, it shows values too close to 6.8, so it will always pick these up as 6.8 solution during calibration!

does anybody know how to completely reset calibration data?

1 Like

I have had this device now for 34 days in lay-z-spa.
First thing what I did added silica bag in and some silicon grease to the sealing o-ring. So that should make it absorb some moisture and bit better water proof.

However within few days noticed there is moisture under the display. Chcked inside it was dry. Noticed there is some bubbles near the buttons. I could press with fingers the bubbles and the water come out from the bubbles. Could not get the display yet out of moisture, maybe needs longer dry out or prying out the top layerā€¦

So seems the top layer taping is not pressed with enough pressure and it leaks.
So check that the top layer taping is flat and no bubbles before taking in to use.

Otherwise the device has been working great, hopefully it is not yet corroded too much and get display dried out during the off season.

1 Like

Iā€™ve integrated my device using HACS and this repository

itā€™s connected with my HotSprings Spa ESP-IQ2020 which Iā€™m using to control the chlorine generator (Freshwater System)

Iā€™m not 100% sure on the readings from the YC01 device (device reading 1.1 Free Chlorine, Test strip indicates itā€™s closer to 2), so Iā€™ve created a few virtual sensors that can be adjusted with calibration values to match the chlorine test strip readings.
Iā€™m testing out 4 different algorithms using a variety of ORP, EC, pH, and temperature. Youā€™ll have to calibrate them initially using a test strip, but hopefully over time Iā€™ll have a more reliable chlorine reading (that even works outside the pH range of the YC01). Honestly, I donā€™t have much insight on the calculations themselves, they were made with a combination of chatGPT and users with similar devices.

code added to configuration.yaml

input_number:
  chlorine_k_simplified:
    name: "Simplified Chlorine k"
    min: 0.000001
    max: 1
    step: 0.001
    unit_of_measurement: "k"
    initial: 0.095

  chlorine_k_simplified_ph:
    name: "Simplified Chlorine (PH) k"
    min: 0.000001
    max: 1
    step: 0.001
    unit_of_measurement: "k"
    initial: 0.73

  chlorine_k_complex:
    name: "Complex Chlorine k"
    min: 0.0001
    max: 300
    step: 0.1
    unit_of_measurement: "k"
    initial: 180

  chlorine_k_complex_ec_temp:
    name: "Complex Chlorine EC/Temp k"
    min: 0.0001
    max: 12
    step: 0.1
    unit_of_measurement: "k"
    initial: 6.2

sensor:
  - platform: template
    sensors:

      calculated_chlorine_level:
        friendly_name: "Calculated Chlorine Level"
        unique_id: "calculated_chlorine_level"
        unit_of_measurement: "ppm"
        value_template: >
          {% set orp = states('sensor.c0_00_00_03_d9_28_oxidation_reduction_potential') | float(0) %}
          {% set ec = states('sensor.c0_00_00_03_d9_28_electrical_conductivity') | float(0) %}
          {% set temp = states('sensor.c0_00_00_03_d9_28_temperature') | float(0) %}
          {% set k = states('input_number.chlorine_k_simplified') | float(0) %}

          {{ (k * orp * ec / temp) | round(2) }}
        icon_template: mdi:chemical-weapon

      calculated_chlorine_level_with_ph:
        friendly_name: "Calculated Chlorine Level (with pH)"
        unique_id: "calculated_chlorine_level_with_ph"
        unit_of_measurement: "ppm"
        value_template: >
          {% set orp = states('sensor.c0_00_00_03_d9_28_oxidation_reduction_potential') | float(0) %}
          {% set ec = states('sensor.c0_00_00_03_d9_28_electrical_conductivity') | float(0) %}
          {% set temp = states('sensor.c0_00_00_03_d9_28_temperature') | float(0) %}
          {% set ph = states('sensor.c0_00_00_03_d9_28_ph') | float(0) %}
          {% set k = states('input_number.chlorine_k_simplified_ph') | float(0) %}

          {{ (k * orp / ph * ec / temp) | round(2) }}
        icon_template: mdi:chemical-weapon

      calculated_chlorine_complex:
        friendly_name: "Calculated Chlorine Complex"
        unique_id: "calculated_chlorine_complex"
        unit_of_measurement: "ppm"
        value_template: >
          {% set orp = states('sensor.c0_00_00_03_d9_28_oxidation_reduction_potential') | float(0) %}
          {% set ph = states('sensor.c0_00_00_03_d9_28_ph') | float(0) %}
          {% set k = states('input_number.chlorine_k_complex') | float(0) %}

          {{ ( k * (14 - ph) ** (1 / (400 - orp)) * (ph - 4.1) ** ((orp - 516)/145) + 10.0 ** ((orp + ph * 70 - 1282) / 40)) | round(2) }}
        icon_template: mdi:chemical-weapon

      calculated_chlorine_complex_ec_temp:
        friendly_name: "Calculated Chlorine Complex (EC & Temp)"
        unique_id: "calculated_chlorine_complex_ec_temp"
        unit_of_measurement: "ppm"
        value_template: >
          {% set orp = states('sensor.c0_00_00_03_d9_28_oxidation_reduction_potential') | float(0) %}
          {% set ph = states('sensor.c0_00_00_03_d9_28_ph') | float(0) %}
          {% set ec = states('sensor.c0_00_00_03_d9_28_electrical_conductivity') | float(0) %}
          {% set temp = states('sensor.c0_00_00_03_d9_28_temperature') | float(0) %}
          {% set k = states('input_number.chlorine_k_complex_ec_temp') | float(0) %}
          {% set adjustment = (ec / temp) %}

          {{ ( (k * (14 - ph) ** (1 / (400 - orp)) * (ph - 4.1) ** ((orp - 516)/145) + 10.0 ** ((orp + ph * 70 - 1282) / 40)) * adjustment ) | round(2) }}
        icon_template: mdi:chemical-weapon


type: vertical-stack
cards:
  - type: entity
    entity: sensor.calculated_chlorine_complex
    name: "Chlorine Level (Complex)"
  - type: entity
    entity: sensor.calculated_chlorine_complex_ec_temp
    name: "Chlorine Level (Complex with EC & Temp)"
  - type: entity
    entity: sensor.calculated_chlorine_level_with_ph
    name: "Chlorine Level (with pH)"
  - type: entity
    entity: sensor.calculated_chlorine_level
    name: "Chlorine Level"
  - type: entity

code added to ā€˜Entities Cardā€™ in dashboard for controlling the calibration values.

type: entities
title: Chlorine Offset Calibration Values
entities:
  - entity: input_number.chlorine_k_simplified
  - entity: input_number.chlorine_k_simplified_ph
  - entity: input_number.chlorine_k_complex
  - entity: input_number.chlorine_k_complex_ec_temp
1 Like

so my above method turned out to be a bit too complicated and didnā€™t give any meaningful results.
Iā€™ve settled on a simpler setup that allows me to calibrate the pH and ORP readings according to my test strip chlorine/pH measurements. So far, this has seemed pretty reliable as even if the device is measuring an incorrect ORP, we can give HA a good idea of the actual ORP by adjusting it to match the true chlorine reading. Even with incorrect ORP readings from the device, the readings seem to reliably fluctuate with chlorine levels.

It ends up being a pretty simple system. First measure your Chlorine and pH with a reliable tool (test strips). Then use the pH offset to get the calibrated pH reading in HA (assuming your device isnā€™t providing a true pH reading like mine was even after test solution calibration). Then adjust ORP Offset / ORP Overall Adjustment to get your Chlorine PPM to match your test reading.

# Calibration Offsets
input_number:
  ph_offset:
    name: pH Offset
    min: -5
    max: 5
    step: 0.01
    unit_of_measurement: ''
    icon: mdi:format-float-left
    initial: -1.2

  orp_offset:
    name: ORP Offset
    min: -1000
    max: 1000
    step: 1
    unit_of_measurement: 'mV'
    icon: mdi:flash
    initial: 400

  overall_adjustment:
    name: Overall Adjustment
    min: -1000
    max: 1000
    step: 1
    unit_of_measurement: 'mV'
    icon: mdi:adjust
    initial: 0

sensor:
  - platform: template
    sensors:
      chlorine_ppm:
        friendly_name: "Chlorine ppm"
        unique_id: "chlorine_ppm"
        unit_of_measurement: 'ppm'
        value_template: >-
          {% set ph_reading = states('sensor.c0_00_00_03_d9_28_ph') | float %}
          {% set orp_reading = states('sensor.c0_00_00_03_d9_28_oxidation_reduction_potential') | float %}
          {% set temp_f = states('sensor.c0_00_00_03_d9_28_temperature') | float %}
          {% set ph_offset = states('input_number.ph_offset') | float %}
          {% set orp_offset = states('input_number.orp_offset') | float %}
          {% set overall_adj = states('input_number.overall_adjustment') | float %}

          {# Adjusted pH and ORP readings #}
          {% set ph_cal = ph_reading + ph_offset %}
          {% set orp_cal = orp_reading + orp_offset %}

          {# Convert Temperature from Fahrenheit to Celsius #}
          {% set temp_c = (temp_f - 32) * (5/9) %}

          {# Temperature in Kelvin #}
          {% set temp_k = temp_c + 273.15 %}

          {# Nernst slope S in mV per pH unit (n = 1) #}
          {% set S = 0.1985 * temp_k %}

          {# Adjusted ORP accounting for pH influence #}
          {% set E_prime = orp_cal + S * (ph_cal - 6.6) %}

          {# Standard potential adjusted with overall adjustment #}
          {% set E0 = 646 + overall_adj %}

          {# Calculate Chlorine ppm #}
          {% set cl_ppm = 10 ** ((E_prime - E0) / S) %}

          {# Ensure the output is rounded and valid #}
          {{ cl_ppm | round(2) if cl_ppm >= 0 else 0 }}

      ph_calibrated:
        friendly_name: "Calibrated pH"
        unique_id: "ph_calibrated"
        unit_of_measurement: ''
        value_template: >-
          {% set ph_reading = states('sensor.hapic0_00_00_03_d9_28_ph') | float %}
          {% set ph_offset = states('input_number.ph_offset') | float %}
          {{ (ph_reading + ph_offset) | round(2) }}

      orp_calibrated:
        friendly_name: "Calibrated ORP"
        unique_id: "orp_calibrated"
        unit_of_measurement: 'mV'
        value_template: >-
          {% set orp_reading = states('sensor.hapic0_00_00_03_d9_28_oxidation_reduction_potential') | float %}
          {% set orp_offset = states('input_number.orp_offset') | float %}
          {{ (orp_reading + orp_offset) | round(1) }}

Card Config code:

type: vertical-stack
cards:
  - type: entities
    entities:
      - entity: sensor.chlorine_ppm
        name: Chlorine ppm
        icon: mdi:pool
      - entity: sensor.orp_calibrated
        name: Calibrated ORP
        icon: mdi:flash-triangle-outline
      - entity: sensor.ph_calibrated
        name: Calibrated pH
        icon: mdi:ph
      - entity: input_number.ph_offset
        name: pH Offset
      - entity: input_number.orp_offset
        name: ORP Offset
      - entity: input_number.overall_adjustment
        name: Overall Adjustment
1 Like