Using HTML buttons for web control with data refreshing

I am working on making a pool controller for one of my classes right now. I have an Arduino Uno with the official arduino ethernet shield attached to it. I have several temperature sensors and relays attached to the arduino, and am hosting an HTML website displaying them. I was able to get the temps and relay status to display on the website as shown below and automatically refresh.

However, I am having trouble adding in website control. I need to have buttons on the website for the user to be able to turn the relays on/off. I was able to implement a test code that only contains the buttons and it works well. However, when trying to combine them my website keeps crashing. I'm assuming it's some sort of error with the interaction of the buttons being pressed and the refreshing of the website to display the pool data. I attached the code with it all combined, it's a bit lengthy but the code for the website stuff starts around line 170.

#include <OneWire.h>
#include <DallasTemperature.h>
#include <SPI.h>
#include <Ethernet.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>

LiquidCrystal_I2C lcd(0x27, 20, 4);  //The LCD address and size.

#define ONE_WIRE_BUS 6  //pin for sensor
#define SensorPin A0    //pH meter Analog output to Arduino Analog Input 0

// Setup oneWire
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);

// Setup relays
const int pushButton[] = { 2, 3, 4 };           // define push button inputs
const int relayPin[] = { 9, 8, 7 };             // output pins where 3 relays will be connected
String relayNames[] = { "CH1", "CH2", "CH3" };  // Just put name for 3 relays
int pushed[] = { 0, 0, 0 };                     // status of each buttons
int relayStatus[] = { HIGH, HIGH, HIGH };       // initial status of relay
String relayState[] = { "OFF", "OFF", "OFF" };
String relayNumber[] = { "1", "2", "3" };
String readString;

float calibration_value = 21.34 + 0.7;
unsigned long int avgValue;  //Store the average value of the sensor feedback
int buf[10], temp;

// Website Setup
// Enter a MAC address and IP address for your controller below.
// The IP address will be dependent on your local network:
byte mac[] = {
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00
  //this is the mac address of the physical ethernet shield, edited for arduino forum
};
// this is the IP address that the server is accessible at
IPAddress ip(11, 11, 11, 11);
// Initialize the Ethernet server library
// with the IP address and port you want to use
// (port 80 is default for HTTP):
EthernetServer server(80);

void setup(void) {
  for (int i = 0; i < 3; i++) {
    pinMode(pushButton[i], INPUT_PULLUP);
    pinMode(relayPin[i], OUTPUT);
    digitalWrite(relayPin[i], HIGH);  // initial relay status to be OFF
  }
  Serial.begin(9600);
  Serial.println("Dallas Temperature IC Control Library Demo");
  // Initialize temp sensor
  sensors.begin();
  // Initialize pH Sensor
  pinMode(SensorPin, INPUT);

  // Initialize LCD and display welcome message
  lcd.init();
  lcd.backlight();
  lcd.setCursor(0, 0);
  lcd.print("Pool Controller");
  lcd.setCursor(0, 1);
  lcd.print("by CC, BJ, NG");
  delay(2000);
  lcd.clear();

  // start the Ethernet connection and the server:
  Ethernet.begin(mac, ip);
  // Check for Ethernet hardware present
  if (Ethernet.hardwareStatus() == EthernetNoHardware) {
    Serial.println("Ethernet shield was not found.  Sorry, can't run without hardware. :(");
    while (true) {
      delay(1);  // do nothing, no point running without Ethernet hardware
    }
  }
  if (Ethernet.linkStatus() == LinkOFF) {
    Serial.println("Ethernet cable is not connected.");
  }

  // start the server
  server.begin();
  Serial.print("server is at ");
  Serial.println(Ethernet.localIP());
}

