Friday, February 18, 2022

ESP Webserver tutorial part 4 - slider

For a complete index to all my articles click this text.

This is a series on building a webpage with the ESP8266 and the ESP32. When this series is completed all the information on building a webpage with buttons, textfields, sliders and color pickers witch have interaction with the ESP8266 or ESP32 will be discussed and demonstrated.

This fourth part leans heavy on the previous two parts in this series, so I urge you to read these stories first:

ESP webserver tutorial part 1 - textfields

ESP webserver tutorial part 2 - button
ESP webserver tutorial part 3 - Button with save

As you can see the previous stories showed you how to buid a webpage with a textfield, buttons and buttons with indicators that send feedback to the ESP on which it can respond. This way you can set for example led's, motors, relays, or lamps on or off.

However there is more as setting things on or off. Maybe you want to dim a lamp or have a motor running faster or slower. This can not be achieved with a simple on-off button. What we need to achieve this is a slider. So lets build a webpage that incorporates a slider.

The ESP8266 breadboard setup.

The breadboard setup is the same as in the previous story and as simple as it can be.



Just an ESP8266 (the Wemos D1 mini version) with a led and a current delimiting resistor attached to D5. Any ESP8266 like the NodeMCU will work. You could even adapt this foran ESP8266-01.

The ESP32 breadboard setup

The ESP32 breadboard setup is equally simple.



I am using the ESP32 Devkit board. These boards will not fit a breadboard. Therefore I use 2 breadboards. From one of these breadboards I stripped the power rail as discussed in the story you can read here:
https://lucstechblog.blogspot.com/2018/08/breadboard-hack-for-esp32-and-esp8266.html

The led is attached to GPIO32 through a 220 Ohm current delimiting resistor.

The program

Just like the previous entries in this series the program is written in Arduino language (C++) and is almost identical for the ESP8266 and the ESP32. The changes for the ESP32 are really minimal. I will give you the ESP8266 program as a whole and you can find the few lines which have to be modified for the ESP32 at the end of this story.


// ======================================================
// Libraries needed
// ======================================================

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

// Your credentials

ESP8266WebServer server(80);
const char* ssid = "XXXXXXXXXXXXXXX";
const char* password = "YYYYYYYYYYYYY";

int ledPin = D5; 

String responseHTML = ""
  "<!DOCTYPE html><html><head><title>CaptivePortal</title></head><body>"
  "<h1>Hello World!</h1><p>This is a captive portal example. All requests will "
  "be redirected here.</p></body></html>";

// ==========================================
// initial variables
// ========================================== 

int slider01value = 0;

// =========================================
// Build the webpage
// =========================================
String getPage(){
  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 slider test demo</title>";
  page += "<style>";
  page += "body { background-color: powderblue}";
  page += "</style>";
  page += "</head>";
  page += "<body>";
  page += "<h1 style='color:red'>Luc's slider test demo</h1>";

  page += "<form action=\"/\" method=\"post\">";
  page += "Move the slider for dimming the led :<br>";
  page += "<input type=\"range\" min=\"0\" max=\"255\" id=\"slider01\" name=\"slider01\" value=\"";
  page += slider01value;
  page +="\" class=\"slider\"> <br>";
  page += "<input type=\"submit\" value=\"Confirm\">";
  page += "</form>";
  page += "<br>";
  page += "<br>";
  page += "<br>";

  page += "</body>";
  page += "</html>";
  return page;
  }




// ==========================================
// Handle if unknown command
// ==========================================
void handleNotFound(){
  server.send(200, "text/html", getPage());
}


// ===========================================
// Submit page
// ===========================================
void handleSubmit(){
  if (server.hasArg("slider01")){
      slider01value = server.arg("slider01").toInt();
      Serial.print("The slider has value: ");
      Serial.println(slider01value);
      analogWrite(ledPin, slider01value);
      }

  server.send(200, "text/html", getPage());       //Response to the HTTP request
}  

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

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

  // WiFi initilisation part
  // 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);

}

//++++++++++++++++++++++++++++++++++++++++++++++//
//              LOOP                            //
//++++++++++++++++++++++++++++++++++++++++++++++//
void loop(){  
  server.handleClient(); 
  delay(50);
}

