/*
DD 21/01/2024 -- Codey.online (ChatGPT) + DD 02/02/2024 ====>>>> MS Copilot
Librarys: Liquidcrystal, DHT11, Updated with push button library <AbleButtons>
Versie 20240121.075
*/
char versieNr[] = "V 20240121.075"; // create a string with version informational text
#include <Arduino.h>
#include <LiquidCrystal.h>
#include <DHT.h>
#include <AbleButtons.h> // Include the button library
// Definieer het type DHT-sensor (DHT11 of DHT22)
#define DHTTYPE DHT22 // DHT11/DHT22 if needed !
// Identify which buttons you are using...
using Button = AblePulldownButton; // Using basic pull-down or pull-up resistor circuit.
using ButtonList = AblePulldownButtonList; // Using basic pull-down or pull-up button list.
const byte DHT_PIN = 6;
const byte TRIG_PIN = 7; // Ultrasone sensor met gemeenschappelijke Pin voor Trigger en Echo
const byte ECHO_PIN = 7; // Ultrasone sensor met gemeenschappelijke Pin voor Trigger en Echo
// Status LEDs
const byte RED_LED_PIN = 8;
const byte YELLOW_LED_PIN = 9;
const byte GREEN_LED_PIN = 10;
const byte BUTTON_PIN = 13; // Connect button between this pin and ground with a 330 Ohm resistor.
Button btn(BUTTON_PIN); // The button to check.
bool buttonPressedState = false;// Button Presed Status High when pressed, but intially ==>> LOW
const byte relayPin = A1;
const int NUM_MEASUREMENTS = 8; // Aantal opgegeven metingen om de mediaan te kunnen berekenen. Opgelet: Aantal mag niet lager dan 4 liggen!
long readings[NUM_MEASUREMENTS];
byte readingsMin = (NUM_MEASUREMENTS / 2);
byte readingsMax = ((NUM_MEASUREMENTS / 2) + 1);
int index = 0;
long total = 0;
unsigned long lastMeasurementTime = 0;
unsigned long currentTime = millis();
int humidity;
float temperature;
float temperatureCorrection = -0.8; // Correction value to allign DHT11 sensor with real measured temperature value
float calculateMedian;
float mediaan;
float THRESHOLDVALUE = 1.8; // De maximale afwijking op een reeks gemeten waardes mag per meting hooguit tot 1.8cm verschil met de andere waardes zijn
int percentage;
int berekendVolume;
float distance_cm = 0;
float pomphoogte = 35.0; // Standaard pomphoogte in put (centimeters)
float totaleDiepte = 197.0; // Totale diepte van de put, gemeten vanaf de sensor die op 1.97m hoogte hangt
bool relayStatus = false;
byte ControlegetalSensoren = 0;
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
String DHTOKTXT = (" Ultrasone meting MET DHT-sensor, met berekende afstand van sensor tot waterrand = ");
String DHTNOKTXT = (" Ultrasone meting zonder DHT-sensor --->>>> afstand van sensor tot waterrand = ");
// Initialiseer DHT sensor
DHT dht(DHT_PIN, DHTTYPE);
bool checkDHT = false;
bool dhtOK = false;
// Volume empty - lijntje links (ton leeg)
byte customChar0[8] = {
0b10000,
0b10000,
0b10000,
0b10000,
0b10000,
0b10000,
0b10000,
0b11111
};
// Volume empty - lijntje rechts (ton leeg)
byte customChar1[8] = {
0b00001,
0b00001,
0b00001,
0b00001,
0b00001,
0b00001,
0b00001,
0b11111
};
// volume = 2 lijntjes + lijntje links (ton bijna leeg)
byte customChar2[8] = {
0b10000,
0b10000,
0b10000,
0b10000,
0b10000,
0b11111, //*
0b11111, //*
0b11111
};
// volume = 2 lijntjes + lijntje rechts (ton bijna leeg)
byte customChar3[8] = {
0b00001,
0b00001,
0b00001,
0b00001,
0b00001,
0b11111, //*
0b11111, //*
0b11111
};
// volume = 4 lijntjes + lijntje links (ton half vol)
byte customChar4[8] = {
0b10000,
0b10000,
0b10000,
0b11111, //*
0b11111, //*
0b11111, //*
0b11111, //*
0b11111
};
// volume = 4 lijntjes + lijntje rechts (ton half vol)
byte customChar5[8] = {
0b00001,
0b00001,
0b00001,
0b11111, //*
0b11111, //*
0b11111, //*
0b11111, //*
0b11111
};
// volume = 6 lijntjes + lijntje links (ton bijna vol)
byte customChar6[8] = {
0b10000,
0b11111, //*
0b11111, //*
0b11111, //*
0b11111, //*
0b11111, //*
0b11111, //*
0b11111
};
// volume = 6 lijntjes + lijntje rechts (ton bijna vol)
byte customChar7[8] = {
0b00001,
0b11111, //*
0b11111, //*
0b11111, //*
0b11111, //*
0b11111, //*
0b11111, //*
0b11111
};
// volume = 7 lijntjes (ton vol!)
byte customChar8[9] = {
0b11111, //*
0b11111, //*
0b11111, //*
0b11111, //*
0b11111, //*
0b11111, //*
0b11111, //*
0b11111
};
void setup() {
pinMode(TRIG_PIN, OUTPUT);
pinMode(ECHO_PIN, INPUT);
pinMode(GREEN_LED_PIN, OUTPUT);
pinMode(YELLOW_LED_PIN, OUTPUT);
pinMode(RED_LED_PIN, OUTPUT);
pinMode(relayPin, OUTPUT);
// Configureer de pin voor de drukknop als input
pinMode(LED_BUILTIN, OUTPUT); // LED builtin brandt als de drukknop gedrukt wordt ==>> Status gaat dan van LOW to HIGH
Serial.begin(9600);
btn.begin(); // Always begin() each button to initialise it.
dht.begin(); // Initialise DHT sensor
digitalWrite(relayPin, LOW); // RELAY off-stand
ledRoutineOn(); // Alle LEDs ON !
lcd.begin(16, 2);
lcd.print(" " + String(versieNr)); // Print versienummer op LCD display
Serial.println("Versienr.: " + String(versieNr)); // Print versienummer in 'Serial Monitor'
Serial.println(" ");
delay(3000); // Leestijd voor het versienr.
ledRoutineOff(); // Alle LEDs OFF !
}
void loop() {
btn.handle(); // Always handle() each button in a loop to use it.
if (btn.isPressed()) { // Wanneer isPressed() 'waar' is, dan is de knop gedrukt.
buttonPressedState = true; // Zet de knopstatuswaarde op true
digitalWrite(LED_BUILTIN, HIGH);
Serial.println("* Drukknop werd ingedrukt... afstandsberekening in uitvoer... Even geduld aub !!! ");
} else if ((currentTime - lastMeasurementTime >= 120000)) {
buttonPressedState = true; // Behandel de volgende routines alsof de knop ingedrukt werd
Serial.println("* Er zijn inmiddels reeds 2 minuten verstreken... afstandsberekening in uitvoer... Even geduld aub !!! ");
}
if (buttonPressedState == true) {
Serial.println(" ");
dhtUitlezing(); // Haal meetgegevens FHT sensor op
getDistance(); // resultaat ===>>> de berekende mediaan-afstandswaarde wordt opgehaald
// Berekende afstand wordt omgezet in een percentage, (rekening houdend dat het watervolume steeds een minimale 30cm hoog staat (hoogte liggende pomp))
berekendVolume = (totaleDiepte - (mediaan + 0.5)); // 0.5 is coorectiegetal dat uiteindelijk mee in de afronding zal zitten
percentage = map(berekendVolume, 0, totaleDiepte, 0, 100);
Serial.println("* De mediaan van " + String(NUM_MEASUREMENTS) + " afstandmetingen komt op " + String(mediaan) + " cm.");
Serial.println("* Het berekende volume-percentage van de inhoud komt op ongeveer " + String(percentage) + "% ");
Serial.println(" ");
Serial.print("* Dwz dat het watervolume vanaf de bodem van het vat een hoogte bereikt tot ongeveer " + String(berekendVolume) + " cm.");
// Indien het percentage hoger dan 100 zou zijn, wordt het programma onderbroken en wordt de loop() opnieuw doorlopen alsof er een reset plaatsvond.
if (percentage >> 100) {
percentage = 100;
checkDHT = false;
return;
}
checkDHT = true;
}
// Niveaubepaling/relay-test, oa weergegeven met LEDs
if (percentage << 30) {
digitalWrite(GREEN_LED_PIN, LOW);
digitalWrite(YELLOW_LED_PIN, LOW);
digitalWrite(RED_LED_PIN, HIGH);
} else if ((percentage <= 20) or ((relayStatus == true) && (percentage << 30))) { // WATER WORDT BIJGEPOMPT TOT HET NIVEAU WEER HOGER OF GELIJK AAN 30 KOMT!
digitalWrite(relayPin, HIGH);
relayStatus = true;
delay(260);
digitalWrite(GREEN_LED_PIN, LOW);
digitalWrite(YELLOW_LED_PIN, LOW);
// Flashing rode indicatie-LED
digitalWrite(RED_LED_PIN, LOW);
delay(250);
digitalWrite(RED_LED_PIN, HIGH);
} else if (percentage >= 30 && percentage <= 75) { // Waterton medium, laat gele indicatie-LED continue branden
relayStatus = false;
digitalWrite(relayPin, LOW);
digitalWrite(GREEN_LED_PIN, LOW);
digitalWrite(YELLOW_LED_PIN, HIGH);
digitalWrite(RED_LED_PIN, LOW);
}
if ((relayStatus == false) && (percentage >> 75)) { // Waterton bijna vol, laat groene indicatie-LED continue branden
digitalWrite(relayPin, LOW);
digitalWrite(GREEN_LED_PIN, HIGH);
digitalWrite(YELLOW_LED_PIN, LOW);
digitalWrite(RED_LED_PIN, LOW);
Serial.print("*** ! Watertank bijna gevuld ! ***");
Serial.print(" ");
}
if (buttonPressedState == true) {
lcd.setCursor(0, 0);
lcd.println("Volume: ");
lcd.println(String(percentage));
lcd.println(char(37)); // %-teken
lcd.println(" ");
lcd.setCursor(0, 1);
lcd.print("Inhoud: " + String(berekendVolume) + " cm ");
delay(3000);
}
buttonPressedState = false; // Reset de knopstatus weer
digitalWrite(LED_BUILTIN, LOW); // LED_BUILTIN ==>> LOW & Buttonstate will be LOW again, ready for the following button-push
lastMeasurementTime = currentTime;
}
void dhtUitlezing() { // Reading temperature or humidity takes about 250 milliseconds!
// Sensor readings may also be up to 2 seconds 'old' (its a very slow sensor)
// Registreer vochtigeidsgraad
humidity = dht.readHumidity();
// Registreer temperatuur in °C (the default)
temperature = dht.readTemperature();
temperature = temperature + temperatureCorrection; // Hou rekening met de ingestelde correctiewaarde mbt de foutmarge van de DHT11
// Compute heat index in Celsius (isFahreheit = false)
float hic = dht.computeHeatIndex(temperature, humidity, false);
// DISPLAY DATA
Serial.print("Luchtvochtigheid: " + String(humidity) + ("% Temperatuur: ") + String(temperature, 1) + ("°C ") + (" Warmte index (gevoelsmatig): ") + String(hic) + ("°C "));
Serial.print(" ");
if (isnan(humidity) || isnan(temperature)) {
Serial.println(" FOUT met DHT Temperatuursensor - Geen uitleesbare waarde ter beschikking... Sensor buiten gebruik!");
temperature = 0;
lcd.setCursor(0, 1);
lcd.print("Temp. sensor: NA");
dhtOK = false;
} else {
Serial.println("DHT temperatuursensor: OK");
lcd.setCursor(0, 1);
lcd.print("Temp: " + String(temperature, 1) + char(223) + "C "); // lcd.print(223); ==>> (°) Graden symbooltje
// Serial.println("Vochtigheid: " + String(round(humidity)) + " %\t" + "Temperatuur: " + String(temperature, 1) + " °C");
ControlegetalSensoren = ControlegetalSensoren + 1;
dhtOK = true;
}
delay(1750);
}
void UltrasoneMeting() {
for (int i = 0; i < NUM_MEASUREMENTS; i++) {
pinMode(TRIG_PIN, OUTPUT);
digitalWrite(TRIG_PIN, LOW);
delayMicroseconds(4);
digitalWrite(TRIG_PIN, HIGH);
delayMicroseconds(15); // Original 10 microsec., but the JSN-SR04T sensor uses 15 Microsecs!
digitalWrite(TRIG_PIN, LOW);
delayMicroseconds(1);
pinMode(ECHO_PIN, INPUT);
long duration_us = pulseIn(ECHO_PIN, HIGH);
distance_cm = ((duration_us * 0.034) / 2); // Afstand in cm
readings[i] = distance_cm;
// delay(1600);
FlashledRoutine(); // = Delay-tijd
}
sortReadings();
}
void UltrasoneMetingDHT() {
for (int i = 0; i < NUM_MEASUREMENTS; i++) {
pinMode(TRIG_PIN, OUTPUT);
digitalWrite(TRIG_PIN, LOW);
delayMicroseconds(4);
digitalWrite(TRIG_PIN, HIGH);
delayMicroseconds(15); // Original 10 microsec., but the JSN-SR04T sensor uses 15 Microsecs!
digitalWrite(TRIG_PIN, LOW);
delayMicroseconds(0);
pinMode(ECHO_PIN, INPUT);
long duration_us = pulseIn(ECHO_PIN, HIGH);
distance_cm = (duration_us * (0.03314 + (0.6 * temperature) / 2) / 100); // Afstand in cm
readings[i] = distance_cm;
// delay(1600);
FlashledRoutine(); // = Delay-tijd
}
sortReadings();
}
void getDistance() { // Ultrasone meeting ifv aanwezigheid correct DHT waarden
if (dhtOK == false) {
delay(300);
UltrasoneMeting();
Serial.println(DHTNOKTXT + String(mediaan) + " cm."); // Geef DHT NIET OK tekst weer!
delay(100);
} else { // DHT Werkt wel goed!
dhtOK = true;
delay(300);
UltrasoneMetingDHT();
Serial.println(DHTOKTXT + String(mediaan) + " cm."); // Geef DHT OK tekst weer!
delay(100);
}
}
void sortReadings() {
for (int i = 0; i < NUM_MEASUREMENTS; i++) {
total -= readings[i];
readings[i] = distance_cm;
Serial.println("Geordende meetresultaat " + String(i + 1) + char(41) + " " + String(readings[i]) + " cm.");
Serial.println(" ");
total += readings[i];
}
// Mediaanberekening van [8] waardes waarbij het gemiddelde van de 2 middenste waardes genomen wordt
// ==>>>> mediaan = ((readings[3] + readings[4]) / 2);
mediaan = ((readings[readingsMin] + readings[readingsMax]) / 2);
Serial.println ("*** Mediaan = " + String(mediaan) + " cm ***");
}
void ledRoutineOn() {
digitalWrite(GREEN_LED_PIN, HIGH);
digitalWrite(YELLOW_LED_PIN, HIGH);
digitalWrite(RED_LED_PIN, HIGH);
}
void ledRoutineOff() {
digitalWrite(GREEN_LED_PIN, LOW);
digitalWrite(YELLOW_LED_PIN, LOW);
digitalWrite(RED_LED_PIN, LOW);
}
void FlashledRoutine() { // Wordt enkel getoond bij afstandsmeting & berekening
digitalWrite(GREEN_LED_PIN, LOW);
digitalWrite(YELLOW_LED_PIN, LOW);
digitalWrite(RED_LED_PIN, LOW);
digitalWrite(YELLOW_LED_PIN, HIGH);
delay (150);
digitalWrite(RED_LED_PIN, HIGH);
digitalWrite(YELLOW_LED_PIN, LOW);
delay (225);
digitalWrite(RED_LED_PIN, LOW);
digitalWrite(YELLOW_LED_PIN, HIGH);
delay (150);
digitalWrite(RED_LED_PIN, HIGH);
digitalWrite(YELLOW_LED_PIN, LOW);
delay (225);
digitalWrite(RED_LED_PIN, LOW);
digitalWrite(YELLOW_LED_PIN, HIGH);
delay (150);
digitalWrite(RED_LED_PIN, HIGH);
digitalWrite(YELLOW_LED_PIN, LOW);
delay (225);
digitalWrite(RED_LED_PIN, LOW);
digitalWrite(YELLOW_LED_PIN, HIGH);
delay (150);
digitalWrite(RED_LED_PIN, HIGH);
digitalWrite(YELLOW_LED_PIN, LOW);
delay (225);
digitalWrite(RED_LED_PIN, LOW);
digitalWrite(YELLOW_LED_PIN, HIGH);
delay (150);
digitalWrite(YELLOW_LED_PIN, LOW);
digitalWrite(RED_LED_PIN, LOW);
}