// Main loop
void loop(void) {

  Serial.println("==");

  // Send the command to get temperatures
  // Serial.print("Requesting temperatures...");
  sensors.requestTemperatures();
  // Serial.println("DONE");

  // Get temperature data of each sensor
  float tempC1 = sensors.getTempCByIndex(0);               // Water sensor
  float tempC2 = sensors.getTempCByIndex(1);               // Air sensor
  float tempF1 = DallasTemperature::toFahrenheit(tempC1);  // Water in Fahrenheit
  float tempF2 = DallasTemperature::toFahrenheit(tempC2);  // Air in Fahrenheit

  // pH sensor
  for (int i = 0; i < 10; i++) {  //Get 10 sample value from the sensor for smooth the value
    buf[i] = analogRead(SensorPin);
    delay(10);
  }
  for (int i = 0; i < 9; i++) {  //sort the analog from small to large
    for (int j = i + 1; j < 10; j++) {
      if (buf[i] > buf[j]) {
        temp = buf[i];
        buf[i] = buf[j];
        buf[j] = temp;
      }
    }
  }
  avgValue = 0;
  for (int i = 2; i < 8; i++) avgValue += buf[i];  //take the average value of 6 center sample

  float phValue = (float)avgValue * 5.0 / 1024 / 6;  //convert the analog into millivolt
  phValue = -5.70 * phValue + calibration_value;     //convert the millivolt into pH value
                                                     // end of pH sensor section

  // this for loop controls the relays
  for (int i = 0; i < 3; i++) {
    int val = digitalRead(pushButton[i]);
    if (val == HIGH && relayStatus[i] == LOW) {
      pushed[i] = 1 - pushed[i];
      delay(100);
    }

    relayStatus[i] = val;  // status of each relay

    // If pushed status is HIGH, turn relay on
    if (pushed[i] == HIGH) {
      digitalWrite(relayPin[i], LOW);
      relayState[i] = "ON";
    } else if (pushed[i] == LOW) {
      digitalWrite(relayPin[i], HIGH);
      relayState[i] = "OFF";
    }
  }

  // start the ethernet client
  EthernetClient client = server.available();
  if (client) {
    Serial.println("new client");
    // an http request ends with a blank line
    while (client.connected()) {
      if (client.available()) {
        char c = client.read();
        //Serial.write(c);
        if (readString.length() < 100) {
          //store characters to string
          readString += c;
          //Serial.print(c);
        }
        // if you've gotten to the end of the line (received a newline
        // character) and the line is blank, the http request has ended,
        // so you can send a reply
        if (c == '\n') {
          // send a standard http response header
          client.println("HTTP/1.1 200 OK");
          client.println("Content-Type: text/html");

          client.println();
          client.println("<!DOCTYPE HTML>");
          client.println("<HTML>");
          client.println("<HEAD> <meta http-equiv='refresh' content='1'/> <title>PoolController</title>");
          client.println("</HEAD>");
          client.println("<BODY>");
          client.println("<H1>Pool Equipment Control</H1>");

          client.print("<input type=submit value=HeaterON style=width:100px;height:45px onClick=location.href='/?on2;'>");
          client.print("<input type=submit value=HeaterOFF style=width:100px;height:45px onClick=location.href='/?off3;'>");
          client.println("<br />");
          client.print("<input type=submit value=PumpON style=width:100px;height:45px onClick=location.href='/?on4;'>");
          client.print("<input type=submit value=PumpOFF style=width:100px;height:45px onClick=location.href='/?off5;'>");
          client.println("<br />");
          client.print("&nbsp;<input type=submit value='ALL OFF' style=width:100px;height:45px onClick=location.href='/?off35;'>");
          client.println("<br />");

          client.println("<H2>Pool Data</H2>");
          client.println("<br />");
          // upload temperature data
          client.print("Water Temp = ");
          client.print(tempF1);
          client.print(" F<br />");

          client.print("Air Temp = ");
          client.print(tempF2);
          client.print(" F<br />");
          //upload pH sensor readings
          client.print("Pool water = ");
          client.print(phValue);
          client.print(" pH<br />");

          client.print("Pool Pump is ");
          client.print(relayState[0]);
          client.println("<br />");
          client.print("Pool Heater is ");
          client.print(relayState[1]);
          client.println("<br />");
          client.print("Relay #3 is ");
          client.print(relayState[2]);
          client.println("<br />");
          client.println("<br />");


          client.println("</BODY>");
          // end document
          client.println("</HTML>");
          delay(1);
          //stopping client
          client.stop();

          if (readString.indexOf('2') > 0)  //checks for 2
          {
            digitalWrite(relayPin[2], LOW);  //turn pin8 ON
          }
          if (readString.indexOf('3') > 0)  //checks for 3
          {
            digitalWrite(relayPin[2], HIGH);  // turn pin8 OFF
          }
          if (readString.indexOf('4') > 0)  //checks for 2
          {
            digitalWrite(relayPin[1], LOW);  //turn pin 9 ON
          }
          if (readString.indexOf('5') > 0)  //checks for 3
          {
            digitalWrite(relayPin[1], HIGH);  // turn pin 9 OFF
          }
          readString = "";
          Serial.println("Server Running");
        }
      }
    }
  }

  // Check if reading was successful
  if (tempC1 != DEVICE_DISCONNECTED_C && tempC2 != DEVICE_DISCONNECTED_C) {
    // Displaying water temp
    lcd.setCursor(0, 0);
    lcd.print("Water: ");
    lcd.setCursor(9, 0);
    lcd.print(tempF1);
    lcd.print((char)223);
    lcd.print(" F");

    // Displaying air temp
    lcd.setCursor(0, 1);
    lcd.print("Air: ");
    lcd.setCursor(9, 1);
    lcd.print(tempF2);
    lcd.print((char)223);
    lcd.print(" F");
  } else {
    Serial.println("Error: Could not read temperature data");
  }

  // Displaying pH Value
  lcd.setCursor(0, 2);
  lcd.print("pH:");
  lcd.setCursor(9, 2);
  lcd.print(phValue);

  // Serial.println("==");
}

