pH ORP DS18B20 Circuit
Table
| Sensor | Best Interface | Why it matches |
|---|---|---|
| EC / TDS / conductivity probe | Extra analog front-end + ADS1115 or separate IC | Common companion to pH/ORP for water quality. Needs AC excitation, so it is more complex than pH/ORP. |
| Dissolved Oxygen (DO) probe | Analog front-end + ADC | Useful for water quality. Probe type matters: galvanic/polarographic/optical. Analog DO needs careful conditioning. |
| Turbidity sensor | Analog or digital module | Easier add-on; can feed ESP32 ADC or ADS1115 if a channel is free. |
| Water temperature sensor, second DS18B20 | Same 1-Wire DQ bus | Very easy. Multiple DS18B20 sensors can share the same DQ line. |
| Water level / float switch | Digital GPIO | Simple safety/status input. Needs an extra J2 pin or separate connector. |
| Leak detector / wet contact sensor | Digital/analog GPIO | Useful for enclosure or tank monitoring. |
| Pressure sensor | I2C or analog | Useful if measuring pipe/tank pressure. Prefer I2C 3.3V sensors. |
| Flow sensor | Digital pulse GPIO | Useful for dosing/flow monitoring. Needs one ESP32 GPIO input. |
Table
| J2 Pin | Signal | ESP32 Firmware Function |
|---|---|---|
| 1 | 3.3V | Power supplied by ESP32 board/regulator |
| 2 | GND | Common ground |
| 3 | ADS1115 SDA | I2C SDA GPIO |
| 4 | ADS1115 SCL | I2C SCL GPIO |
| 5 | DS18B20 DQ | 1-Wire GPIO |
Cpp
#include <Wire.h> #include <Adafruit_ADS1X15.h> #include <OneWire.h> #include <DallasTemperature.h> // Set these to the actual ESP32 pins used with J2. static const int PIN_I2C_SDA = 8; static const int PIN_I2C_SCL = 9; static const int PIN_ONEWIRE_DQ = 10; Adafruit_ADS1115 ads; OneWire oneWire(PIN_ONEWIRE_DQ); DallasTemperature ds18b20(&oneWire); float readAdsDiffMv(uint8_t mux) { int16_t raw = 0; if (mux == 0) raw = ads.readADC_Differential_0_1(); // pH else raw = ads.readADC_Differential_2_3(); // ORP // Adjust multiplier to match selected ADS1115 gain. // For GAIN_ONE on Adafruit ADS1X15, scale is commonly 0.125 mV/bit. return raw * 0.125f; } float filteredAdsMv(uint8_t mux) { const int N = 15; float sum = 0; for (int i = 0; i < N; i++) { sum += readAdsDiffMv(mux); delay(20); } return sum / N; } void setup() { Serial.begin(115200); Wire.begin(PIN_I2C_SDA, PIN_I2C_SCL); ds18b20.begin(); if (!ads.begin(0x48)) { Serial.println("ADS1115 not found at 0x48"); while (true) delay(1000); } ads.setGain(GAIN_ONE); // confirm range/noise tradeoff for ORP ads.setDataRate(RATE_ADS1115_128SPS); } void loop() { ds18b20.requestTemperatures(); float tempC = ds18b20.getTempCByIndex(0); float phMv = filteredAdsMv(0); float orpMv = filteredAdsMv(1); // TODO: replace with calibrated conversion. float ph = phMv; // placeholder float orp = orpMv; // mV before calibration offset Serial.printf("T=%.2f C, pH_raw=%.3f mV, ORP_raw=%.3f mV\n", tempC, phMv, orpMv); delay(1000); }
Hardware Interface
Libraries
ADS1115 Settings
Example Arduino-Style Skeleton
Calibration Notes
Simulation-Based Limits