Help with ESP8266 web (servo) server and javascript sliders

Hello all,

I am trying to use the web interface to control two servos using sliders with code found on the net (for using with one servo/slider). I modified it as much as I could but still the code works with only one slider... or both sliders move the same servo.
I think the issue lies somewhere in the PageIndex.h file... (no programming experience..just trail and error..)
In the PageIndex.h file there are two script sections, each for each servo. I found out that if I commend the first script section, the second slider moves the second servo. If I commend the second script section, the first slider moves the first servo.
Unfortunately I don't now further and would need help.

The code I am using:


#include <ESP8266WiFi.h>
#include <ESP8266WebServer.h>
//----------------------------------------Include the Servo Library
#include <Servo.h>

#include "PageIndex.h"; //--> Include the contents of the User Interface Web page, stored in the same folder as the .ino file

#define LEDonBoard 2  //--> Defining an On Board LED, used for indicators when the process of connecting to a wifi router
#define ServoPort D1   //--> Defining Servo Port
#define ServoPort2 D3   //--> Defining Servo2 Port

//----------------------------------------SSID and Password of your WiFi router
const char *ssid = "wifi_name";
const char *password = "wifi_password";
//----------------------------------------

Servo myservo;  //--> create servo object to control a servo
Servo myservo2;  //--> create servo2 object to control a servo2
ESP8266WebServer server(80);  //--> Server on port 80

//----------------------------------------This routine is executed when you open NodeMCU ESP8266 IP Address in browser
void handleRoot() {
 String s = MAIN_page; //Read HTML contents
 server.send(200, "text/html", s); //Send web page
}
//----------------------------------------

//----------------------------------------Procedure for handling servo control
void handleServo(){
  String POS = server.arg("servoPOS");
  int pos = POS.toInt();
  myservo.write(pos);   //--> Move the servo motor according to the POS value
  delay(15);
  Serial.print("Servo Angle:");
  Serial.println(pos);
  server.send(200, "text/plane","");
}

void handleServo2(){
  String POS2 = server.arg("servoPOS2");
  int pos2 = POS2.toInt();
  myservo2.write(pos2);   //--> Move the servo2 motor according to the POS2 value
  delay(15);
  Serial.print("Servo2 Angle:");
  Serial.println(pos2);
  server.send(200, "text/plane","");
}


//----------------------------------------
//----------------------------------------Setup----------------------------------------
void setup() {
  Serial.begin(115200);
  delay(1000);
  
  WiFi.begin(ssid, password); //--> Connect to your WiFi router
  Serial.println("");
    
  pinMode(LEDonBoard,OUTPUT); //--> On Board LED port Direction output
  digitalWrite(LEDonBoard, HIGH); //--> Turn off Led On Board

  myservo.attach(ServoPort); //--> attaches the servo on D1 to the servo object
  myservo2.attach(ServoPort2); //--> attaches the servo on D1 to the servo object
  //----------------------------------------Wait for connection
  Serial.print("Connecting");
  while (WiFi.status() != WL_CONNECTED) {
    Serial.print(".");
    //----------------------------------------Make the On Board Flashing LED on the process of connecting to the wifi router.
    digitalWrite(LEDonBoard, LOW);
    delay(250);
    digitalWrite(LEDonBoard, HIGH);
    delay(250);
    //----------------------------------------
  }
  //----------------------------------------
  digitalWrite(LEDonBoard, HIGH); //--> Turn off the On Board LED when it is connected to the wifi router.
  //----------------------------------------If connection successful show IP address in serial monitor
  Serial.println("");
  Serial.print("Successfully connected to : ");
  Serial.println(ssid);
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());
  //----------------------------------------

  //----------------------------------------Initialize Webserver
  server.on("/",handleRoot);  //--> Routine to handle at root location. This is to display web page.
  server.on("/setPOS",handleServo); //--> Sets servo position from Web request
  server.on("/setPOS2",handleServo2); //--> Sets servo2 position from Web request
  server.begin();  
  Serial.println("HTTP server started");
}
//------------------------------------------------------------------------------------
//----------------------------------------Loop----------------------------------------
void loop() {
 server.handleClient();
}
//------------------------------------------------------------------------------------