please, please never ever again post pictures of text... Not only they are not readable nor usable directly for copy&paste but they use up lots of storage and internet bandwidth which contributes to polluting the planet.

➜ do your part and do yourself a favour and please read How to get the best out of this forum and modify your post accordingly (including code tags and necessary documentation for your ask).

--

for the code you don't need to attach it, just copy & paste it here with the code tags.

I changed it, thanks!

1 Like

try with this code for your page

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta http-equiv="refresh" content="1">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>PoolController</title>
    <style>button{width:100px}</style>
</head>
<body>
    <h1>Pool Equipment Control</h1>
    <a href="/heateron"><button>Heater ON</button></a>
    <a href="/heateroff"><button>Heater OFF</button></a>
    <a href="/pumpon"><button>Pump ON</button></a>
    <a href="/pumpoff"><button>Pump OFF</button></a>
    <a href="/alloff"><button>ALL OFF</button></a>
    <h2>Pool Data</h2>
    <br />
    Water Temp = [value of tempF1] F<br />
    Air Temp = [value of tempF2] F<br />
    Pool water = [value of phValue] pH<br />
    Pool Pump is [value of relayState[0]]<br />
    Pool Heater is [value of relayState[1]]<br />
    Relay #3 is [value of relayState[2]]<br />
    <br />
</body>
</html>

you can generate that with

client.println(F("<!DOCTYPE html><html lang=\"en\"><head><meta charset=\"UTF-8\"><meta http-equiv=\"refresh\" content=\"1\"><meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\"><title>PoolController</title><style>button{width:100px}</style></head><body><h1>Pool Equipment Control</h1><a href=\"/heateron\"><button>Heater ON</button></a><a href=\"/heateroff\"><button>Heater OFF</button></a><a href=\"/pumpon\"><button>Pump ON</button></a><a href=\"/pumpoff\"><button>Pump OFF</button></a><a href=\"/alloff\"><button>ALL OFF</button></a><h2>Pool Data</h2><br />Water Temp = "));
client.print(tempF1);
client.println(F(" F<br />Air Temp = "));
client.print(tempF2);
client.println(F(" F<br />Pool water = "));
client.print(phValue);
client.println(F(" pH<br />Pool Pump is "));
client.print(relayState[0]);
client.println(F("<br />Pool Heater is "));
client.print(relayState[1]);
client.println(F("<br />Relay #3 is "));
client.print(relayState[2]);
client.println(F("<br /><br /></body></html>")));

When a user clicks on one of the buttons, the browser sends a GET request to the corresponding URL specified in the href attribute of the anchor element.

  1. Heater ON: /heateron
  2. Heater OFF: /heateroff
  3. Pump ON: /pumpon
  4. Pump OFF: /pumpoff
  5. ALL OFF: /alloff

These URLs are to be handled by the server to perform the desired actions, such as turning the heater or pump on or off, or toggling all equipment off.

for that you can search for exact URL like /heateron for example in the GET request

(it will refresh every second)

1 Like

Thank you for your reply, just to make sure, on your very last line is there an extra parentheses?

yes, sorry I typed it here.

No worries, thanks again for your help. As far as handling the button click goes, what would be the correct syntax for that? Previously, I used the readString.indexOf('number') > 0 to check if that specific button had been pressed, should I be doing that the same way?

if you print readString do you see something like GET .....?

