Friday, October 14, 2022

ESP webpage with Gauges

For an index to all my stories click this text.

As some of my previous articles have shown you: an ESP8266 or ESP32 is capable of producing a webpage on which we can represent data, and put all kinds of buttons and sliders to control lights, motors etc. etc.

Until now I have presented this data in a rather dull way. Just a text on the screen that tells the temperature or the status of a sensor. While this works it is not an attractive way to show the data. Now look at the next picture.



Just look at that. Much nicer as just a text. This story tells how to put a Gauge on your ESP's webpage that shows the data of a sensor. I will give you the breadboard setup and code for both the ESP8266 and the ESP32

This story relies heavily on the article I wrote about making Gauges with Javascript. So I urge you to read that story before you jump into the pool. You can re-read that story here: http://lucstechblog.blogspot.com/2019/11/gauges-and-linecharts-in-javascript.html

What we basically are going to do is to attach a sensor to an ESP8266 or ESP32. Then in the program we build a webpage which shows the value of that sensor on a Gauge. So some basic understanding of building webpages with the ESP8266 or ESP32 will come in handy. I did an extensive series on that which you can find here:
http://lucstechblog.blogspot.com/2019/07/esp-webserver-tutorial-part-1-textfields.html
http://lucstechblog.blogspot.com/2019/07/esp-webserver-tutorial-part-2-button.html
http://lucstechblog.blogspot.com/2019/08/esp-webserver-tutorial-part-3-button.html
http://lucstechblog.blogspot.com/2019/08/esp-webserver-tutorial-part-4-slider.html

https://lucstechblog.blogspot.com/2019/09/esp-webserver-tutorial-part-5-neopixel.html

I use a Dallas DS18B20 temperature sensor for this purpose but you can easily change the code for using it with an LDR or potmeter or any other sensor that supplies a value.

The code for the ESP32 is almost similar to the code for the ESP8266. The code is written in C++ more broadly known as Arduino language. You'll find the complete program further on and after the explanation I'll give you the necessary changes for the ESP32 which are minimal.

ESP8266 Breadboard setup

For this example I am going to use the usual breadboard setup for a Dallas DS18B20 thermometer with a Wemos D1 mini.



The Dallas DS18B20 Thermometer does not use a lot of current so can be powered directly from the ESP8266. The sensor is connected to D4 of the ESP8266 and uses a 4.7k pull-up resistor. You can use any other IO pin as long as you adjust the program.

ESP32 breadboard setup

The ESP32 breadboard setup is taken from my book about the ESP32. You can find a link to my book at the bottom of this page.



The Dallas DS18B20 is attached to IO pin 23 (D23) but you may attach it to another pin if that is more suitable for your own project. Just do not forget to adjust the program accordingly.

ESP8266 Program

As stated before this program leans heavy on two previous discussed programs: ESP webserver and Javascript Gauges. Find the links to these programs and stories at the beginning of this entry. Please re-read these stories for a complete understanding of this program.

As usual I will give you the complete code first.


// ======================================================
// Webserver program that sends temperature information
// as a Gauge to a webpage.
// by Luc Volders
// ======================================================

#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>

ESP8266WebServer server(80);

#include <OneWire.h>
#include <DallasTemperature.h>

#define ONE_WIRE_BUS D4

// Setup a oneWire instance 
OneWire oneWire(ONE_WIRE_BUS);

// Pass our oneWire reference to Dallas Temperature. 
DallasTemperature sensors(&oneWire);

// Your routers credentials
const char* ssid = "XXXXXXXXXXXXXXXXX";
const char* password = "YYYYYYYYYYYYYYY";

