pH传感器模组(水质监测)

元器件
传感器
库存 30

介绍

用于水质监测节点的pH传感器模组,基于模拟电压输出型pH探头+信号调理板。支持三点标定(pH 4.00/6.86/9.18缓冲液),通过ESP32的ADC读取电压并线性拟合出pH值。配套Python Qt标定工具和C++固件驱动,适用于水环境监测、水产养殖、污水处理等场景。

规格参数

参数
精度±0.1 pH (标定后)
分辨率0.01 pH
ADC分辨率12-bit (ESP32)
供电电压3.3V / 5V
响应时间<30s (达到稳定读数)
工作温度0 ~ 60°C
拟合公式pH = k·V + b (线性)
探头接口BNC
标定方式三点标定 (pH 4.00/6.86/9.18)
测量范围0.00 ~ 14.00 pH
输出信号模拟电压 (mV级,经信号调理板放大后送入ADC)
通信接口GPIO (ADC)
配套工具Python Qt 三点标定工具 (ph_calib)
单片机平台ESP32-S3 (Arduino框架)

代码例程

pH传感器模组代码例程 — ESP32 Arduino.md
# pH 传感器模组 — 代码例程 (ESP32 Arduino)

## 1. GPIO 初始化

```cpp
#include <Arduino.h>

// pH 探头 ADC 引脚(可根据实际接线修改)
#define PH_ADC_PIN  4

// 标定参数:每块板不同,由 ph_calib 工具生成后填入
#ifndef PH_V686
#define PH_V686  1.3699f   // pH=6.86 缓冲液对应电压 (V)
#endif
#ifndef PH_V918
#define PH_V918  1.1168f   // pH=9.18 缓冲液对应电压 (V)
#endif

void setup() {
  Serial.begin(115200);

  // ADC 初始化:12-bit 分辨率,11dB 衰减(~3.3V 满量程)
  analogReadResolution(12);
  analogSetPinAttenuation(PH_ADC_PIN, ADC_11db);

  Serial.println("pH Sensor ready.");
  Serial.printf("PH_V686=%.4f  PH_V918=%.4f\n", PH_V686, PH_V918);
}
```

---

## 2. 驱动函数

### 2.1 读取 pH 探头电压(多次采样取均值)

```cpp
/**
 * @brief  读取 pH 探头输出电压 (V)
 * @note   连续采样 N 次取均值,降低噪声
 * @return 电压值,单位 V
 */
static float read_ph_voltage() {
  const int N = 20;                // 采样次数
  uint32_t sum_mv = 0;
  for (int i = 0; i < N; ++i) {
    sum_mv += analogReadMilliVolts(PH_ADC_PIN);
    delay(2);
  }
  return (sum_mv / (float)N) / 1000.0f;
}
```

### 2.2 电压转 pH(两点线性插值)

```cpp
/**
 * @brief  电压转 pH 值
 * @param  v  探头电压 (V)
 * @return pH 值
 * @note   线性模型: pH = k·v + b
 *         其中 k = (6.86-9.18)/(V686-V918)
 *              b = 6.86 - k*V686
 */
static float voltage_to_ph(float v) {
  constexpr float k = (6.86f - 9.18f) / (PH_V686 - PH_V918);
  return 6.86f + k * (v - PH_V686);
}
```

### 2.3 综合读取(电压 + pH 一起返回)

```cpp
/**
 * @brief  读取 pH 探头并返回电压和 pH
 * @param  v_out   [out] 原始电压 (V)
 * @return pH 值 (0.00 ~ 14.00)
 */
static float read_ph(float* v_out = nullptr) {
  float v = read_ph_voltage();
  if (v_out) *v_out = v;
  float ph = voltage_to_ph(v);
  // 钳位到合理范围
  if (ph < 0.0f)  ph = 0.0f;
  if (ph > 14.0f) ph = 14.0f;
  return ph;
}
```

---

## 3. 完整示例 — 每 2 秒打印一次 pH

```cpp
#include <Arduino.h>

// ==================== 引脚 & 标定参数 ====================
#define PH_ADC_PIN  4

#ifndef PH_V686
#define PH_V686  1.3699f
#endif
#ifndef PH_V918
#define PH_V918  1.1168f
#endif

// ==================== 驱动函数 ====================

static float read_ph_voltage() {
  const int N = 20;
  uint32_t sum_mv = 0;
  for (int i = 0; i < N; ++i) {
    sum_mv += analogReadMilliVolts(PH_ADC_PIN);
    delay(2);
  }
  return (sum_mv / (float)N) / 1000.0f;
}

static float voltage_to_ph(float v) {
  constexpr float k = (6.86f - 9.18f) / (PH_V686 - PH_V918);
  return 6.86f + k * (v - PH_V686);
}

static float read_ph(float* v_out = nullptr) {
  float v = read_ph_voltage();
  if (v_out) *v_out = v;
  float ph = voltage_to_ph(v);
  if (ph < 0.0f)  ph = 0.0f;
  if (ph > 14.0f) ph = 14.0f;
  return ph;
}

// ==================== setup & loop ====================

void setup() {
  Serial.begin(115200);
  delay(300);

  analogReadResolution(12);
  analogSetPinAttenuation(PH_ADC_PIN, ADC_11db);

  Serial.println("===== pH Sensor Demo =====");
  Serial.printf("PH_ADC_PIN = GPIO%d\n", PH_ADC_PIN);
  Serial.printf("PH_V686    = %.4f V\n", PH_V686);
  Serial.printf("PH_V918    = %.4f V\n", PH_V918);
  Serial.println("==========================");
}

void loop() {
  float voltage = 0.0f;
  float ph = read_ph(&voltage);

  Serial.printf("[pH] voltage=%.4f V  =>  pH=%.2f\n", voltage, ph);
  delay(2000);
}
```

**预期输出**(串口 115200):

```
===== pH Sensor Demo =====
PH_ADC_PIN = GPIO4
PH_V686    = 1.3699 V
PH_V918    = 1.1168 V
==========================
[pH] voltage=1.2345 V  =>  pH=7.12
[pH] voltage=1.2342 V  =>  pH=7.13
...
```

---

## 4. 标定模式固件(calib)

烧录此固件后,配合 Python `ph_calib` 工具完成三点标定:

```cpp
#include <Arduino.h>
#define PH_ADC_PIN 4

void setup() {
  Serial.begin(115200);
  analogReadResolution(12);
  analogSetPinAttenuation(PH_ADC_PIN, ADC_11db);
  Serial.println("[PH_CAL] CALIB MODE READY");
}

void loop() {
  const int N = 16;
  uint32_t sum_mv = 0;
  for (int i = 0; i < N; ++i) {
    sum_mv += analogReadMilliVolts(PH_ADC_PIN);
    delay(5);
  }
  float v = (sum_mv / (float)N) / 1000.0f;
  Serial.printf("[PH_CAL] v=%.4f\n", v);
  delay(100);  // ~5 Hz 输出
}
```

输出格式:`[PH_CAL] v=1.2345`,供标定工具正则匹配。

---

## 5. 在 platformio.ini 中覆盖标定参数

```ini
[env:my_node]
build_flags =
  -DPH_V686=1.3699f
  -DPH_V918=1.1168f
```

> ⚠️ 每块板的参数不同,务必用标定工具测量后填入!

参考资料

暂无参考文献