if so yes, you would just check if (readString.indexOf("/heateron") > 0) {...

Shown below is my current code for the relevant section. I added in a third button set. However, the only issue I am having now my readString doesn't seem to be properly clearing itself. When I press a button it changes as expected, but when the website refreshes it detects that last button input as a brand new one and will continually do the same command

          client.println(F("<!DOCTYPE html><html lang=\"en\"><head><meta charset=\"UTF-8\"><meta http-equiv=\"refresh\" content=\"3\"><meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\"><title>PoolController</title><style>button{width:100px}</style></head><body><h1>Pool Equipment Control</h1><a href=\"/heateron\"><button>Heater ON</button></a><a href=\"/heateroff\"><button>Heater OFF</button></a><a href=\"/pumpon\"><button>Pump ON</button></a><a href=\"/pumpoff\"><button>Pump OFF</button></a><br /><a href=\"/filteron\"><button>Filter ON</button></a><a href=\"/filteroff\"><button>Filter OFF</button></a><a href=\"/alloff\"><button>ALL OFF</button></a><h2>Pool Data</h2><br />Water Temp = "));
          client.print(tempF1);
          client.println(F(" F<br />Air Temp = "));
          client.print(tempF2);
          client.println(F(" F<br />Pool water = "));
          client.print(phValue);
          client.println(F(" pH<br />Pool Pump is "));
          client.print(relayState[0]);
          client.println(F("<br />Pool Heater is "));
          client.print(relayState[1]);
          client.println(F("<br />Pool Filter is "));
          client.print(relayState[2]);
          client.println(F("<br /><br /></body></html>"));


          if(readString.indexOf("/heateron") >0)//checks for 
          {
            Serial.println(readString.indexOf("/heateron"));
            Serial.println("heater ON");
            digitalWrite(relayPin[2], LOW);//turn heater ON
          }
          if(readString.indexOf("/heateroff") >0)//checks for 
          {
            digitalWrite(relayPin[2], HIGH);// turn heater OFF
            Serial.println(readString.indexOf("/heateroff"));
            Serial.println("heater OFF");

          }
          if(readString.indexOf("/pumpon") >0)//checks for 2
          {
            digitalWrite(relayPin[1], LOW);//turn pump ON
            Serial.println(readString.indexOf("/pumpon"));
            Serial.println("pump ON");
          }
          if(readString.indexOf("/pumpoff") >0)//checks for 3
          {
            digitalWrite(relayPin[1], HIGH);// turn pump OFF
            Serial.println(readString.indexOf("/pumpoff"));
            Serial.println("pump oFF");
          }  
          if(readString.indexOf("/filteron") >0)
          {
            digitalWrite(relayPin[0], LOW);//turn filter ON
            Serial.println(readString.indexOf("/filteron"));
            Serial.println("filter ON");
          }
          if(readString.indexOf("/filteroff") >0)
          {
            digitalWrite(relayPin[0], HIGH);// turn filter OFF
            Serial.println(readString.indexOf("/filteroff"));
            Serial.println("filter off");
          }  
          if(readString.indexOf("/alloff") >0)
          {
            digitalWrite(relayPin[0], HIGH);// turn filter OFF
            digitalWrite(relayPin[1], HIGH);// turn pump OFF
            digitalWrite(relayPin[2], HIGH);// turn heater OFF
            Serial.println(readString.indexOf("/alloff"));
            Serial.println("all off");
          }  
          readString="";
          Serial.println("Server Running");
          delay(5);
          //stopping client
          client.stop();

        }

What is the URL shown in the browser - does it include the /xxx corresponding to the button?

(To prevent the URL from changing when clicking the HTML button, you can use JavaScript to handle the click event and prevent the default behavior of the button. )

I fixed it by adding a redirect page that triggers after a button press as shown below. Also added some fancy formatting


#include <OneWire.h>
#include <DallasTemperature.h>
#include <SPI.h>
#include <Ethernet.h>
#include <Wire.h>
#include <LiquidCrystal_I2C.h>
#include <TimeLib.h>


LiquidCrystal_I2C lcd(0x27, 20, 4);  //The LCD address and size.

#define ONE_WIRE_BUS 6  //pin for sensor
#define SensorPin A0    //pH meter Analog output to Arduino Analog Input 0

// Setup oneWire
OneWire oneWire(ONE_WIRE_BUS);
DallasTemperature sensors(&oneWire);

// Setup relays
const int pushButton[] = { 2, 3, 4 };                  // define push button inputs
const int relayPin[] = { 7, 8, 9 };                    // output pins where 3 relays will be connected
String relayNames[] = { "Filter", "Pump", "Heater" };  // Just put name for 3 relays
int pushed[] = { 0, 0, 0 };                            // status of each buttons
int relayStatus[] = { HIGH, HIGH, HIGH };              // initial status of relay
String relayState[] = { "OFF", "OFF", "OFF" };
String relayNumber[] = { "1", "2", "3" };
String readString;
String date;
String time;
String datetime;
String pumpTime;
int buttonPressed = 0;
bool filterStatus;
float calibration_value = 21.34 + 0.7;
unsigned long int avgValue;  //Store the average value of the sensor feedback
int buf[10], temp;

// Website Setup
// Enter a MAC address and IP address for your controller below.
// The IP address will be dependent on your local network:
byte mac[] = {
  0x00, 0x00, 0x00, 0x00, 0x00, 0x00
  //this is the mac address of the physical ethernet shield
};