// =========================================
// This is where we build the HTML page
// =========================================
String getPage()
  {
  sensors.requestTemperatures();
  String page = "<!DOCTYPE HTML>";
  page += "<html>";
  page += "<head>";
  page += "<meta name = \"viewport\" content = \"width = device-width, initial-scale = 1.0 maximum-scale = 2.5, user-scalable=1\">";
  page += "<title>Luc's Gauge demo</title>";
  page += "<body style='background-color:powderblue;'>";
  page += "<style>";
  page += "</style>";
  page += "</head>";
  page += "<body>";
  
  page += "<h1 style='color:red'>Hobby room";
  page += "<br>";
  page += "temperature</h1>";
  
  page += "<div id='gauge_div' style='width:280px; height: 140px;'></div>";
  page += "<br>";
  
  page += "<FORM action=\"/\" method=\"post\">";
  page += "<button type=\"submit\" name=\"button1\" id=\"button1\" value=\"but1\" onclick=\'update()\'>CLICK FOR UPDATE</button>";
  page += "</form>";
  
  page += "<script type='text/javascript' src='https://www.gstatic.com/charts/loader.js'></script>";
  page += "<script type='text/javascript'>";
  page += "google.charts.load('current', {'packages':['gauge']});";
  page += "google.charts.setOnLoadCallback(drawGauge);";

  page += "var gaugeOptions = {min: -15, max: 50,";
  // yellow color changed to blue
  page += "yellowColor: '#1a66ff',";
  page += "yellowFrom: -15, yellowTo: 15,";
  page += "greenFrom: 15, greenTo: 25,";
  page += "redFrom: 25, redTo: 50, minorTicks: 5};";
  page += "var gauge;";

  page += "function drawGauge() {";
  page += "gaugeData = new google.visualization.DataTable();";
  page += "gaugeData.addColumn('number', 'Temp.');";
  page += "gaugeData.addRows(1);";
  page += "gaugeData.setCell(0, 0,";
  page += String(int(sensors.getTempCByIndex(0)));
  page += ");";
  page += "gauge = new google.visualization.Gauge(document.getElementById('gauge_div'));";
  page += "gauge.draw(gaugeData, gaugeOptions);";
  page += "}";

  page += "function update() {";
  page += "}";
 
  page += "</script>";  
  page += "</body>";
  page += "</html>";
  return page;
  }


// ==================================================
// Handle for page not found
// ==================================================
void handleNotFound()
{
  server.send(200, "text/html", getPage());
}


// ==================================================
// Handle submit form
// ==================================================
void handleSubmit()
{   
   if (server.hasArg("button1"))
      {
      Serial.print("The temperature is: ");
      Serial.print(int(sensors.getTempCByIndex(0)));
      Serial.println(" degrees C");
      } 
  server.send(200, "text/html", getPage());       //Response to the HTTP request
}  


// ===================================================
// Handle root
// ===================================================
void handleRoot() 
{   
  if (server.args() ) 
    {
    handleSubmit();
    } 
  else 
    {
    server.send(200, "text/html", getPage());  
    }
}


// ===================================================
// Setup
// ===================================================
void setup()
{
  delay(1000);
  Serial.begin(115200);

  // Connect to Wi-Fi network with SSID and password
  Serial.print("Connecting to ");
  Serial.println(ssid);
  WiFi.begin(ssid,password);
  while (WiFi.status() != WL_CONNECTED) 
  {
    delay(500);
    Serial.print(".");
  }
  // Print local IP address and start web server
  Serial.println("");
  Serial.println("WiFi connected.");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());
  
  server.begin();
  server.on("/", handleRoot);
  server.onNotFound(handleNotFound);
  server.begin();
  delay(500);

  // Start up the library
  sensors.begin();
}


// ===================================================
// Loop
// ===================================================
void loop()
{  
  server.handleClient(); 
  delay(50);
}

Let's have a closer look at the code so you may change it for your own purposes.

The first part of the program contains the obvious things. The libraries for the webserver and Dallas DS18B20 are loaded and the OneWire library also.


#define ONE_WIRE_BUS D4

This line is important cause here is defined at which pin the Dallas DS18B20 is connected.  I used D4 but you can change that to any other pin that might be more practical for you.


// Your routers credentials
const char* ssid = "XXXXXXXXXXXXXXXXXXXXXX";
const char* password = "YYYYYYYYYYYYYYYYYYYYYY";