And here is the content of the PageIndex.h file with both sections uncommented. (both sliders move the same servo -- servo2)


const char MAIN_page[] PROGMEM = R"=====(
<!DOCTYPE html>
<html>
  <head>
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <style>
      html {
        font-family: Arial;
        display: inline-block;
        margin: 0px auto;
        text-align: center;
      }
      
      .slidecontainer {
        width: 100%;
      }

      .slider {
        -webkit-appearance: none;
        width: 50%;
        height: 15px;
        border-radius: 5px;
        background: #d3d3d3;
        outline: none;
        opacity: 0.7;
        -webkit-transition: .2s;
        transition: opacity .2s;
      }

      .slider:hover {
        opacity: 1;
      }

      .slider::-webkit-slider-thumb {
        -webkit-appearance: none;
        appearance: none;
        width: 25px;
        height: 25px;
        border-radius: 50%;
        background: #4CAF50;
        cursor: pointer;
      }

      .slider::-moz-range-thumb {
        width: 25px;
        height: 25px;
        border-radius: 50%;
        background: #4CAF50;
        cursor: pointer;
      }


      
    </style>
  </head>
  <body>

    <h1>NodeMCU ESP8266 / ESP12E Control Servo SG90</h1>
    <br><br>
    <div class="slidecontainer">
      <input type="range" min="0" max="180" value="90" class="slider" id="myRange">
      <p>Value : <span id="demo"></span></p>
    </div>

        <div class="slidecontainer">
      <input type="range" min="0" max="180" value="90" class="slider" id="myRange2">
      <p>Value : <span id="demo2"></span></p>
    </div>


    <script>
      function sendData(pos) {
        var xhttp = new XMLHttpRequest();
        xhttp.onreadystatechange = function() {
          if (this.readyState == 4 && this.status == 200) {
            console.log(this.responseText);
          }
        };
        xhttp.open("GET", "setPOS?servoPOS="+pos, true);
        xhttp.send();
      } 
      var slider = document.getElementById("myRange");
      var output = document.getElementById("demo");
      output.innerHTML = slider.value;

      slider.oninput = function() {
        output.innerHTML = this.value;
        sendData(output.innerHTML);
      }
    </script>

<script>
  function sendData(pos2) {
        var xhttp = new XMLHttpRequest();
        xhttp.onreadystatechange = function() {
          if (this.readyState == 4 && this.status == 200) {
            console.log(this.responseText);
          }
        };
        xhttp.open("GET", "setPOS2?servoPOS2="+pos2, true);
        xhttp.send();
      } 
      var slider2 = document.getElementById("myRange2");
      var output2 = document.getElementById("demo2");
      output2.innerHTML2 = slider2.value;

      slider2.oninput = function() {
        output2.innerHTML2 = this.value;
        sendData(output2.innerHTML2);
      }
</script>

  </body>
</html>
)=====";


Thank you in advance!

"innerHTML2"?? That just looks wrong. I strongly suspect it should be simply "innerHTML".

Have you looked at the web console in your browser? I would bet you will see that flagged as an error.

Hi,
Thanks for the reply.
I've corrected the innerHTML2 issue but it doesn't work as expected.
Both sliders still move the same servo, servo2.
Below the current sections:

   <div class="slidecontainer">
      <input type="range" min="0" max="180" value="90" class="slider" id="myRange">
      <p>Value : <span id="demo"></span></p>
    </div>

        <div class="slidecontainer2">
      <input type="range" min="0" max="180" value="90" class="slider2" id="myRange2">
      <p>Value : <span id="demo2"></span></p>
    </div>


    <script>
      function sendData(pos) {
        var xhttp = new XMLHttpRequest();
        xhttp.onreadystatechange = function() {
          if (this.readyState == 4 && this.status == 200) {
            console.log(this.responseText);
          }
        };
        xhttp.open("GET", "setPOS?servoPOS="+pos, true);
        xhttp.send();
      } 
      var slider = document.getElementById("myRange");
      var output = document.getElementById("demo");
      output.innerHTML = slider.value;

      slider.oninput = function() {
        output.innerHTML = this.value;
        sendData(output.innerHTML);
      }
    </script>