// this is the IP address that the server is accessible at
IPAddress ip(10, 4, 76, 93);

// define IPAddress object that will contain the NTP server IP address
// We will use an NTP server from https://tf.nist.gov/tf-cgi/servers.cgi
IPAddress timeSrvr(132, 163, 97, 1);

// Initialize the Ethernet server library
// with the IP address and port you want to use
// (port 80 is default for HTTP):
EthernetServer server(80);

// define Ethernet UDP object and local port 8888
EthernetUDP ethernet_UDP;
unsigned int localPort = 8888;

// variable to store previous displayed time
time_t prevDisplay = 0;

// array to hold incoming/outgoing NTP messages
// NTP time message is 48 bytes long
byte messageBuffer[48];

void setup(void) {
  for (int i = 0; i < 3; i++) {
    pinMode(pushButton[i], INPUT_PULLUP);
    pinMode(relayPin[i], OUTPUT);
    digitalWrite(relayPin[i], HIGH);  // initial relay status to be OFF
    Serial.println("Relays Set UP");
  }

  Serial.begin(9600);
  Serial.println("Dallas Temperature IC Control Library Demo");

  // Initialize temp sensor
  sensors.begin();

  // Initialize pH Sensor
  pinMode(SensorPin, INPUT);

  // Initialize LCD and display welcome message
  lcd.init();
  lcd.backlight();
  lcd.setCursor(0, 0);
  lcd.print("Pool Controller");
  lcd.setCursor(0, 1);
  lcd.print("by CC, BJ, NG");
  delay(2000);
  lcd.clear();

  // start the Ethernet connection and the server:
  Ethernet.begin(mac, ip);
  // Check for Ethernet hardware present
  if (Ethernet.hardwareStatus() == EthernetNoHardware) {
    Serial.println("Ethernet shield was not found.  Sorry, can't run without hardware. :(");
    while (true) {
      delay(1);  // do nothing, no point running without Ethernet hardware
    }
  }
  if (Ethernet.linkStatus() == LinkOFF) {
    Serial.println("Ethernet cable is not connected.");
  }

  // start the server
  server.begin();
  Serial.print("server is at ");
  Serial.println(Ethernet.localIP());

  // start UDP
  // [part of Ethernet Library]
  ethernet_UDP.begin(localPort);
  // pass function getTime() to Time Library to update current time
  // [part of Time Library]
  setSyncProvider(getTime);
}