Do not forget to change the XXXX and YYYY in these lines to your own routers name and password.

In the getPage() routine the webpage is build. I will not go over this as it was covered in the stories about building a webpage. I will just highlight the important parts.

sensors.requestTemperatures();

This line makes sure that the Dallas DS18B20 is activated.

page += "<div id='gauge_div' style='width:280px; height: 140px;'></div>";

In this line the space on the webpage is created that will contain the Gauge. Both the width and the height of the Gauge are defined. Alter these to your own whishes or likings.

  page += "<FORM action=\"/\" method=\"post\">";
  page += "<button type=\"submit\" name=\"button1\" id=\"button1\" value=\"but1\" onclick=\'update()\'>CLICK FOR UPDATE</button>";
  page += "</form>";

The above lines put a button on the webpage below the Gauge. Pressing the button wil send a signal to the ESP and the page will be updated with the temperature at this moment.

  page += "<script type='text/javascript' src='https://www.gstatic.com/charts/loader.js'></script>";
  page += "<script type='text/javascript'>";
  page += "google.charts.load('current', {'packages':['gauge']});";
  page += "google.charts.setOnLoadCallback(drawGauge);";

The Javascript library for the Gauge is loaded from the internet, and activated.

  page += "var gaugeOptions = {min: -15, max: 50,";
  // yellow color changed to blue
  page += "yellowColor: '#1a66ff',";
  page += "yellowFrom: -15, yellowTo: 15,";
  page += "greenFrom: 15, greenTo: 25,";
  page += "redFrom: 25, redTo: 50, minorTicks: 5};";
  page += "var gauge;";

Here is a nice trick. The variable gaugeOptions defines that the Gauge will show temperatures from -15 to 50 degrees Celsius.
My gauge starts its scale in blue. Blue is the color that represents cold. However the Google Charts library does not recognise blue as a standard color. So I redefine yellowColor to '#1a66ff' which is blue.

There is a simple way to get RGB codes for your own purpose. You can find that method in a previous story I published on this weblog and which you can find here:
http://lucstechblog.blogspot.com/2019/10/choosing-colors-for-webpage-or-for.html

The lines also define where the blue, green and red legends start and end. In this example the blue runs from -15 to 15 degrees which I define as cold. The green which I see as a bearable temperature runs from 15 to 25 degrees and above that I think it is too hot and the scale is in red.

  page += "gaugeData.setCell(0, 0,";
  page += String(int(sensors.getTempCByIndex(0)));
  page += ");";

Here the cell in the datalist (0, 0) that contains the temperature is altered in such a way that it is filled with the value from the DS18B20.

If you do not own a DS18B20 you can alter the second line to a different sensor reading.

Suppose you own an LDR or a potmeter. Attach that to the analog input pin A0 and alter the second line to:

page += String(int(analogRead(A0));

In this case you need to alter the Gauges scale too.

page += "var gaugeOptions = {min: -15, max: 50,";

The values should then be altered to min: 0 and max: 1024.

Do not forget to alter the lines in the handleSubmit() routine and the setup() routine to what is needed for your sensor.

Thats all.

ESP32 Changes

The Changes for the ESP32 are as mentioned before minimal.

#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>


ESP8266WebServer server(80);

Have to be changed in:

#include <WiFi.h>
#include <WebServer.h>


WebServer server(80);

You also will need to change the line that defines where the Dallas DS18B20 is connected.

#define ONE_WIRE_BUS D4

Change the D4 in 23 as the thermometer will be connected to D23 on the ESP23. You may alter this to your own liking if you have altered the connectio on the breadboard.

That's all.

Gauges on the webpage

Start the program and open the Serial Monitor in the Arduino IDE. The Serial monitor will show you the IP adress of the ESP. You can also find it in your router like I described in the web-server stories.

Copy the IP number and put it in the URL field of your browser and the webpage with the Gauge will appear in the browsers window. It looks like the page shown at the beginning of this story.


This is how it looks on a phone's webpage.

Click the button for the current temperature.

Have fun

Luc Volders