<script>
  function sendData(pos2) {
        var xhttp = new XMLHttpRequest();
        xhttp.onreadystatechange = function() {
          if (this.readyState == 4 && this.status == 200) {
            console.log(this.responseText);
          }
        };
        xhttp.open("GET", "setPOS2?servoPOS2="+pos2, true);
        xhttp.send();
      } 
      var slider2 = document.getElementById("myRange2");
      var output2 = document.getElementById("demo2");
      output2.innerHTML = slider2.value;

      slider2.oninput = function() {
        output2.innerHTML = this.value;
        sendData(output2.innerHTML);
      }
</script>

Thank you

Hi,
Any other input is welcome.
Thanks

You could find some ideas here
https://tttapa.github.io/ESP8266/Chap14%20-%20WebSocket.html

have a look at esp32-web-server-websocket-sliders

Hi,
Thank you the suggestions.
I ended up using this code with a ESP32:

 
#include <Arduino.h>
#include <WiFi.h>
#include <AsyncTCP.h>
#include <ESPAsyncWebServer.h>
#include <iostream>
#include <sstream>
#include <ESP32Servo.h>

 
#define PAN_PIN 13
#define TILT_PIN 14
#define LEDonBoard 2 // define onboard led pin 2
Servo panServo;
Servo tiltServo;


const char* ssid     = "wifi_name_here";
const char* password = "wifi_password";

AsyncWebServer server(80);
AsyncWebSocket wsServoInput("/ServoInput");


const char* htmlHomePage PROGMEM = R"HTMLHOMEPAGE(
<!DOCTYPE html>
<html>
  <head>
  <meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
    <style>
    .noselect {
      -webkit-touch-callout: none; /* iOS Safari */
        -webkit-user-select: none; /* Safari */
         -khtml-user-select: none; /* Konqueror HTML */
           -moz-user-select: none; /* Firefox */
            -ms-user-select: none; /* Internet Explorer/Edge */
                user-select: none; /* Non-prefixed version, currently
                                      supported by Chrome and Opera */
    }
    .slidecontainer {
      width: 100%;
    }
    .slider {
      -webkit-appearance: none;
      width: 100%;
      height: 11px;
      border-radius: 5px;
      background: #d3d3d3;
      outline: none;
      opacity: 0.7;
      -webkit-transition: .2s;
      transition: opacity .2s;
    }
    .slider:hover {
      opacity: 1;
    }
  
    .slider::-webkit-slider-thumb {
      -webkit-appearance: none;
      appearance: none;
      width: 30px;
      height: 30px;
      border-radius: 50%;
      background: #29b6f6;
      cursor: pointer;
    }
    .slider::-moz-range-thumb {
      width: 30px;
      height: 30px;
      border-radius: 50%;
      background: #29b6f6;
      cursor: pointer;
    }
    </style>
  
  </head>
  <body class="noselect" align="center" style="background-color:white">
     
    <!--h2 style="color: teal;text-align:center;">Wi-Fi Camera &#128663; Control</h2-->
    
    <table id="mainTable" style="width:400px;margin:auto;table-layout:fixed" CELLSPACING=5>
         <td style="text-align:right"><b>Pan:</b></td>
        <td colspan=3>
         <div class="slidecontainer">
            <input type="range" min="0" max="180" value="90" class="slider" id="Pan" oninput='sendButtonInput("Pan",value)'>
          </div>
        </td>
      </tr> 
      <tr/><tr/>       
      <tr>
        <td style="text-align:right"><b>Tilt:</b></td>
        <td colspan=3>
          <div class="slidecontainer">
            <input type="range" min="0" max="180" value="90" class="slider" id="Tilt" oninput='sendButtonInput("Tilt",value)'>
          </div>
        </td>   
      </tr>
      <tr/><tr/>       
    </table>
  
    <script>
      var webSocketServoInputUrl = "ws:\/\/" + window.location.hostname + "/ServoInput";      
      var websocketServoInput;
      
      
      function initServoInputWebSocket() 
      {
        websocketServoInput = new WebSocket(webSocketServoInputUrl);
        websocketServoInput.onopen    = function(event)
        {
          var panButton = document.getElementById("Pan");
          sendButtonInput("Pan", panButton.value);
          var tiltButton = document.getElementById("Tilt");
          sendButtonInput("Tilt", tiltButton.value);
     
        };
        websocketServoInput.onclose   = function(event){setTimeout(initServoInputWebSocket, 2000);};
        websocketServoInput.onmessage = function(event){};        
      }
      
      function initWebSocket() 
      {
          initServoInputWebSocket();
      }
      function sendButtonInput(key, value) 
      {
        var data = key + "," + value;
        websocketServoInput.send(data);
      }
    
      window.onload = initWebSocket;
      document.getElementById("mainTable").addEventListener("touchend", function(event){
        event.preventDefault()
      });      
    </script>
  </body>    