// Main loop
void loop(void) {

  Serial.println("==");

  if (timeStatus() != timeNotSet) {  // check if the time is successfully updated
    if (now() != prevDisplay) {      // update the display only if time has changed
      prevDisplay = now();
      datetime = dateTimeStringGenerator();  // this returns the time date as a string
      lcdClockDisplay(datetime);
    }
  }

  // Send the command to get temperatures
  // Serial.print("Requesting temperatures...");
  sensors.requestTemperatures();
  // Serial.println("DONE");

  // Get temperature data of each sensor
  float tempC1 = sensors.getTempCByIndex(0);               // Water sensor
  float tempC2 = sensors.getTempCByIndex(1);               // Air sensor
  float tempF1 = DallasTemperature::toFahrenheit(tempC1);  // Water in Fahrenheit
  float tempF2 = DallasTemperature::toFahrenheit(tempC2);  // Air in Fahrenheit

  // pH sensor
  for (int i = 0; i < 10; i++) {  //Get 10 sample value from the sensor for smooth the value
    buf[i] = analogRead(SensorPin);
    delay(10);
  }
  for (int i = 0; i < 9; i++) {  //sort the analog from small to large
    for (int j = i + 1; j < 10; j++) {
      if (buf[i] > buf[j]) {
        temp = buf[i];
        buf[i] = buf[j];
        buf[j] = temp;
      }
    }
  }
  avgValue = 0;
  for (int i = 2; i < 8; i++) avgValue += buf[i];  //take the average value of 6 center sample

  float phValue = (float)avgValue * 5.0 / 1024 / 6;  //convert the analog into millivolt
  phValue = -5.70 * phValue + calibration_value;     //convert the millivolt into pH value
                                                     // end of pH sensor section
  // this for loop controls the relays
  if (buttonPressed == 1) {
    for (int i = 0; i < 3; i++) {
      int val = digitalRead(pushButton[i]);
      if (val == HIGH && relayStatus[i] == LOW) {
        pushed[i] = 1 - pushed[i];
        delay(100);
      }

      relayStatus[i] = val;  // status of each relay

      // If pushed status is HIGH, turn relay on
      if (pushed[i] == HIGH) {
        // Serial.print(relayNames[i]);
        // Serial.println(" ON");
        // if(digitalRead(relayPin[i]) == HIGH){
        //   lcd.setCursor(0,3);
        //   lcd.print("Relay #" + relayNumber[i] + " is now on ");
        // }
        digitalWrite(relayPin[i], LOW);
        relayState[i] = "ON";


      } else if (pushed[i] == LOW) {
        // if pushed status is LOW, turn relay off
        // Serial.print(relayNames[i]);
        // Serial.println(" OFF");
        // if(digitalRead(relayPin[i]) == HIGH){
        //   lcd.setCursor(0,3);
        //   lcd.print("Relay #" + relayNumber[i] + " is now off");
        // }
        digitalWrite(relayPin[i], HIGH);
        relayState[i] = "OFF";
      }
    }
  }


  // start the ethernet client
  EthernetClient client = server.available();
  if (client) {
    Serial.println("new client");
    // an http request ends with a blank line
    while (client.connected()) {
      if (client.available()) {

        char c = client.read();

        if (readString.length() < 100) {

          //store characters to string
          readString += c;
          //Serial.print(c);
        }
        // if you've gotten to the end of the line (received a newline
        // character) and the line is blank, the http request has ended,
        // so you can send a reply
        if (c == '\n') {
          buttonPressed = 0;
          if (readString.indexOf("/heateron") > 0)  //checks for
          {
            Serial.println("heater ON");
            digitalWrite(relayPin[2], LOW);  //turn heater ON
            relayState[2] = "ON";
            buttonPressed = 1;
          }
          if ((readString.indexOf("/heateroff") > 0))  //checks for
          {
            digitalWrite(relayPin[2], HIGH);  // turn heater OFF
            Serial.println("heater OFF");
            relayState[2] = "OFF";
            buttonPressed = 1;
          }

          if ((readString.indexOf("/pumpon") > 0))  //checks for 2
          {
            digitalWrite(relayPin[1], LOW);  //turn pump ON
            Serial.println("pump ON");
            relayState[1] = "ON";
            buttonPressed = 1;
          }

          if ((readString.indexOf("/pumpoff") > 0))  //checks for 3
          {
            digitalWrite(relayPin[1], HIGH);  // turn pump OFF
            Serial.println("pump off");
            relayState[1] = "OFF";
            buttonPressed = 1;
          }
          if ((readString.indexOf("/filteron") > 0)) {
            digitalWrite(relayPin[0], LOW);  //turn filter ON
            Serial.println("filter ON");
            relayState[0] = "ON";
            buttonPressed = 1;
            filterStatus = true;
          }
          if ((readString.indexOf("/filteroff") > 0)) {
            digitalWrite(relayPin[0], HIGH);  // turn filter OFF

            Serial.println("filter off");
            relayState[0] = "OFF";
            buttonPressed = 1;
            filterStatus = false;
          }

          if (buttonPressed == 1) {
            client.println(F("<!DOCTYPE html><html lang=\"en\"><head><meta http-equiv=\"refresh\" content=\"0; url=http://10.4.76.93\" /></head><body><p><a href=\"http://10.4.76.93\">Redirect</a></p></body></html>"));
            buttonPressed = 0;
            delay(50);
            client.stop();
            Serial.println("Redirecting");
            readString = "";
          } else {
            Serial.println("Main Page");
            client.println(F("<!DOCTYPE html> <html lang=\"en\"> <head> <meta charset=\"UTF-8\"> <meta http-equiv=\"refresh\" content=\"4\"> <meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\"> <title>PoolController</title> <style> * { box-sizing: border-box; } .grid-container { display: grid; grid-template-columns: auto auto; background-color: #2196F3; padding: 10px; column-gap: 5px; row-gap: 5px; } .grid-item { background-color: rgba(255, 255, 255, 0.8); border: 1px solid rgba(0, 0, 0, 0.8); padding: 15px 12px; font-size: 24px; text-align: center; font-style: Trebuchet MS; font-weight: 250; font-style: normal; } .grid-item1 { background-color: rgba(255, 255, 255, 0.8); border: 1px solid rgba(0, 0, 0, 0.8); padding: 10px 10px; text-align: center; } body { margin: 0; font-size: 18px; } buttonOn { background-color: #39bc2d; color: #fff; font-family: Trebuchet MS; font-size: 23px; font-weight: 800; font-style: normal; text-decoration: none; padding: 25px 20px; border: 0px solid #000; border-radius: 10px; display: inline-flex; } buttonOff { background-color: #de232c; color: #fff; font-family: Trebuchet MS; font-size: 23px; font-weight: 800; font-style: normal; text-decoration: none; padding: 25px 20px; border: 0px solid #000; border-radius: 10px; display: inline-block; } .header { font-family: Trebuchet MS; background-color: #dfdddd; padding: 5px; text-align: center; } input[type=time] { border:1px solid #2196F3; color: #0e0e0e; background-color: #99a2b5; font-size: 25px; font-family: Trebuchet MS; } h2 { font-family: Trebuchet MS; background-color: #f1f1f1; padding: 5px; text-align: center; } .column { float: left; width: 33%; position: relative; padding: 15px; } .row::after { content: \"\"; display: table; clear: both; } @media screen and (max-width:800px) { .column { width: 100%; } } </style> </head> <body> <div class=\"header\"> <h1>Maher's Pool Controller</h1> </div> <div class=\"row\"> <div class=\"column\"> <h2>Equipment Control</h2> <div class=\"grid-container\"> <div class=\"grid-item1\"> <a href=\"/heateron\"> <buttonOn>Heater ON</buttonOn> </a></div> <div class=\"grid-item1\"> <a href=\"/heateroff\"> <buttonOff>Heater OFF</buttonOff> </a></div> <div class=\"grid-item1\"> <a href=\"/pumpon\"> <buttonOn>Pump ON</buttonOn> </a></div> <div class=\"grid-item1\"> <a href=\"/pumpoff\"> <buttonOff>Pump OFF</buttonOff> </a></div> <div class=\"grid-item1\"> <a href=\"/filteron\"> <buttonOn>Filter ON</buttonOn> </a></div> <div class=\"grid-item1\"> <a href=\" /filteroff\"> <buttonOff>Filter OFF</buttonOff> </a></div> </div> </div> <div class=\"column\"> <h2>Equipment Scheduling</h2> <div class=\"grid-container\"> <div class=\"grid-item\">Heater On<br /><input type=\"time\" id=\"OnHeater\" name=\"heat\" min=\"00:00\" max=\"24:00\" required /> </div> <div class=\"grid-item\">Heater Off<br /><input type=\"time\" id=\"OffHeater\" name=\"heat\" min=\"00:00\" max=\"24:00\" required /> </div> <div class=\"grid-item\">Pump On<br /><input type=\"time\" id=\"OnPump\" name=\"pump\" min=\"00:00\" max=\"24:00\" required /> </div> <div class=\"grid-item\">Pump Off<br /><input type=\"time\" id=\"OffPump\" name=\"pump\" min=\"00:00\" max=\"24:00\" required /> </div> <div class=\"grid-item\">Filter On<br /><input type=\"time\" id=\"OnFilter\" name=\"filter\" min=\"00:00\" max=\"24:00\" required /> </div> <div class=\"grid-item\">Filter Off<br /><input type=\"time\" id=\"OffFilter\" name=\"filter\" min=\"00:00\" max=\"24:00\" required /> </div> </div> <br /> </div> <div class=\"column\"> <h2>"));
            client.println(datetime);
            client.println(F("</h2><div class=\"grid-container\"><div class=\"grid-item\">Pool Heater is "));
            client.print(relayState[2]);
            client.println(F("</div><div class=\"grid-item\">Air Temp: "));
            client.print(tempF1);
            client.println(F(" F</div><div class=\"grid-item\">Pool Pump is "));
            client.print(relayState[1]);
            client.println(F("</div><div class=\"grid-item\">Water Temp: "));
            client.print(tempF2);
            client.println(F(" F</div><div class=\"grid-item\">Pool Filter is "));
            client.print(relayState[0]);
            client.println(F("</div><div class=\"grid-item\"> Water Chemistry: "));
            client.print(phValue);
            client.println(F(" pH</div></div></div></body></html>"));
            Serial.println("Server Running");
            delay(50);
            //stopping client
            client.stop();
            readString = "";
          }
        }
      }
    }
  }

  // Check if reading was successful
  if (tempC1 != DEVICE_DISCONNECTED_C && tempC2 != DEVICE_DISCONNECTED_C) {
    // Displaying temps in serial monitor
    // Serial.print("Temperature for the device 1 (index 0) is: ");
    // Serial.println(tempC1);
    // Serial.print("Temperature for the device 2 (index 1) is: ");
    // Serial.println(tempC2);

    // Displaying water temp
    lcd.setCursor(0, 0);
    lcd.print("Water: ");
    lcd.setCursor(9, 0);
    lcd.print(tempF1);
    lcd.print((char)223);
    lcd.print(" F");

    // Displaying air temp
    lcd.setCursor(0, 1);
    lcd.print("Air: ");
    lcd.setCursor(9, 1);
    lcd.print(tempF2);
    lcd.print((char)223);
    lcd.print(" F");
  } else {
    Serial.println("Error: Could not read temperature data");
  }

  // Displaying pH Value
  lcd.setCursor(0, 2);
  lcd.print("pH:");
  lcd.setCursor(9, 2);
  lcd.print(phValue);

  // Serial.println("==");
}

