#include <Wire.h>
#include <OneWire.h>
#include <DallasTemperature.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
// -------------------------------
// SHIYANK PIN CONFIGURATION
// -------------------------------
const int PH_PIN = 34;
const int TDS_PIN = 35;
const int TURBIDITY_PIN = 32;
const int TEMP_PIN = 4;
const int FLOAT_PIN = 27;
// OLED configuration
#define SCREEN_WIDTH 128
#define SCREEN_HEIGHT 64
#define OLED_ADDRESS 0x3C
Adafruit_SSD1306 display(
SCREEN_WIDTH,
SCREEN_HEIGHT,
&Wire,
-1
);
// Temperature sensor
OneWire oneWire(TEMP_PIN);
DallasTemperature tempSensor(&oneWire);
// -------------------------------
// SAMPLE STATES
// -------------------------------
enum SampleState {
NO_SAMPLE,
SETTLING,
MEASURING
};
SampleState sampleState = NO_SAMPLE;
unsigned long sampleStartTime = 0;
unsigned long lastReadingTime = 0;
const unsigned long SETTLING_TIME = 5000;
const unsigned long READING_INTERVAL = 2000;
// Button debounce
bool lastButtonReading = HIGH;
bool stableButtonState = HIGH;
unsigned long lastDebounceTime = 0;
const unsigned long DEBOUNCE_DELAY = 50;
// -------------------------------
// ANALOGUE SENSOR READING
// -------------------------------
float readSensorVoltage(int pin) {
const int numberOfSamples = 20;
long total = 0;
for (int i = 0; i < numberOfSamples; i++) {
total += analogRead(pin);
delay(5);
}
float average = total / (float)numberOfSamples;
// Convert 12-bit ADC reading into an
// approximate voltage for simulation.
return (average / 4095.0) * 3.3;
}
// -------------------------------
// SAMPLE STATE DISPLAY
// -------------------------------
String getStateName() {
switch (sampleState) {
case NO_SAMPLE:
return "NO SAMPLE";
case SETTLING:
return "SETTLING";
case MEASURING:
return "MEASURING";
}
return "UNKNOWN";
}
void updateDisplay(
float phVoltage,
float tdsVoltage,
float turbidityVoltage,
float temperature
) {
display.clearDisplay();
display.setTextSize(1);
display.setTextColor(SSD1306_WHITE);
display.setCursor(0, 0);
display.println("SHIYANK WATER MONITOR");
display.println("---------------------");
display.print("Status: ");
display.println(getStateName());
if (sampleState == MEASURING) {
display.print("pH voltage: ");
display.print(phVoltage, 2);
display.println(" V");
display.print("TDS voltage: ");
display.print(tdsVoltage, 2);
display.println(" V");
display.print("Turbidity: ");
display.print(turbidityVoltage, 2);
display.println(" V");
display.print("Temperature: ");
if (temperature > -100) {
display.print(temperature, 1);
display.println(" C");
} else {
display.println("ERROR");
}
} else {
display.println();
display.println("Waiting for sample...");
}
display.display();
}
// -------------------------------
// SETUP
// -------------------------------
void setup() {
Serial.begin(115200);
pinMode(FLOAT_PIN, INPUT_PULLUP);
analogReadResolution(12);
tempSensor.begin();
Wire.begin(21, 22);
if (!display.begin(
SSD1306_SWITCHCAPVCC,
OLED_ADDRESS
)) {
Serial.println("OLED initialisation failed!");
} else {
Serial.println("OLED initialised.");
}
Serial.println();
Serial.println("==========================");
Serial.println(" SHIYANK INITIALISED");
Serial.println("==========================");
Serial.println("Waiting for water sample...");
updateDisplay(0, 0, 0, -127);
}
// -------------------------------
// LOOP
// -------------------------------
void loop() {
// Read pushbutton
bool buttonReading = digitalRead(FLOAT_PIN);
// Debounce the button
if (buttonReading != lastButtonReading) {
lastDebounceTime = millis();
}
if ((millis() - lastDebounceTime) > DEBOUNCE_DELAY) {
if (buttonReading != stableButtonState) {
stableButtonState = buttonReading;
// Button pressed = sample present
if (stableButtonState == LOW &&
sampleState == NO_SAMPLE) {
sampleState = SETTLING;
sampleStartTime = millis();
Serial.println();
Serial.println("Sample detected!");
Serial.println("State: SETTLING");
updateDisplay(0, 0, 0, -127);
}
// Button released = sample removed
else if (stableButtonState == HIGH &&
sampleState != NO_SAMPLE) {
sampleState = NO_SAMPLE;
Serial.println();
Serial.println("Sample removed.");
Serial.println("Old readings invalidated.");
Serial.println("State: NO SAMPLE");
updateDisplay(0, 0, 0, -127);
}
}
}
lastButtonReading = buttonReading;
// Wait for sample to settle
if (sampleState == SETTLING) {
if (millis() - sampleStartTime >= SETTLING_TIME) {
sampleState = MEASURING;
Serial.println("State: MEASURING");
}
}
// Read sensors
if (sampleState == MEASURING &&
millis() - lastReadingTime >= READING_INTERVAL) {
lastReadingTime = millis();
float phVoltage = readSensorVoltage(PH_PIN);
float tdsVoltage = readSensorVoltage(TDS_PIN);
float turbidityVoltage = readSensorVoltage(TURBIDITY_PIN);
tempSensor.requestTemperatures();
float temperature =
tempSensor.getTempCByIndex(0);
Serial.println();
Serial.println("====== SHIYANK READINGS ======");
Serial.print("pH sensor voltage: ");
Serial.print(phVoltage, 3);
Serial.println(" V");
Serial.print("TDS sensor voltage: ");
Serial.print(tdsVoltage, 3);
Serial.println(" V");
Serial.print("Turbidity sensor voltage: ");
Serial.print(turbidityVoltage, 3);
Serial.println(" V");
Serial.print("Water temperature: ");
if (temperature == DEVICE_DISCONNECTED_C) {
Serial.println("SENSOR ERROR");
temperature = -127;
} else {
Serial.print(temperature, 2);
Serial.println(" C");
}
Serial.println("Sample status: VALID");
Serial.println("==============================");
updateDisplay(
phVoltage,
tdsVoltage,
turbidityVoltage,
temperature
);
}
delay(10);
}
Loading
esp32-devkit-c-v4
esp32-devkit-c-v4
Loading
ssd1306
ssd1306