I think I'm getting there (almost). The ultimate goal is that the LCD is "only" updated every 5 minutes or so (no need to have the water level updated too regularly), and that the web page should always have that last update. In the code below I put the update interval to 10 seconds.
Two more questions:
- Actually reading the sensor should be a separate function too ? With the result (CurVol and CurPercentage) passed on to update the LCD and update the web page ? I tried that but doesn't seem to work properly if I try to return the values.
- The client connection to the webserver can happen anytime during those 5 minutes. Is it OK then to have that run every second, so it can pick up the incoming client request?
#include <HCSR04.h>
#include <Wire.h>
#include "rgb_lcd.h"
#include <SPI.h>
#include <Ethernet.h>
#include <ArduinoJson.h>
// HC-SR04
UltraSonicDistanceSensor distanceSensor(15, 14);
// 16x2 LCD
rgb_lcd lcd;
// Wired Ethernet
byte mac[] = { 0xDE, 0xAD, 0xBE, 0xEF, 0xFE, 0xED };
IPAddress ip(192, 168, 0, 30); // static IP not working due to changed ESP32/server.h
IPAddress gateway(192, 168, 0, 1);
IPAddress subnet(255, 255, 255, 0);
EthernetServer server(80);
// Variables
int MaxHeight = 200; //height of water tank
int MaxVol = 20000; //max vol in L of both water tanks
int CurVol = 0;
int CurPercentage = 0;
// Progress Bar characters
byte zero[] = {B00000, B00000, B00000, B00000, B00000, B00000, B00000, B00000};
byte one[] = {B10000, B10000, B10000, B10000, B10000, B10000, B10000, B10000};
byte two[] = {B11000, B11000, B11000, B11000, B11000, B11000, B11000, B11000};
byte three[] = {B11100, B11100, B11100, B11100, B11100, B11100, B11100, B11100};
byte four[] = {B11110, B11110, B11110, B11110, B11110, B11110, B11110, B11110};
byte five[] = {B11111, B11111, B11111, B11111, B11111, B11111, B11111, B11111};
// Function to connect to Ethernet & start server
void setupEthernet () {
Ethernet.init(33);
Ethernet.begin(mac, ip, gateway, subnet);
delay(1000);
server.begin();
Serial.println(F("Server is ready."));
Serial.print(F("Please connect to http://"));
Serial.println(Ethernet.localIP());
}
// Function to setup LCD screen
void setupLcd () {
lcd.begin(16, 2);
lcd.createChar(0, zero);
lcd.createChar(1, one);
lcd.createChar(2, two);
lcd.createChar(3, three);
lcd.createChar(4, four);
lcd.createChar(5, five);
lcd.clear();
}
void updateLCD(int CurPercentage, unsigned long totalCount, int lineToPrintOn, int CurVol) {
static unsigned long timer = 0;
unsigned long interval = 10000;
if (millis() - timer >= interval) {
timer = millis();
// Show progress bar on LCD
double factor = totalCount / 80.0; // 16 characters x 5
int percent = (CurPercentage + 1) / factor;
int number = percent / 5;
int remainder = percent % 5;
if (number > 0) {
for (int j = 0; j < number; j++) {
lcd.setCursor(j, lineToPrintOn);
lcd.write(5);
}
}
lcd.setCursor(number, lineToPrintOn);
lcd.write(remainder);
if (number < 16) {
for (int j = number + 1; j <= 16; j++) {
lcd.setCursor(j, lineToPrintOn);
lcd.write((byte)0x00);
}
}
// show current volume and percentage on LCD
lcd.setCursor(0, 0);
lcd.print(" ");
lcd.setCursor(1, 0);
lcd.print(CurVol);
lcd.print(" L - ");
lcd.print(CurPercentage);
lcd.print(" %");
}
}
void doEthernet(int CurPercentage) {
static unsigned long timer = 0;
unsigned long interval = 1000;
if (millis() - timer >= interval) {
// Wait for an incoming connection
EthernetClient client = server.available();
if (!client)
return;
//Serial.println(F("New client"));
while (client.available()) client.read();
StaticJsonDocument<100> doc;
doc["data"] = CurPercentage;
// Write response headers
client.println(F("HTTP/1.0 200 OK"));
client.println(F("Content-Type: application/json"));
client.println(F("Connection: close"));
client.print(F("Content-Length: "));
client.println(measureJsonPretty(doc));
client.println();
serializeJsonPretty(doc, client);
client.stop();
}
}
// ========== MAIN FUNCTIONS: SETUP & LOOP ==========
void setup () {
Serial.begin(9600);
setupLcd ();
lcd.print("(re)Starting...");
setupEthernet(); // Connect to Ethernet
delay(5000);
lcd.clear();
}
void loop () {
float inputReading = distanceSensor.measureDistanceCm();
int CurPercentage = (100 - (inputReading / MaxHeight * 100));
int CurVol = MaxVol / 100 * CurPercentage;
updateLCD(CurPercentage, 100, 1, CurVol);
doEthernet(CurPercentage);
}