Hot Water Tank Temperature on Arduino LCD

Back in March 2014, I posted about monitoring the hot water tank temperature and when the immersion was switched on by the solar surplus http://blog.v-s-f.co.uk/2014/03/home-monitoring-home-made-results/.

We have now decided to display the last temperature reading on an LCD next to the shower room and boiler control panel. The previous software I’d written to upload data to PVOutput had* to be re-written in order to accommodate this new Arduino which would request the last reading available and display it.

The Arduino code below is fairly simple. Every 1 minute it requests data from my server named Pompeii. If it receives data, it refreshes the screen with the response, changing the last character for an up or down arrow, to represent the temperature in/decreasing or a hyphen for level. It’s possibly not the most efficient code in the world, but it doesn’t need to be!

There is one notable item in the code and that’s the pin configuration of the LCD. It turns out that the pins referenced in the Arduino tutorial book I have are pins used for the Ethernet connection on the Ethernet board, therefore I’ve shifted pins 11 and 12 to 6 and 7 respectively.

So what does it look like?

IMG_5312

Code below

#include <SPI.h>
#include <Ethernet.h>
#include <LiquidCrystal.h>

///////// CHANGEABLE VALUES /////////

char pompeii[] = "192.168.0.16";
int pompeiiPort = 28080;

double minutesBetweenCalls = 1.0;

///////// CHANGEABLE VALUES ABOVE /////////

EthernetClient pompeiiClient;
byte mac[] = {
  0x90, 0xA2, 0xDA, 0x0F, 0xA1, 0xCF};
char pompeiiService[] = "/aggregator/services/hot-water-display";
double millisecondsInAMinute = 60000.0;

//LiquidCrystal lcd(12, 11, 5, 4, 3, 2);
LiquidCrystal lcd(7, 6, 5, 4, 3, 2);

const int LCD_WIDTH=16;

byte upArrow[8] = {
  B00100,
  B01110,
  B11111,
  B10101,
  B00100,
  B00100,
  B00000,
};

byte downArrow[8] = {
  B00000,
  B00100,
  B00100,
  B10101,
  B11111,
  B01110,
  B00100,
};

void setup() {
  lcd.createChar(1, upArrow);
  lcd.createChar(0, downArrow);
  lcd.begin(16, 2);
  lcd.setCursor(0,0);

  Serial.begin(9600);

  delay(1000);

  connectToEthernet();
}

void connectToEthernet() {
  // attempt to connect to Wifi network:
  // start the Ethernet connection:
  if (Ethernet.begin(mac) == 0) {
    Serial.println("Failed to configure Ethernet using DHCP waiting 1 minute");
    delay(millisecondsInAMinute);

    if (Ethernet.begin(mac) == 0)
    {
      Serial.println("Failed to configure Ethernet using DHCP waiting 1 more minute");
      delay(millisecondsInAMinute);

      if (Ethernet.begin(mac) == 0) {
        Serial.println("Failed to configure Ethernet using DHCP stopping - will need reset");
        while(true);
      }
    }

  }
  // give the Ethernet shield a second to initialize:
  delay(1000);
  Serial.println("connecting...");
  //lcd.print("connecting...");

  Serial.print("Connected to the network IP: ");
  Serial.println(Ethernet.localIP());
  //lcd.print("Network up...");
}

void loop() {
  displayData();

  Serial.println("fetched data");
  delay(millisecondsInAMinute * minutesBetweenCalls);
}

void displayData() {
  String data = receiveDataFromPompeii();

  if(data.length() > 0) {
    lcd.clear();
    lcd.home();

    String lastChar = "";
    if(data.endsWith(" U") || data.endsWith(" D") || data.endsWith(" L")){
      lastChar = data.substring(data.length() - 1);
      data = data.substring(0, data.length() - 1);
      Serial.println("last char " + lastChar);
    }
    Serial.println("display data " + data);

    if(data.length() > LCD_WIDTH) {
      lcd.home();
      lcd.print(data.substring(0, LCD_WIDTH));
      lcd.setCursor(0, 1);
      if(data.length() > (LCD_WIDTH * 2)) {
        lcd.print(data.substring(LCD_WIDTH, LCD_WIDTH * 2));
      }
      else {
        lcd.print(data.substring(LCD_WIDTH));
      }
    } 
    else {
      lcd.setCursor(0, 0);
      lcd.print(data);
    }

    if(lastChar == "U") {
      lcd.print((char) 1);
    } 
    else if (lastChar == "D") {
      lcd.print((char) 0);
    }
    else if (lastChar == "L") {
      lcd.print("-");
    }
  }
}

String receiveDataFromPompeii() {
  Serial.println("Request data from Pompeii");

  String response = "";

  if (pompeiiClient.connect(pompeii, pompeiiPort)) {
    Serial.println("connected to pompeii");
    // Make a HTTP request:
    pompeiiClient.print("GET ");
    pompeiiClient.print(pompeiiService);
    pompeiiClient.println(" HTTP/1.1");
    pompeiiClient.print("Host: ");
    pompeiiClient.print(pompeii);
    pompeiiClient.print(":");
    pompeiiClient.println(pompeiiPort);
    pompeiiClient.println("Accept: text/html, text/plain");
    pompeiiClient.println("Pragma: no-cache");
    pompeiiClient.println("Cache-Control: no-cache");
    pompeiiClient.println("Connection: close");
    pompeiiClient.println();

    Serial.println("Called pompeii");
    delay(3000);

    String dataRead = "";
    boolean reachedData = false;
    while (pompeiiClient.connected() || pompeiiClient.available()) {
      char c = pompeiiClient.read();
      //Serial.print(c);

      if( reachedData ) {
        response += c;
        //Serial.println(response);
      }

      dataRead += c;

      if(dataRead.endsWith("\r\n\r\n")) {
        Serial.println("Reached the data");
        reachedData = true;
      }
    }
    Serial.println("Finished reading data");

    pompeiiClient.stop();
    pompeiiClient.flush();
    Serial.println("Closed connection");
  }

  Serial.println("response data to return is " + response);
  return response;
}

* As any programmer knows, when you look at your old code, you think… “what on earth!” But also there was a technical reason for re-writing part of it (although I ended up re-writing it all) and that was to store the readings more locally rather than having to go out onto the internet to get the readings.