/*
Automatic, ultrasonic sewage control by Steve Barth. 2023.
Ultrasonic sensor, Pro Mini 8MHz with Nokia 5110 screen and RGB led
The display was designed with the help of https://lopaka.app
*********************************************************************
*********************************************************************
RAM: [==== ] 38.4% (used 786 bytes from 2048 bytes)
Flash: [======= ] 75.1% (used 23060 bytes from 30720 bytes)
Building .pio\build\pro8MHzatmega328\firmware.hex
*********************************************************************/
//! last modify: 2025.10.08. v.4.3a
//****************************************** libraries *************************************************
#include <Arduino.h>
#include <avr/wdt.h> // watchdog timer library
#include <NewPing.h>
#include <U8g2lib.h> //- https://github.com/olikraus/u8g2/wiki/u8g2reference#setdisplayrotation
//****************************************** declarations **********************************************
#define BackLight 4
#define Pump 5
#define GreenLed 6
#define RedLed 7
#define TRIGGER_PIN A0 // Arduino pin tied to TRIGGER_PIN pin on ping sensor.
#define ECHO_PIN A1 // Arduino pin tied to ECHO_PIN pin on ping sensor.
#define MAX_DISTANCE 50 // Maximum Distance (in cm) to ping.
#define ITERATIONS 20 // Number of iterations.
// #define PING_INTERVAL 33 // Milliseconds between sensor pings (29ms is about the min to avoid cross-sensor ECHO_PIN).
NewPing sonar(TRIGGER_PIN, ECHO_PIN, MAX_DISTANCE); // NewPing setup of pins and maximum Distance.
float sound_time, Distance; //
const unsigned int LOOP_DELAY = 50; // msec of additional loop delay
const unsigned int CLOCK_PIN = 13, DATA_PIN = 11, CS_PIN = 10, DC_PIN = 9, RESET_PIN = 8; //
int PumpState = 0, temp = 0, level_Min = 42.0, level_Max = 32.5; //
char dispStr[5]; // null terminated char array used to pass to renderer.
/* Nokia 5110 blue pin assignments:
RST: 8
DC/"D/C": 9 ( 10 ?)
CE/CS/SCE: 10 ( 9 ?)
DIN/DN/MOSI/DATA: 11
CLK/SCLK/SCK: 13
VCC: 3.3V
LIGHT/LED: sw 3.3V (ground through 330 ohm resistor)
GND: ground
*/
/*
Controller "PCD8544", Display "84x48" [Description]
U8G2_PCD8544_84X48_1_4W_SW_SPI(rotation, clock, data, cs, dc [, reset]) [page buffer, size = 88 bytes]
U8G2_PCD8544_84X48_2_4W_SW_SPI(rotation, clock, data, cs, dc [, reset]) [page buffer, size = 176 bytes]
U8G2_PCD8544_84X48_F_4W_SW_SPI(rotation, clock, data, cs, dc [, reset]) [full framebuffer, size = 528 bytes]
U8G2_PCD8544_84X48_1_4W_HW_SPI(rotation, cs, dc [, reset]) [page buffer, size = 88 bytes]
U8G2_PCD8544_84X48_2_4W_HW_SPI(rotation, cs, dc [, reset]) [page buffer, size = 176 bytes]
U8G2_PCD8544_84X48_F_4W_HW_SPI(rotation, cs, dc [, reset]) [full framebuffer, size = 528 bytes]
U8G2_PCD8544_84X48_1_2ND_4W_HW_SPI(rotation, cs, dc [, reset]) [page buffer, size = 88 bytes]
U8G2_PCD8544_84X48_2_2ND_4W_HW_SPI(rotation, cs, dc [, reset]) [page buffer, size = 176 bytes]
U8G2_PCD8544_84X48_F_2ND_4W_HW_SPI(rotation, cs, dc [, reset]) [full framebuffer, size = 528 bytes]
U8G2_PCD8544_84X48_1_3W_SW_SPI(rotation, clock, data, cs [, reset]) [page buffer, size = 88 bytes]
U8G2_PCD8544_84X48_2_3W_SW_SPI(rotation, clock, data, cs [, reset]) [page buffer, size = 176 bytes]
U8G2_PCD8544_84X48_F_3W_SW_SPI(rotation, clock, data, cs [, reset]) [full framebuffer, size = 528 bytes]
U8G2_PCD8544_84X48_1_3W_HW_SPI(rotation, cs [, reset]) [page buffer, size = 88 bytes]
U8G2_PCD8544_84X48_2_3W_HW_SPI(rotation, cs [, reset]) [page buffer, size = 176 bytes]
U8G2_PCD8544_84X48_F_3W_HW_SPI(rotation, cs [, reset]) [full framebuffer, size = 528 bytes]
*/
U8G2_PCD8544_84X48_1_4W_HW_SPI lcd(U8G2_R0, CS_PIN, DC_PIN, RESET_PIN);
// if display rotation: U8G2_R0 : 0°; U8G2_R1 : 90°; U8G2_R2 : 180°; U8G2_R3 : 270°
//****************************************** setup *****************************************************
void setup(void)
{
Serial.begin(9600);
pinMode(BackLight, OUTPUT);
pinMode(Pump, OUTPUT);
pinMode(GreenLed, OUTPUT);
pinMode(RedLed, OUTPUT);
pinMode(TRIGGER_PIN, OUTPUT);
pinMode(ECHO_PIN, INPUT);
digitalWrite(BackLight, LOW);
digitalWrite(Pump, LOW);
delay(500);
digitalWrite(RedLed, HIGH);
delay(500);
digitalWrite(RedLed, LOW);
delay(500);
digitalWrite(GreenLed, HIGH);
delay(500);
digitalWrite(GreenLed, LOW);
delay(500);
lcd.begin();
lcd.setContrast(160); // display specific
digitalWrite(BackLight, HIGH);
delay(500);
lcd.firstPage(); // start screen
do
{
lcd.setFont(u8g2_font_6x13_tr); // u8g2_font_6x13_tr
lcd.drawRFrame(0, 1, 84, 46, 4); // if needed
lcd.drawStr(12, 12, "Ultrasonic");
lcd.drawStr(1, 21, "sewage control");
lcd.setFont(u8g2_font_6x10_tr);
lcd.drawStr(8, 33, "2025.");
lcd.drawStr(52, 33, "by:"); // 33, 34,
lcd.setFont(u8g2_font_7x13B_tr); // u8g2_font_7x13B_tr
lcd.drawStr(4, 44, "Steve Barth");
} while (lcd.nextPage());
delay(4000);
digitalWrite(BackLight, LOW);
lcd.clearDisplay();
delay(2000);
wdt_enable(WDTO_1S); // Watchdog Timer setting 1s
}
//****************************************** void's ****************************************************
void ultrasonic_meter() // ultrasonic sensor start
{
sound_time = sonar.ping_median(ITERATIONS);
Distance = (sound_time * 0.0343) / 2; // Use 343 metres per second as speed of sound //?? (x) /4 ??
}
void Pump_Control() // Pump control
{
/* 250mm fixing ultrasonic sensor, the water level max: 110mm + 65mm berm , water level min: 15mm */
if (Distance < level_Max && temp == 0) // 110mm water level max ( = (250mm) fixing + (65mm) berm)
{
digitalWrite(Pump, HIGH); // Pump on
PumpState = 1;
temp = 1;
}
else if (Distance < level_Max && temp == 1)
{
digitalWrite(Pump, HIGH);
PumpState = 1;
}
else if (Distance > level_Min) // 15mm water level min ( = (250mm) fixing + (65mm) berm + (95mm)water height)
{
digitalWrite(Pump, LOW);
PumpState = 0;
temp = 0;
}
}
void Led_Control() // led control
{
/*
red led on: water level 50% - 100% distance: 373mm - 325mm
green led on: water level 0% - 90% distance: 420mm - 334mm
*/
if (Distance < 37.3) // < 373mm / smaller 50%
{
digitalWrite(RedLed, HIGH); // red led on
}
else
digitalWrite(RedLed, LOW);
if (Distance > 33.4) // > 334mm / higher 90%
{
digitalWrite(GreenLed, HIGH); // green led on
}
else
digitalWrite(GreenLed, LOW);
}
void Lcd_display() // display control
{
digitalWrite(BackLight, HIGH);
delay(200);
lcd.firstPage();
do
{
lcd.setFont(u8g2_font_7x13B_tr);
//lcd.drawRFrame(9, 0, 67, 13, 4); // if needed upper -frame
//lcd.drawRFrame(1, 12, 83, 25, 4); // if needed middle -frame
lcd.drawRFrame(1, 1, 82, 35, 4); // if needed upper half -frame
lcd.drawStr(15, 11, "Distance");
Serial.println(Distance);
lcd.setFont(u8g2_font_logisoso20_tr);
String(Distance).toCharArray(dispStr, 5);
lcd.drawStr(5, 34, dispStr);
lcd.setFont(u8g2_font_fub11_tr);
lcd.drawStr(58, 33, "cm");
lcd.setFontMode(1); // activate transparent font mode
lcd.setFont(u8g2_font_7x13B_tr);
lcd.setDrawColor(2);
lcd.drawStr(4, 46, "pump is");
if (PumpState == 1)
{
lcd.drawButtonUTF8(68, 46, U8G2_BTN_HCENTER | U8G2_BTN_INV, 25, 1, 0, "on");
}
else
lcd.drawStr(60, 46, "off");
} while (lcd.nextPage());
}
//****************************************** loop ******************************************************
void loop(void)
{
ultrasonic_meter();
Lcd_display();
Led_Control();
Pump_Control();
wdt_reset(); // A watchdog timer reset
delay(LOOP_DELAY);
}
//****************************************** loop end **************************************************
//program end