/*
   ========================================================================================
   function to display the time in an easy to read format using the Time Library functions
   ========================================================================================
*/

/*
   ========================================================================================
   function to display the time on the LCD in an easy to read format using the Time Library functions
   ========================================================================================
*/
String dateTimeStringGenerator() {

  datetime = "";

  if (hour() > 12) {
    datetime += hour() - 12;
    datetime += ":";
    if (minute() < 10) {
      datetime += "0";
      datetime += minute();
    } else {
      datetime += minute();
    }
    datetime += " P.M. ";
  } else {
    datetime += hour();
    datetime += ":";
    if (minute() < 10) {
      datetime += "0";
      datetime += minute();
    } else {
      datetime += minute();
    }
    datetime += " A.M. ";
  }
  datetime += month();
  datetime += "/";
  datetime += day();
  datetime += "/";
  datetime += year();
  return datetime;
}
void lcdClockDisplay(String datetime) {
  lcd.setCursor(0, 3);
  lcd.print(datetime);
}

/*
   =========================================
   helper function for digitalClockDisplay()
   =========================================
*/
void printDigits(int digits) {
  // add colon character and a leading zero if number < 10
  Serial.print(":");
  if (digits < 10)
    Serial.print('0');
  Serial.print(digits);
}

/*
   ===========================================
   NTP code for communicating with NTP server
   ===========================================

   =================================================
   function to request current time from NTP server
   =================================================
*/
time_t getTime() {
  while (ethernet_UDP.parsePacket() > 0)
    ;  // discard packets remaining to be parsed

  Serial.println("Transmit NTP Request message");

  // send packet to request time from NTP server
  sendRequest(timeSrvr);

  // wait for response
  uint32_t beginWait = millis();

  while (millis() - beginWait < 1500) {

    int size = ethernet_UDP.parsePacket();

    if (size >= 48) {
      Serial.println("Receiving NTP Response");

      // read data and save to messageBuffer
      ethernet_UDP.read(messageBuffer, 48);

      // NTP time received will be the seconds elapsed since 1 January 1900
      unsigned long secsSince1900;

      // convert to an unsigned long integer the reference timestamp found at byte 40 to 43
      secsSince1900 = (unsigned long)messageBuffer[40] << 24;
      secsSince1900 |= (unsigned long)messageBuffer[41] << 16;
      secsSince1900 |= (unsigned long)messageBuffer[42] << 8;
      secsSince1900 |= (unsigned long)messageBuffer[43];

      // returns UTC time
      return secsSince1900 - 2208988800UL - 18000UL;
    }
  }

  // error if no response
  Serial.println("Error: No Response.");
  return 0;
}

