Code for PH Sensor DFRobot

@kp1602 I have updated my code to use the ADS1115 and have also added calibration services.

custom component: Custom dfrobot ph sensor with ads1115 for esphome · GitHub

esphome config:

esphome:
  includes:
    - custom_dfrobot_ph_sensor_adc.h
  libraries:
    - eeprom
    - onewire
    - DallasTemperature
    - Wire
    - SPI
    - adafruit/Adafruit BusIO
    - adafruit/Adafruit ADS1X15
    - file:///config/esphome/custom/DFRobot_ESP_PH_WITH_ADC

sensor:
  - platform: custom
    lambda: |-
      auto my_sensor = new CustomDFRobotPhSensor(30000);
      App.register_component(my_sensor);
      return {my_sensor->ph_sensor, my_sensor->temperature_sensor, my_sensor->voltage_sensor};
  
    sensors:
    - name: "pH Sensor"
      accuracy_decimals: 2
      unit_of_measurement: " "

    - name: "Water Temperature Sensor"
      accuracy_decimals: 2
      unit_of_measurement: "°F"
      filters:
      - lambda: return x * (9.0/5.0) + 32.0;

    - name: "pH Sensor Voltage"
      accuracy_decimals: 2
      unit_of_measurement: "V"

Just picked up a Gravity Analog pH Sensor v2 from DFROBOT. just having a little issue understanding how I calibrate this sensor. I understand that it’s done by Voltage. Does anyone have an example code for the calibration or have I missed something here?

I should add I’m using an esp32

Updated, So I think I have calibrated the sensor using the following code. Does anyone know if it’s possible to add a temperature offset? or whether I need to worry about that?

# Ph Probe     
     # https://esphome.io/components/sensor/adc.html
  - platform: adc
    pin: GPIO35
    id: ph
    name: "pH Sensor"
    update_interval: 30s
    unit_of_measurement: pH
    # https://esphome.io/components/sensor/index.html#sensor-filters
    filters:
      - median:
          window_size: 7
          send_every: 4
          send_first_at: 3
      # Measured voltage -> Actual pH (buffer solution)
      - calibrate_linear:
          - 1.55 -> 7.0
          - 2.09 -> 4.0
    attenuation: auto

  - platform: adc
    pin: GPIO35
    name: "Flex 0"
    update_interval: 1s
    attenuation: auto

@pmiles156 My custom component exposes calibration services to Home Assistant in the latest version.

See here for the built in ADC version: Custom sensor component for DFRobot Ph sensor · GitHub

And here for the ADS1115 ADC version:

That’s great and from what I understand this will use the temp sensor to calibrate the sensor.

What if I wanted to use the same temp sensor to display the temp information in home assistant ?

I have also a TDS sensor running from this esp.

Will this effect it?

A TDS will alter the PH values without having an isolator if in the same liquid system. This is the issue I am running into. I am trying to figure out how to control transistors with espHome to turn the TDS sensor on and off. Do you know how to do that?

Good Morning

So I’m just trying to use your new ADC version and I keep getting this error

My esp code looks like this

esphome:
  name: aquarium-ph
  
  includes:
    - custom_dfrobot_ph_sensor.h
  libraries:
    - eeprom
    - onewire
    - DallasTemperature
    - file:///config/esphome/custom/DFRobot_ESP_PH

esp32:
  board: esp32dev
  framework:
    type: arduino
    
# Enable logging
logger:

# Enable Home Assistant API
api:
  encryption:
    key: "oDZ4E4IAk2HsGxMOxd69j+KsfkqbZBLPmZqff8="

ota:
  password: "9e844fecabc82164026c11f32c2a"

wifi:
  ssid: !secret WiFi_SSID
  password: !secret WiFi_Password
  domain: ".mrmiles.internal"

  # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: "Aquarium-Ph Fallback Hotspot"
    password: "8wxY4Bj32AR5"

captive_portal:
    
    
web_server:
  port: 80
  auth:
    username: admin
    password: admin
    
sensor:
  - platform: custom
    lambda: |-
      auto my_sensor = new CustomDFRobotPhSensor();
      App.register_component(my_sensor);
      return {my_sensor};
  
    sensors:
      name: "DFRobot Ph Sensor"
      accuracy_decimals: 2
      unit_of_measurement: " "

What am I doing wrong, I have copied the files and folders into their correct place.

Your sensors section in the esp code should look like this:

