pH Sensor
The pH sensor provides water quality measurement critical for environmental monitoring and anomaly detection.
Hardware Specifications
Parameter | Value |
|---|---|
Model | DFRobot SEN0161 (Analog pH meter) |
Interface | Analog ADC |
Reference Voltage | 3.3V or 5.0V (configurable) |
Output Range | 0-5V analog |
Measurement Range | 0-14 pH units |
Accuracy | ±0.1 pH @ 25°C |
Sample Rate | Configurable (40 samples for averaging) |
Calibration Model
The sensor uses linear voltage-to-pH conversion:
pH = (Voltage / Reference_Voltage) × Slope + Offset
Default Parameters for SEN0161 @ 25°C:
- Slope: 3.5
- Offset: Variable (user calibration)
Data Structure
typedef struct {
// Raw ADC Reading
uint16_t raw_value; // Raw ADC value
// Calculated Values
float voltage; // Converted voltage (0-5V)
float ph_value; // Calculated pH (0-14)
float reference_voltage; // ADC reference (typically 3.3V or 5.0V)
// Calibration Parameters
ph_calibration_t calibration; // { offset: float, slope: float }
// Averaging Buffer (Noise Filtering)
uint16_t sample_buffer[40]; // Last 40 samples
uint8_t sample_index; // Current position in buffer
uint8_t samples_collected; // Total samples collected (0-40)
} ph_sensor_t;
Initialization & Usage
Initialize pH Sensor
ph_sensor_t ph_sensor;
ph_sensor_init(&ph_sensor, 3.3f); // 3.3V reference voltage
Poll pH Sensor
result_t ph_result = poll_ph_sensor(&ph_sensor);
if (ph_result == RESULT_OK) {
float ph_value = ph_sensor.ph_value;
float voltage = ph_sensor.voltage;
}
Manual Sample Addition
// For manual sampling at regular intervals
uint16_t adc_reading = 2048; // Example ADC value
ph_sensor_add_sample(&ph_sensor, adc_reading);
Validation
result_t validate_ph_value(float ph_value);
// Returns RESULT_OK if 0 <= ph_value <= 14
// Returns RESULT_ERR_INVALID_DATA otherwise
Sample Averaging Strategy
Parameter | Value |
|---|---|
Sample Buffer Size | 40 samples |
Method | Circular buffer moving average |
Purpose | Noise filtering and stable readings |
Typical Update Latency | 40ms-800ms |
Averaging Algorithm
1. ADC sample added to circular buffer
2. All 40 samples averaged together
3. Averaged value converted to voltage
4. Voltage converted to pH via calibration
Two-Point Calibration Procedure
Step 1: Neutral Point (pH 7.0)
1. Immerse electrode in pH 7.0 buffer solution
2. Wait for stable reading (~2 minutes)
3. Record voltage: V_neutral
4. Calculate offset adjustment
Step 2: Slope Calibration (pH 4.0 or 10.0)
1. Immerse electrode in second known pH solution
2. Wait for stable reading
3. Record voltage: V_reference
4. Calculate slope from two points:
slope = (pH_reference - 7.0) / (V_reference - V_neutral)
Protobuf Message Format
message SensorBoardPHInfo {
float ph_value;
float voltage;
SensorState state;
PHErrorCode error_code;
}
enum PHErrorCode {
PH_NO_ERROR = 0;
PH_COMMUNICATION_FAILURE = 1;
PH_INVALID_DATA = 2;
}
Error Handling
if (ph_result == RESULT_ERR_UNIMPLEMENTED) {
// Hardware not connected
diagnostics.ph_sensor.state = SensorState_SENSOR_IDLE;
diagnostics.ph_sensor.error_code = PHErrorCode_PH_COMMUNICATION_FAILURE;
} else if (ph_result == RESULT_OK) {
if (validate_ph_value(ph_sensor.ph_value) == RESULT_OK) {
diagnostics.ph_sensor.state = SensorState_SENSOR_OPERATING;
diagnostics.ph_sensor.error_code = PHErrorCode_PH_NO_ERROR;
} else {
// Invalid data from sensor (out of 0-14 range)
diagnostics.ph_sensor.state = SensorState_SENSOR_ERROR;
diagnostics.ph_sensor.error_code = PHErrorCode_PH_INVALID_DATA;
}
}
Integration Notes
- Single sensor instance in main application
- Updates transmitted to network at main loop interval (5 seconds default)
- Temperature compensation not currently implemented (assumes ~25°C)
- Sample averaging reduces noise but introduces ~40ms latency per update
- Electrode response time: ~100-300ms depending on pH change magnitude