/*
   helper function for getTime()
   this function sends a request packet 48 bytes long
*/
void sendRequest(IPAddress &address) {
  // set all bytes in messageBuffer to 0
  memset(messageBuffer, 0, 48);

  // create the NTP request message

  messageBuffer[0] = 0b11100011;  // LI, Version, Mode
  messageBuffer[1] = 0;           // Stratum, or type of clock
  messageBuffer[2] = 6;           // Polling Interval
  messageBuffer[3] = 0xEC;        // Peer Clock Precision
  // array index 4 to 11 is left unchanged - 8 bytes of zero for Root Delay & Root Dispersion
  messageBuffer[12] = 49;
  messageBuffer[13] = 0x4E;
  messageBuffer[14] = 49;
  messageBuffer[15] = 52;

  // send messageBuffer to NTP server via UDP at port 123
  ethernet_UDP.beginPacket(address, 123);
  ethernet_UDP.write(messageBuffer, 48);
  ethernet_UDP.endPacket();
}

Nice
There are a few things I would handle differently but if that works go for it!

1 Like

the F Makro is good to be used with Serial.print, lcd.print and lot of others, but don't use it for the Webserver.

If you need to put lot of HTML in your code, I propose to use @Juraj StreamLib.h

here are my notes regarding the F-Makro and the webserver: Arduino Webserver optimize SRAM, Progmem and Speed

1 Like

Yeah I'm sure it is far from an optimal solution, but our professor decided to put three electrical engineers on one team for our embedded system design and I'm the only one who's sorta decent at coding hahah

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.