sensor:
  - platform: custom
    lambda: |-
      auto my_sensor = new CustomDFRobotPhSensor(30000);
      App.register_component(my_sensor);
      return {my_sensor->ph_sensor, my_sensor->temperature_sensor, my_sensor->voltage_sensor};
  
    sensors:
    - name: "pH Sensor"
      accuracy_decimals: 2
      unit_of_measurement: " "

    - name: "Water Temperature Sensor"
      accuracy_decimals: 2
      unit_of_measurement: "°F"
      filters:
      - lambda: return x * (9.0/5.0) + 32.0;

    - name: "pH Sensor Voltage"
      accuracy_decimals: 2
      unit_of_measurement: "V"

What am I doing wrong now :slight_smile:

I think you may need to update the library to the one with the ADC code.

So replace your libraries entry with:

    - file:///config/esphome/custom/DFRobot_ESP_PH_WITH_ADC

and make sure this directory exists with this code: https://github.com/GreenPonik/DFRobot_ESP_PH_WITH_ADC_BY_GREENPONIK

Set the update time to, I believe, zero. It’s been a while and I can’t find the how to set a sensor to never update. You can then use the update call to take readings when you want.

Still can’t get this working
I have downloaded the code from https://github.com/GreenPonik/DFRobot_ESP_PH_WITH_ADC_BY_GREENPONIK
to \config\config\esphome\custom\DFRobot_ESP_PH_WITH_ADC

I have downloaded your custom code from
Custom sensor component for DFRobot Ph sensor · GitHub
to \config\config\esphome\custom_dfrobot_ph_sensor.h

And I’m still getting an error

You are using the wrong version of my custom code. That file is for the built in ADC. You want the ADS1115 version here: Custom dfrobot ph sensor with ads1115 for esphome · GitHub

Does this require an additional ADS115 board tho?

I just have the gravity PH Sensor V2
https://uk.farnell.com/dfrobot/sen0161-v2/analogue-ph-sensor-meter-kit-v2/dp/3769978?gclid=CjwKCAjw6raYBhB7EiwABge5KnqitQqGX4pXC_NGAv4lsYFXvwoCgnFMf5maW9JZoNlDvsR7j_OHmBoC6JQQAvD_BwE&mckv=_dc|pcrid||plid||kword||match||slid||product|3769978|pgrid||ptaid|&CMP=KNC-GUK-GEN-SHOPPING-SMART-PMAX-Medium_ROAS-Test915&gross_price=true

Do I need anything else?

No the ADS1115 is not required. I have posted 2 different versions of custom code that use 2 different libraries from GreenPonik based on whether or not you are using the ADS1115.

Good Evening
I would like to say that I have solved this, but I’m running into issues all the time. would you mind writing this in a dummy guide for me, please?

I have a Gravity Sensor v2 with no ADS1115 module.

my esp config looks like this

esphome:
  name: aquarium-ph
  
  includes:
    - custom_dfrobot_ph_sensor.h
  libraries:
    - eeprom
    - onewire
    - DallasTemperature
    - file:///config/esphome/custom/DFRobot_ESP_PH_WITH_ADC

esp32:
  board: esp32dev
  framework:
    type: arduino
    
# Enable logging
logger:

# Enable Home Assistant API
api:
  encryption:
    key: "oDZ4E4IAk2HsGxMOxdsfkqbZBLPmZqskqQqff8="

ota:
  password: "9e844fecabc82d0d41f32c2a"

wifi:
  ssid: !secret WiFi_SSID
  password: !secret WiFi_Password

  # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: "Aquarium-Ph Fallback Hotspot"
    password: "8wxY4Bj32AR5"

captive_portal:
    
    
web_server:
  port: 80
  auth:
    username: admin
    password: admin
    
sensor:
  - platform: custom
    lambda: |-
      auto my_sensor = new CustomDFRobotPhSensor(30000);
      App.register_component(my_sensor);
      return {my_sensor->ph_sensor, my_sensor->temperature_sensor, my_sensor->voltage_sensor};
  
    sensors:
    - name: "pH Sensor"
      accuracy_decimals: 2
      unit_of_measurement: " "

    - name: "Water Temperature Sensor"
      accuracy_decimals: 2
      unit_of_measurement: "°F"
      filters:
      - lambda: return x * (9.0/5.0) + 32.0;

    - name: "pH Sensor Voltage"
      accuracy_decimals: 2
      unit_of_measurement: "V"

What files have I got to download from where and to where? :slight_smile:

Hi @nkgilley ,

