本來沒打算要掛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);
}
}
}