The program is almost identical to the program in the previous story. All explanation therefore has already been done except for the few lines that are needed for putting the slider on the screen. This is done in the <form> part of the webpage.

  page += "<form action=\"/\" method=\"post\">";

  page += "Move the slider for dimming the led :<br>";

  page += "<input type=\"range\" min=\"0\" max=\"255\" id=\"slider01\" name=\"slider01\" value=\"";

  page += slider01value;

  page +="\" class=\"slider\"> <br>";

  page += "<input type=\"submit\" value=\"Confirm\">";

  page += "</form>";

In HTML code a slider is represented by an input of the type range. As we are using it for sending PWM values to the ESP thye range is defined from 0 to 255. The HTML code will send the name "slider01" and its value to the ESP if you move the slider and press the confirm button.

If you have moved the slider and pressed the confirm button the value is send to the ESP and the handleSubmit() routine is activated.

// ===========================================
// Submit page
// ===========================================
void handleSubmit(){

  if (server.hasArg("slider01")){

      slider01value = server.arg("slider01").toInt();

      Serial.print("The slider has value: ");

      Serial.println(slider01value);

      analogWrite(ledPin, slider01value);

      }

As you can see the program tests if "slider01" is received and which value is received. The value is a string and with the command server.arg("slider01").toInt() converted into an integer value which then can be written to the D5 pin with the line: analogWrite(ledPin, slider01value);

ESP32 program.

We do have to make some changes for the ESP32. First the led is attached to pin 32 and therefore we have to change:

int ledPin = D5;

into:

int ledPin = 32;

And direct after this line you need to add the following lines:

const int freq = 5000;
const int ledChannel = 0;
const int resolution = 8;

These lines set the PWM frequency to 5000, tell the ESP32 that we are going to use channel 0 with an 8 bit resolution (255 steps).

Next in the setup we need to add some extra lines:

// =============================================
// Setup
// =============================================

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

  // WiFi initilisation part
  // 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);

  ledcSetup(ledChannel, freq, resolution);
  ledcAttachPin(ledPin, ledChannel);

}

The two last lines are the only change in the setup() routine. They activate the PWM with the chosen channel, frequency and resolution and then attach this information to the right IO pin.

Lastly he analogWrite command does not work with the ESP32 and therefore we need to make one alteration in the handleSubmit part of the program:

// ===========================================
// Submit page
// ===========================================

void handleSubmit(){
  if (server.hasArg("slider01")){
      slider01value = server.arg("slider01").toInt();
      Serial.print("The slider has value: ");
      Serial.println(slider01value);
      ledcWrite(ledChannel, slider01value);
      }

As you can see I replaced the analogWrite function with ledcWrite(ledChannel, slider01value); which sets the PWM value to the received slider01value.

Now your webpage with a slider will work on the ESP32.

Real world looks


And this is how the webpage will look on your computer screen or phone.

Expanding

Many months ago I wrote an article on this webpage about building a remote controlled car: http://lucstechblog.blogspot.com/2019/02/remote-controlled-car-with-wifi.html
 And even longer ago I wrote a story on controlling a strip of neopixels with a webpage that has 3 sliders: https://lucstechblog.blogspot.com/2018/03/rgb-strip-control-over-wifi-part-1.html

As an excercise you can rebuild these examples with the techniques described in this and the previous story. Rewrite the program in C++ in such a way that it can do the same as the ESPBasic program.

I'll give you a hint.


page += "<input type=\"range\" min=\"0\" max=\"255\" id=\"slider01\" name=\"slider01\" value=\"";

Copy this line in the form part 3 times and alter slider01 in slider02 and slider03

Make sure you declare the slider02value and slider03value at the beginning of the program.

In the handleSubmit routine copy the whole if() part 3 times so you can test for slider01, slider02 and slider03.

For the ESP32 you need to do some extra work, if you are building the remote controlled car, to get the PWM working for each motor. It should not prove too difficult.

Next time I will give you the complete program to get the neopixels strip working with this C++ webserver.

Till then !!
Have fun !!

Luc Volders