This looks awesome (nothing new vs what has been said already but I wanted to join the crew in thanking you!.

I have one question related to the custom component:

  1. I do not have a Dallas sensor, so I was thinking to just remove the Dallas bit from your component and plug my temperature sensor from HomeAssistant. To do so, how should I adjust this bit of code?
	//add your code here to get the temperature from your temperature sensor
	sensors.requestTemperatures();
	return sensors.getTempCByIndex(0);

Thanks

The ADC quality varies significantly on which microcontroller you are using. If you use an ESP32 then I would highly recommend the use of an ADS1115. You will get much better resolution and accuracy. If you are interested in why have a look at #340 How good are the ADCs inside Arduinos, ESP8266, and ESP32? And external ADCs (ADS1115) - YouTube. The ADS1115 requires I2C but if you have more than one analog sensor you will break even regarding pin count.

If you don’t use an ADS1115, then you should note that the ADC on the ESP32 is not linear. Using the calibrate linear filter in ESPhome doesn’t work as well as it might. I calculated the linear fit using the simple line equation y = mx + b as I wanted to be able to change the values using code and I couldn’t work out a way to use global variables in the sensor filter.

globals:
   - id: ph4raw  # raw v value from probe using ph 4 calibration solution.
     type: float
     restore_value: yes
     initial_value: '2.047'
   - id: ph7raw # raw v value from probe using ph 7 calibration solution.
     type: float
     restore_value: yes
     initial_value: '1.51'
   - id: phm  # calculated line slope
     type: float
     restore_value: yes
     initial_value: '-0.14667'
   - id: phb  # calculated line intersect
     type: float
     restore_value: yes
     initial_value : '2.54'

ads1115:
  - address: 0x48 # default

i2c:
  sda: 21 # default pins on the esp32. You can change to suit
  scl: 22

- platform: ads1115
    internal: True
    multiplexer: 'A3_GND'
    gain: 2.048
    name: 'ADS1115 PH'
    id: ADS1115_PH
    update_interval: 360s # default 60s
    filters:
      - median:
          window_size: 7
          send_every: 4
          send_first_at: 3

  # Use two points to calculate the equation of the line fitting your ph measurements. Note
  # that if you interested in higher ph meaurements (>7) then calibrating using a ph 10 solution
  # and a ph 7 solution will give you better results than using the ph 4 solution. You can easily make
  # your own ph 10 solution if you have a scale with > 0.1 gram accuracy. Look on line.
  # From the current raw ph measure, calculate the calibrated ph using the line
  # equation phraw = phm*X + phb, X = (phraw - phb) / phm
  # phm is the slope of the line
  # phb is the line intersect
  - platform: template
    name: "Calibrated PH"
    id: ph
    unit_of_measurement: "pH"
    accuracy_decimals: 2
    state_class: measurement
    icon: mdi:ph
    update_interval: 360s
    lambda: |-   
       id(phm) = (id(ph7raw) - id(ph4raw)) / 3;
       id(phb) = (id(ph4raw) - (id(phm) * 4));
       return((id(ADS1115_PH).state - id(phb)) / id(phm));


I’m getting the same issue as @pmiles156 :

My config:

esphome:
  name: trialphprobe
  includes:
  - custom_dfrobot_ph_sensor.h
  libraries:
    - eeprom
    - onewire
    - DallasTemperature
    - /config/esphome/custom/DFRobot_ESP_PH_BY_GREENPONIK


esp32:
  board: esp32dev
  framework:
    type: arduino

# Enable logging
logger:

# Enable Home Assistant API
api:
  encryption:
    key: "xxxxx="

ota:
  password: "xxxxx"

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

  # Enable fallback hotspot (captive portal) in case wifi connection fails
  ap:
    ssid: "Trialphprobe Fallback Hotspot"
    password: "WumH7aDgCvxk"

captive_portal:
    
sensor:
  - platform: custom
    lambda: |-
      auto my_sensor = new CustomDFRobotPhSensor(30000);
      App.register_component(my_sensor);
      return {my_sensor->ph_sensor, my_sensor->temperature_sensor, my_sensor->voltage_sensor};
  
    sensors:
    - name: "pH Sensor"
      accuracy_decimals: 2
      unit_of_measurement: " "

    - name: "Water Temperature Sensor"
      accuracy_decimals: 2
      unit_of_measurement: "°F"
      filters:
      - lambda: return x * (9.0/5.0) + 32.0;

    - name: "pH Sensor Voltage"
      accuracy_decimals: 2
      unit_of_measurement: "V"

And I’ve got the Gravity pH Meter Pro v2 hooked up to pin 13 on my ESP32.
This is the setup of my directory structure too, ensuring that things should be in the right place:


Should be… I think :sweat_smile:

I don’t have any ADC, just the probe straight to an ESP32.

Any assistance with where I’ve gone wrong would be much appreciated, thanks.

Hello. is there a possibility in HA to add a button or something like that that triggers calibration?

hi. how to enter calibration mode? via serial Arduino monitor does not work. follows the dfrobot Wiki. please save me