#include <NewPing.h>
//SCL pin to A5
//SDA pin to A4
#include <SPI.h>
#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SH110X.h>
#include <Fonts/FreeSans9pt7b.h>
#define OLED_WIDTH 128
#define OLED_HEIGHT 64
#define OLED_ADDR 0x3C
#define SCREEN_WIDTH 128 // OLED display width, in pixels
#define SCREEN_HEIGHT 64 // OLED display height, in pixels
#define OLED_RESET -1 // QT-PY / XIAO
Adafruit_SH1106G display = Adafruit_SH1106G(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
#define TRIGGER_PIN 2
#define ECHO_PIN 3
#define MAX_DISTANCE 160 // Maximum distance we want to measure (in centimeters) 60 inches.
int sensorMax = 48;
int sensorMin = 0;
#define SPEAKER_PIN 6
const long updateScreenInterval = 1000; //1 sec
//const long interval = 300000; //5 min
const long interval = 1000; //5 min
unsigned long previousScreenMillis = 0;
unsigned long previousMillis = 0;
int waterDroppingCount = 0;
int previousDistance = 0;
int currentDistance = 0;
NewPing sonar(TRIGGER_PIN, ECHO_PIN, MAX_DISTANCE);
void setup() {
pinMode(SPEAKER_PIN, OUTPUT);
display.begin(OLED_ADDR, true); // Address 0x3C default
display.clearDisplay();
Serial.begin(9600);
display.setFont(&FreeSans9pt7b);
display.setRotation(1);
display.setTextSize(1.5);
display.setTextColor(SH110X_WHITE);
display.setCursor(10, 40);
display.println("Water");
display.setCursor(3, 60);
display.println("Monitor");
display.setCursor(13, 80);
display.println("2000");
display.display();
delay(2000);
display.clearDisplay();
display.display();
}
void loop() {
unsigned long currentMillis = millis();
if (currentMillis - previousScreenMillis >= updateScreenInterval) {
previousScreenMillis = currentMillis;
//update screen every second
getDistanceReading();
updateScreen();
}
if (currentMillis - previousMillis >= interval) {
previousMillis = currentMillis;
//compare tank level every 5 minutes, longer distance means less water
if (previousDistance < currentDistance)
{
Serial.println("Up");
waterDroppingCount++;
}
else {
//if level stayed the same, clear the count
Serial.println("Down");
waterDroppingCount = 0;
}
//play alert if tank continually falls
if (waterDroppingCount > 3)
{
playAlert();
}
previousDistance = currentDistance;
}
}
void getDistanceReading()
{
currentDistance = sonar.ping_cm();
}
void updateScreen()
{
display.clearDisplay();
//current rankinbg - 1-10
Serial.println(getRanking());
display.setTextSize(4);
display.setCursor(15, 50);
display.println(getRanking());
display.setTextSize(1);
display.setCursor(0, 80);
display.println(String(getGallons()) + " gal");
Serial.println(String(currentDistance) + " distance");
display.setCursor(0, 100);
display.println(String(currentDistance) + " - " + String(waterDroppingCount));
display.setCursor(0, 120);
display.println(previousDistance);
display.display();
}
int getRanking()
{
return map(currentDistance, sensorMin, sensorMax, 9, 0);
}
int getGallons()
{
return map(sensorMax - currentDistance, sensorMin, sensorMax, 0, 275);
}
void playAlert()
{
display.println("tone");
stone(SPEAKER_PIN, 900, 300);
delay(1000);
stone(SPEAKER_PIN, 900, 300);
}
void stone(int pin, uint16_t freq, uint16_t duration)
{
pinMode(pin, OUTPUT);
uint32_t period = 500000UL / freq; // half cycle period in microseconds
uint32_t cycles = duration * 1000UL / period; // number of half cycles
auto t0 = micros();
while (cycles--)
{
digitalWrite(pin, !digitalRead(pin)); // toggle pin
while (micros() - t0 < period) {}
t0 += period;
}
digitalWrite(pin, LOW);
}