Hi,
I followed along the tutorial for setting up web server using ESP32. In my application I needed a simple slider and numeric read out. The slider works fine and the readout but each time I initially navigate to the web url, the value is always shown as “5”. Any idea what I could look for in the code to fix this and show correct value?
Hi David.
So, you’re saying that if you move the slider, the next time you access the web server, it’s value is always 5?
I’ve experimented the web server and if I move the slider, the next time I access the web server, it shows the previous value.
Or do you want it to display a different default value when you access it for the first time?
What browser are you using to access the web server? Are you experimenting on a PC or smartphone?
Regards,
Sara
Hi Sara,
I have copied the code below. I wonder if it has something to do with the size of “valueString”? This is the only place in my code I see a “5”. The code should receive the current value from my host controller via serial port on boot and set valueString to that value.
#include <WiFi.h>
#include <stdio.h>
#include <stdlib.h>
// Replace with your network credentials
const char* ssid = “BodyGuard”;
// Set web server port number to 80
WiFiServer server(80);
// Variable to store the HTTP request
String header;
// Decode HTTP GET value
String valueString = String(5);
int pos1 = 0;
int pos2 = 0;
int receivedValue =0;
int initialValue =0;
void setup() {
Serial.begin(115200);
WiFi.softAP(ssid);
IPAddress IP = WiFi.softAPIP();
Serial.print(“AP IP Address: “);
Serial.println(IP);
server.begin();
Serial2.begin(115200);
delay(3000);
Serial2.print(‘R’);
delay(250);
if(Serial2.available()>0){
receivedValue = Serial2.read();
Serial.println(receivedValue);
valueString = receivedValue;
Serial.println(valueString);
}
}
void loop(){
WiFiClient client = server.available(); // Listen for incoming clients
if (client) { // If a new client connects,
Serial.println(“New Client.”); // print a message out in the serial port
String currentLine = “”; // make a String to hold incoming data from the client
while (client.connected()) { // loop while the client’s connected
if (client.available()) { // if there’s bytes to read from the client,
char c = client.read(); // read a byte, then
Serial.write(c); // print it out the serial monitor
header += c;
if (c == ‘\n’) { // if the byte is a newline character
// if the current line is blank, you got two newline characters in a row.
// that’s the end of the client HTTP request, so send a response:
if (currentLine.length() == 0) {
// HTTP headers always start with a response code (e.g. HTTP/1.1 200 OK)
// and a content-type so the client knows what’s coming, then a blank line:
client.println(“HTTP/1.1 200 OK”);
client.println(“Content-type:text/html”);
client.println(“Connection: close”);
client.println();
// Display the HTML web page
client.println(“<!DOCTYPE html><html>”);
client.println(“<head><meta name=\”viewport\” content=\”width=device-width, initial-scale=1\”>”);
client.println(“<link rel=\”icon\” href=\”data:,\”>”);
// CSS to style the on/off buttons
// Feel free to change the background-color and font-size attributes to fit your preferences
client.println(“<style>body { text-align: center; font-family: \”Trebuchet MS\”, Arial; margin-left:auto; margin-right:auto;}”);
client.println(“.slider { width: 300px; }</style>”);
client.println(“<script src=\”https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js\”></script>”);
// Web Page
client.println(“</head><body><h1>BodyGuard Portable Detector</h1>”);
client.println(“<p>Range : <span id=\”servoPos\”></span></p>”);
client.println(“<input type=\”range\” min=\”1\” max=\”16\” class=\”slider\” id=\”servoSlider\” onchange=\”servo(this.value)\” value=\””+valueString+”\”/>”);
client.println(“<script>var slider = document.getElementById(\”servoSlider\”);”);
client.println(“var servoP = document.getElementById(\”servoPos\”); servoP.innerHTML = slider.value;”);
client.println(“slider.oninput = function() { slider.value = this.value; servoP.innerHTML = this.value; }”);
client.println(“$.ajaxSetup({timeout:1000}); function servo(pos) { “);
client.println(“$.get(\”/?value=\” + pos + \”&\”); {Connection: close};}</script>”);
client.println(“</body></html>”);
//GET /?value=180& HTTP/1.1
if(header.indexOf(“GET /?value=”)>=0) {
pos1 = header.indexOf(‘=’);
pos2 = header.indexOf(‘&’);
valueString = header.substring(pos1+1, pos2);
Serial2.print(‘S’+valueString);
Serial.println(valueString);
}
// The HTTP response ends with another blank line
client.println();
// Break out of the while loop
break;
} else { // if you got a newline, then clear currentLine
currentLine = “”;
}
} else if (c != ‘\r’) { // if you got anything else but a carriage return character,
currentLine += c; // add it to the end of the currentLine
}
}
}
// Clear the header variable
header = “”;
// Close the connection
client.stop();
Serial.println(“Client disconnected.”);
Serial.println(“”);
}
}
The valueString holds the value “5” for the first time you access the web server.
The next time you access the web server, it holds the previous value you have selected.
However, if you reset the ESP32, it “forgets” all the variables it have saved before. So, the valueString is again 5.
If you want to permanently save the last slider value, even if you reset the ESP32 or if it loses power, you can save the valueString value on the flash memory, and then, read its value at the beginning of the sketch. Learn more here: https://rntlab.com/module-2/esp32-flash-memory-store-permanent-data-write-and-read/
Regards,
Sara
I must have made a mistake in syntax, the “5” should have been defining number of elements for the array.
Maybe I should have declared like this char valueString[5]; or String valueString = “”;
The idea is the program starts up and receives the current value from the host via serial port and sets “valueString” using the received value.
Maybe I need to have the page with a button like “Connect” that then requests current value from the host and updates the value on screen properly in case host sends the value before ESP32 is ready?
Hi David.
I’m sorry, I thought you were using our code. Now, I see that it is a different code.
String(5) transforms 5 int number into a string “5”.
You can initialize an empty String, for example:
String valueString = “”;
To get the new valueString displayed on your web server, you just need to refresh the web server. Because we’re sending that variable to the client, when we receive a request:
client.println("<input type=\"range\" min=\"1\" max=\"16\" class=\"slider\" id=\"servoSlider\" onchange=\"servo(this.value)\" value=\""+valueString+"\"/>");
If you get a new valueString via Serial, it will only be updated on the web server, if you refresh the web page.
Depending on your application, you may consider using a different type of web server (async web server with events, for example).
Regards,
Sara
Hi,
I am doing another project using Arduino on the ESP32 this time. I am using the code from Unit 9 – ESP32 Control Server Motor, from Ebook, Learn ESP with Arduino IDE V2.1
I do not have a servo so just trying to get this running using a variable without servo control. I get the web page served up ok and see my heading and Slider but no value on screen for slider position and no get happening in the code.
I set the timeout to 6 seconds to have pleny of time.
Below is my code. Thanks
void check_for_wifi(void)
{
int pos1 = 0;
int pos2 = 0;
String header;
WiFiClient client = server.available();
if (client)
{
currentTime = millis();
previousTime = currentTime;
Serial.print(“Attached to wifi device\n”);
String currentLine = “”; // make a String to hold incoming data from the client
while (client.connected() && currentTime – previousTime <= timeoutTime)
{
currentTime = millis();
// loop while the client’s connected
if (client.available()) {
// if there’s bytes to read from the client,
char c = client.read(); // read a byte, then
Serial.write(c); // print it out the serial monitor
header += c;
if (c == ‘\n’)
{
// if the byte is a newline character
// if the current line is blank, you got two newline characters in a row.
// that’s the end of the client HTTP request, so send a response:
if (currentLine.length() == 0)
{
// HTTP headers always start with a response code (e.g. HTTP/1.1 200 OK)
// and a content-type so the client knows what’s coming, then a blank line:
client.println(“HTTP/1.1 200 OK”);
client.println(“Content-type:text/html”);
client.println(“Connection: close”);
client.println();
// the content of the HTTP response follows the header:
client.println(“<!DOCTYPE html><html>”);
client.println(“<head><meta name=\”viewport\”content = \”width=device-width, initial-scale=1\”>”);
client.println(“<link rel=\”icon\” href=\”data:,\”>”);
// CSS to style the on/off buttons
// Feel free to change the background-color and font-size attributes to fit your preferences
client.println(“<style>body { text-align: center; font-family:\”Trebuchet MS\”, Arial; margin-left:auto; margin-right:auto;}”);
client.println(“.slider { width: 300px; }</style>”);
client.println(“<script src = \”https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js\”></script > “);
client.println(“</head><body><h1>BodyGuard Config</h1>”);
client.println(“<p>Detection Range: <spanid = \”servoPos\”></span></p>”); //change servoPos to detection range func
client.println(“<input type=\”range\” min=\”1\” max=\”20\”class = \”slider\” id=\”servoSlider\” onchange=\”servo(this.value)\”value = \”” + valueString + “\”/>”);
client.println(“<script>var slider = document.getElementById(\”servoSlider\”);”);
client.println(“var servoP =document.getElementById(\”servoPos\”); servoP.innerHTML = slider.value;”);
client.println(“slider.oninput = function() { slider.value = this.value; servoP.innerHTML = this.value; }”);
client.println(“$.ajaxSetup({timeout:1000}); function servo(pos){ “);
client.println(“$.get(\”/?value=\” + pos + \”&\”); {Connection: close};}</script>”);
client.println(“</body></html>”);
//GET /?value=180& HTTP/1.1
if (header.indexOf(“GET /?value=”) >= 0)
{
pos1 = header.indexOf(‘=’);
pos2 = header.indexOf(‘&’);
valueString = header.substring(pos1 + 1, pos2);
//Rotate the servo
//myservo.write(valueString.toInt());
trip_distance = valueString.toInt();
Serial.println(valueString);
}
// The HTTP response ends with another blank line
client.println();
// Break out of the while loop
break;
}
else
{
// if you got a newline, then clear currentLine
currentLine = “”;
}
}
else if (c != ‘\r’)
{
currentLine += c;
}
}
}
// close the connection:
header = “”;
client.stop();
Serial.println(“Client Disconnected.”);
}
}
Hi.
Did you change anything on the code?
I’ve just tested the code and it is working just fine.
In your case, the value highlighted in the following picture is not showing?
What browser are you using?
Regards,
Sara
That is correct. The value does not display.
I am using samsung galaxy mobile phone to browes to site.
The problem is somewhere in these few lines and I cannot find it.
I can set up a value for slider (like 10) and when I run the code the slider moves to 10th position. When I move the slider I GET the correct value back at the ESP32 and can serial.print it to the monitor (so the GET and slider are working). But, I still see no value in the text with spanid = “rangeValue”
client.println(“<p>Detection Range<spanid = \”rangeValue\”></span></p>”);
client.println(“<input type=\”range\” min=\”1\” max=\”20\”class = \”slider\” id=\”rangeSlider\” onchange=\”range(this.value)\”value = \”” + valueString + “\”/>”);
client.println(“<script>var slider = document.getElementById(\”rangeSlider\”);”);
client.println(“var output =document.getElementById(\”rangeValue\”); output.innerHTML = slider.value;”);
client.println(“slider.oninput = function() { slider.value = this.value; output.innerHTML = this.value; }”);
client.println(“$.ajaxSetup({timeout:1000}); function range(pos){ “);
client.println(“$.get(\”/?value=\” + pos + \”&\”); {Connection: close};}</script>”);
client.println(“</body></html>”);
//GET /?value=180& HTTP/1.1
if (header.indexOf(“GET /?value=”) >= 0)
{
pos1 = header.indexOf(‘=’);
pos2 = header.indexOf(‘&’);
valueString = header.substring(pos1 + 1, pos2);
trip_distance = valueString.toInt();
Serial.println(valueString);
}
Using F12 function in Chrome, I can see where the error occurs but don’t know what is causing this.
On this line below I get error “Uncaught TypeError: Cannot set properties of null (setting ‘innerHTML’)”
client.println(“var output =document.getElementById(\”rangeValue\”); output.innerHTML = myslider.value;”);
Hi.
Please share your complete code with me. Otherwise, it is very difficult to debug.
Use pastebin, github, google drive or send me an email with the code with the correct formatting.
Regards,
Sara
I don’t believe your backslash escapes are working. Try using single quotes instead.
Thanks Steve,
I found a simpler example and it is now working but I need to figure out how to move the html and script back into flah under data folder. Also, need to add a button and figure out how to GET the button press.
Generally a button press generates a POST request. You’ll have to learn some Javascript to get it to generate a GET request.
Hi David.
We have several examples on our website that save the HTML into the filesystem.
We also have several tutorials that use sliders and buttons and add events to them using JavaScript.
Here are all our web server tutorials:
Check if any of those would help.
Regards,
Sara