可用於ESP32上經濟實惠的pH量測模組PH-4502C

本來沒打算要掛pH模組到ESP32上的,因為查到可以用的pH模組實在太貴,但後來在淘寶上看到PH-4502C和一支不可充pH電極的組合只要台幣不到300元,大概一週後就拿到手了。

看規格,這塊模組需要5V輸入電壓(3.3V好像也可以但沒有幫助),接線的部分

  • BNC接頭接上pH電極
  • V+腳位接ESP32上的VIN(通常是5V)
  • G腳位擇一接上ESP32上的GND
  • Po腳位接上ESP32上自選的GPIO(這裡我選34)

其他元件的部分

  • To是溫度補償,攝氏1度約影響0.03的pH值,這裡忽略不計。
  • Do看文件是寫3.3V pH limit trigger,量其電壓不會隨著標準液的不同而改變,實際上用法不明。
  • 靠近BNC接頭的藍色方塊是Boater 3296 W103可變電阻,用一字螺絲起子可以調整電阻值,藉以調整Po輸出電壓的平移,是拿來做硬體校正用的。
  • 另一邊的可變電阻,說明書上是寫PH limit setting,實際調整沒發現Po輸出有什麼變化。

先做硬體校正,硬體校正的目的是要把pH7的電壓讀值調到中心點2.5V。先將BNC接頭短路,再把V+與GND腳位接好即可上電,拿三用電錶量測Po腳位到G腳位的電位差,用一字螺絲起子調整靠近BNC接頭的可變電阻,讓三用電表的讀值接近於2.5V。

接著使用pH4、pH7與pH10的標準液做軟體校正,目的是要取得pH4、pH7與pH10在ESP32 ADC上的讀值並與其對應的pH值做線性回歸,然後將得到電壓對pH值的校正(斜率與截距)寫入程式中。

實際接上ESP32前,保險起見我拿三用電錶測量pH4標準液的電壓值(pH愈小電壓愈高),讀值是3.28V很接近ESP32 ADC的上限3.3V。雖然魚缸環境很難到pH4這麼酸,沒有燒毀ADC的風險,但為了做校正我還是把pH7中心點電壓往下微調0.1V左右。

在Arduino上編寫以下程式碼並上傳ESP32,這段程式碼的目的是每秒鐘取得一個電壓值。

#define PH_METER_PIN 34
#define VREF 3.3

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

void loop() 
{
  int pHReading = analogRead(PH_METER_PIN);
  float pHVoltage = pHReading * (float)VREF / 4095;
  Serial.println(pHVoltage);
  delay(1000);
}

將pH電極置入pH4、pH7與pH10的標準液並記錄其電壓,可以得到斜率跟截距分別為-4.6322和18.587。

最後可以仿照TDS的計算方式來寫pH讀值的程式碼,如下

#define pH_SENSOR_PIN 34 // 定義GPIO腳位為GPIO34
#define VREF 3.3 // ESP32輸入電壓為3.3V
#define SCOUNT 30 // 取樣數
int analogBuffer[SCOUNT];
int analogBufferIndex = 0;
float averageVoltage = 0;
float pHValue = 0;
float pHslope = -4.6322;
float pHintercept = 18.587;
 
void setup()
{
  Serial.begin(115200);
  pinMode(pH_SENSOR_PIN, INPUT);
}
 
float lastpHValue = -1; // 定義最後的pH值為無效(-1)
 
void loop()
{
  // pH取樣
  static unsigned long analogSampleTimepoint = 0;
  if(millis() - analogSampleTimepoint > 40)
  {
    analogSampleTimepoint = millis();
    analogBuffer[analogBufferIndex] = analogRead(pH_SENSOR_PIN);
    analogBufferIndex++;
    if(analogBufferIndex == SCOUNT)
    { 
      analogBufferIndex = 0;
    }
  }   
   
  // pH計算
  static unsigned long printTimepoint = 0;
  if(millis() - printTimepoint > 800)
  {
    printTimepoint = millis();
    float sum = 0;
    for(int i = 0; i < SCOUNT; i++)
    {
      sum += analogBuffer[i];
    }
    averageVoltage = (sum / SCOUNT) * (float)VREF / 4095; // 轉換為電壓值,ESP32的ADC解析度是12位(4095)。
 
    pHValue = averageVoltage * pHslope + pHintercept;
     
    if (pHValue != lastpHValue) // 如果pH數值有更新,才會將結果Print出來。
    {
      lastpHValue = pHValue;
      Serial.print("pH Value: ");
      Serial.println(pHValue, 2);
    }
  }
}

發佈留言

發佈留言必須填寫的電子郵件地址不會公開。 必填欄位標示為 *

返回頂端