</html>
)HTMLHOMEPAGE";

void handleRoot(AsyncWebServerRequest *request) 
{
  request->send_P(200, "text/html", htmlHomePage);
}

void handleNotFound(AsyncWebServerRequest *request) 
{
    request->send(404, "text/plain", "File Not Found");
}

void onServoInputWebSocketEvent(AsyncWebSocket *server, 
                      AsyncWebSocketClient *client, 
                      AwsEventType type,
                      void *arg, 
                      uint8_t *data, 
                      size_t len) 
{                      
  switch (type) 
  {
    case WS_EVT_CONNECT:
      Serial.printf("WebSocket client #%u connected from %s\n", client->id(), client->remoteIP().toString().c_str());
      break;
    case WS_EVT_DISCONNECT:
      Serial.printf("WebSocket client #%u disconnected\n", client->id());
      panServo.write(90);
      tiltServo.write(90);
      break;
    case WS_EVT_DATA:
      AwsFrameInfo *info;
      info = (AwsFrameInfo*)arg;
      if (info->final && info->index == 0 && info->len == len && info->opcode == WS_TEXT) 
      {
        std::string myData = "";
        myData.assign((char *)data, len);
        Serial.printf("Key,Value = [%s]\n", myData.c_str());        
        std::istringstream ss(myData);
        std::string key, value;
        std::getline(ss, key, ',');
        std::getline(ss, value, ',');
        if ( value != "" )
        {
          int valueInt = atoi(value.c_str());
          if (key == "Pan")
          {
            panServo.write(valueInt);
          }
          else if (key == "Tilt")
          {
            tiltServo.write(valueInt);   
          }
         
        }
      }
      break;
    case WS_EVT_PONG:
    case WS_EVT_ERROR:
      break;
    default:
      break;  
  }
}


void setUpPinModes()
{ 
  panServo.attach(PAN_PIN);
  tiltServo.attach(TILT_PIN);
  pinMode(LEDonBoard,OUTPUT);
}

void setup(void) 
{
  setUpPinModes();
  Serial.begin(115200);

  WiFi.begin(ssid, password); //--> Connect to your WiFi router
  Serial.println("");
 

  server.on("/", HTTP_GET, handleRoot);
  server.onNotFound(handleNotFound);
      
  wsServoInput.onEvent(onServoInputWebSocketEvent);
  server.addHandler(&wsServoInput);

  server.begin();
  Serial.println("HTTP server started");
  Serial.print("Connecting");
  while (WiFi.status() != WL_CONNECTED) {
    Serial.print(".");
    //----------------------------------------Make the On Board Flashing LED on the process of connecting to the wifi router.
    digitalWrite(LEDonBoard, LOW);
    delay(250);
    digitalWrite(LEDonBoard, HIGH);
    delay(250);
    //----------------------------------------
  }
  //----------------------------------------
  digitalWrite(LEDonBoard,LOW);  // >> Turm off onboard LED when it is connected successfully
  //----------------------------------------
 
  //----------------------------------------If connection successful show IP address in serial monitor
  Serial.println("");
  Serial.print("Successfully connected to : ");
  Serial.println(ssid);
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());
  //----------------------------------------
}


void loop() 
{
   wsServoInput.cleanupClients(); 
}

This topic was automatically closed 180 days after the last reply. New replies are no longer allowed.