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

Friday, February 11, 2022

Watch your print orientation to save some time

For an index to all my stories click this text.

I was working on a project that needed a frame to hold a servo. A prototype of the frame was made in cardboard. And then I drew the frame in Tinkercad and imported it into my slicer for 3D printing.


 

The slicer indicated that it would take 5 hours and 48 minutes to print the design. Well as it is a hobby I do not care too much about time. And besides that, I can do other things while the printer is busy.

Then I decided to rotate the frame so that it would lay on its back. And guess what.....the print time reduced with about an hour !!! The print would take now 4 hours 59 minutes.

Like said I do not care too much for print time, however I do not like to leave my printer unattended. There are a few stories around about a 3D printer cathing a fire. So I am cautious.

Just be aware that changing the print orientation might influence the strength of your print. So this will not work out well for every print. But in this case it did not matter.

So experiment with your print orientation and you might save some time.

And remember that if your print is to big for your printbed, or takes too long to print in one day you can always cut it up in several parts:
http://lucstechblog.blogspot.com/2015/03/cutting-up-designs-in-tinkercad-in-my.html

Till next time.
Have fun

Luc Volders

Friday, February 4, 2022

ESP32 cam with Octoprint

 For an index to all my stories click this text.

As you will know by now I have been playing with the ESP32-cam module lately. I build a programming board for it, which makes life a lot easier. You can read that story here: http://lucstechblog.blogspot.com/2021/12/esp32-cam-programming-board-revisited.html

And there was a modification for that board which in certain circumstances makes sending pictures a lot faster: http://lucstechblog.blogspot.com/2021/12/esp32-cam-programming-board-revisited.html

And here is a small experimenting board for the ESP32-CAM: http://lucstechblog.blogspot.com/2021/10/esp32cam-experiment-board.html

For those who have no clue on what this is about: the ESP32-cam board is an ESP32 with an OV2640 camera which gives a decent picture (for a board of a few dollar anyhow) and I have a few plans for this.

My 3D printer is controlled by Octoprint. I have an USB camera attached and Octoprint will send a notification to my phone when a print has finished. Besides that I can watch proceedings on my phone or tablet from the Octoprint web-page whenever I want. The USB webcam has a low resolution (640 x 480) but it does the job. The ESP32-cam has a better resolution but is wireless and I wondered how difficult it would be to use that.

It took time.

Actually it took me some time before I had the wireless ESP32-cam working with Octoprint. Not that is was difficult to get it working, but there is few documentation on this subject and you have to use the right settings in Octoprint. Finding the settings was the time consuming part. So you will find them here a bit further on.

Installing the ESP32-cam in Octoprint.

First thing to do is to get the ESP32-cam working. If it works you can see the picture on a web-page in your PC.
To find the IP adress of the ESP32-cam just look into your router. My router shows all IP adresses of all attached (wired and wireless). I have demonstrated in previous stories on how to do that. You can read an example here: http://lucstechblog.blogspot.com/2020/01/sending-data-from-esp-to-domoticz.html
In my particular case the ESP32-cam has the IPnumber 192.168.1.84

If you know the IP-number we can go on to the next step.



Open Octoprints web-page and press on the wrench at the top-right side of the page that will open the settings page.



First enable the web-cam support with the radio button.

In the Stream URL enter: http://192.168.1.84:81/stream

Replace the 192.168.1.84 with the IP-number of your ESP32-cam. Add :81 after the IP-number and then /stream.
So in your case the command should be:
http://YOURIPNUMBER:81/stream

Finding the port number (81) took me a considerable time. So this makes it easy for you.



Press the test button and a small screen should open that shows the webcam stream.

It does not work.

Well it did not work on my end either at first until I realised something.
I had the ESP32-cam webpage still open on my PC. And there was the pitfall. The ESP32-cam can only stream to one device. So it streams to Octoprint or it streams to your PC. Not both at the same time.

When I closed the webpage on the PC everything worked as it should.



And there it is. The picture of my printerbed.

All in all a very cheap solution if you need a webcam for checking your 3D printer.

Till next time.
Have fun

Luc Volders