ESP8266 Webserver Multiple Servo Motor Control

 



Welcome back, everyone! Due to popular demand, I’ve created a new project that showcases how to control multiple servo motors using an ESP8266 via a Wi-Fi Soft Access Point (AP) web server. This project is ideal for anyone looking to expand their knowledge in electronics, specifically with the use of ESP8266 and servo motors.

In this project, I will guide you through setting up a web server on the ESP8266 that allows you to control several servo motors simultaneously. By creating a web interface, you can adjust the angles of the servos using sliders and buttons from any device connected to the ESP8266’s network. This makes it a versatile project for applications in robotics, home automation, and other DIY electronics projects.

The ESP8266 is a powerful and affordable microcontroller with built-in Wi-Fi capabilities, making it perfect for IoT projects. By utilizing its Wi-Fi feature, we can create a web server that can be accessed through any web browser, eliminating the need for additional hardware or complicated setups. This makes the project more accessible and easier to implement for hobbyists and enthusiasts alike.

You can also adjust the code in the Arduino IDE according to your specific requirements. The flexibility of this project allows for various customizations, whether you need to control more servos, integrate additional sensors, or modify the web interface to better suit your needs. The Arduino IDE provides a user-friendly environment to write, compile, and upload code to the ESP8266, ensuring that even beginners can follow along and succeed.

Simply follow the steps outlined in my video, and you'll have your multi-servo controller up and running in no time. The video provides a detailed, step-by-step tutorial, covering everything from the initial setup to the final testing of your servo motors. Whether you're a seasoned maker or just starting out, this project is a great way to enhance your skills and explore the capabilities of the ESP8266.

Part Needed:- 

1x ESP8266 NodeMCU

4x Servo Motor

1x NeoPixel LED Ring(This is option you can use or not depends on you)

Some Jumper Wires

5V 1 Amps Power Supply  

Schematic:-


Follow this Schematic to make this make sure power is correct or checked properly. You can Build in breadboard or simply solder components on breadboard.

     +5V    Power Supply    GND

ESP8266 Module Pins

Components

Yes

Yes

Digital Pin 1

Servo Motor 1

Yes

Yes

Digital Pin 2

Servo Motor 2

Yes

Yes

Digital Pin 6

Servo Motor 3

Yes

Yes

Digital Pin 7

Servo Motor 4

Yes

Yes

Digital Pin 5

NeoPixel LED Input

 
If you face any problem regarding with Power fluctuation which with 5V. You can simply add 220uF 25V Capacitor or upgrade the voltage with 6V-7V with precaution of Microcontroller which can be burn. 

The Main Code:-

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

// Include the HTML file
#include "webpage.h"


// Wi-Fi credentials
const char* ssid = "ESP8266-Servo"; // You can Change the SSID here 
const char* password = "password";  // You can also change the Password here

// NeoPixel configuration
#define LED_PIN    D5
#define NUM_LEDS   16

Adafruit_NeoPixel pixels(NUM_LEDS, LED_PIN, NEO_GRB + NEO_KHZ800);

// Create web server object
ESP8266WebServer server(80);

// Create servo objects
Servo servo1, servo2, servo3, servo4;
int pos1 = 90, pos2 = 90, pos3 = 90, pos4 = 90; // Initial positions for servos

void setup() {
  // Initialize serial communication
  Serial.begin(115200);
  Serial.println("NeoPixel Loading Effect");

  // Initialize NeoPixel
  pixels.begin();
  pixels.show(); // Initialize all pixels to 'off'

  // Set up servos
  servo1.attach(D1);
  servo2.attach(D2);
  servo3.attach(D6);
  servo4.attach(D7);
  servo1.write(pos1);
  servo2.write(pos2);
  servo3.write(pos3);
  servo4.write(pos4);

  // Set up Wi-Fi
  WiFi.softAP(ssid, password);

  // Define web server routes
  server.on("/", handleRoot);
  server.on("/servo1", handleServo1);
  server.on("/servo2", handleServo2);
  server.on("/servo3", handleServo3);
  server.on("/servo4", handleServo4);
  server.onNotFound(handleNotFound);

  // Start web server
  server.begin();
  Serial.println("HTTP server started");

  // Start the NeoPixel loading effect
  startLoadingEffect();
}

void loop() {
  // Handle client requests
  server.handleClient();
}

void handleRoot() {
  String html = FPSTR(webpage); // Use the stored HTML page
  server.send(200, "text/html", html);
}

void handleServo1() {
  if (server.hasArg("pos")) {
    pos1 = server.arg("pos").toInt();
    servo1.write(pos1);
    updateLoadingEffect();
  }
  server.send(200, "text/plain", "OK");
}

void handleServo2() {
  if (server.hasArg("pos")) {
    pos2 = server.arg("pos").toInt();
    servo2.write(pos2);
    updateLoadingEffect();
  }
  server.send(200, "text/plain", "OK");
}

void handleServo3() {
  if (server.hasArg("pos")) {
    pos3 = server.arg("pos").toInt();
    servo3.write(pos3);
    updateLoadingEffect();
  }
  server.send(200, "text/plain", "OK");
}

void handleServo4() {
  if (server.hasArg("pos")) {
    pos4 = server.arg("pos").toInt();
    servo4.write(pos4);
    updateLoadingEffect();
  }
  server.send(200, "text/plain", "OK");
}

void handleNotFound() {
  server.send(404, "text/plain", "404: Not Found");
}

void startLoadingEffect() {
  int delayTime = 50; // Adjust speed of loading effect (smaller value = faster)

  // Gradient filling effect
  for (int i = 0; i < NUM_LEDS; i++) {
    for (int hue = 0; hue <= 255; hue++) {
      // Calculate brightness based on current hue position
      uint8_t brightness = map(hue, 0, 255, 0, 255);

      // Set color with adjusted brightness
      pixels.setPixelColor(i, pixels.ColorHSV(hue, 255, brightness));
      pixels.show();
      delayMicroseconds(delayTime * 100); // Adjust speed more smoothly
    }
    delay(delayTime * 5); // Pause between each LED filling
  }

  Serial.println("Loading complete!");
}

void updateLoadingEffect() {
  int position = (pos1 + pos2 + pos3 + pos4) / 4; // Calculate average position
  int hue = map(position, 0, 180, 0, 65535); // Map servo position to hue
  for (int i = 0; i < NUM_LEDS; i++) {
    pixels.setPixelColor(i, pixels.ColorHSV(hue, 255, 255));
  }
  pixels.show();
}

Now Open New tab by pressing (Crtl+Shift+N) and rename it this webpage.h and save and

then paste this Web code.

 

const char webpage[] PROGMEM = R"=====(
<!DOCTYPE html>
<html>
<head>
  <meta name='viewport' content='width=device-width, initial-scale=1'/>
  <title>ESP8266 Servo Control</title>
  <style>
    body {
      font-family: Arial, sans-serif;
      text-align: center;
      background: linear-gradient(to right, #00c6ff, #0072ff);
      color: white;
    }
    h1 {
      color: #ffcc00;
    }
    .slider-container {
      margin: 20px auto;
      width: 80%;
      max-width: 600px;
    }
    .slider {
      width: 100%;
      margin: 10px 0;
    }
    .button {
      background-color: #6a1b9a;
      border: none;
      color: white;
      padding: 15px 32px;
      text-align: center;
      text-decoration: none;
      display: inline-block;
      font-size: 16px;
      margin: 4px 2px;
      cursor: pointer;
      border-radius: 8px;
      transition-duration: 0.4s;
    }
    .button:hover {
      background-color: white;
      color: black;
      border: 2px solid #6a1b9a;
    }
  </style>
  <script>
    function updateServo(servo, value) {
      fetch(`/${servo}?pos=${value}`);
    }
  </script>
</head>
<body>
  <h1>ESP8266 Servo Control</h1>
  <div class="slider-container">
    <input type="range" min="0" max="180" value="90" class="slider" id="servo1" oninput="updateServo('servo1', this.value)">
    <button class="button" onclick="updateServo('servo1', 0)">0&deg;</button>
    <button class="button" onclick="updateServo('servo1', 45)">45&deg;</button>
    <button class="button" onclick="updateServo('servo1', 90)">90&deg;</button>
    <button class="button" onclick="updateServo('servo1', 180)">180&deg;</button>
  </div>
  <div class="slider-container">
    <input type="range" min="0" max="180" value="90" class="slider" id="servo2" oninput="updateServo('servo2', this.value)">
    <button class="button" onclick="updateServo('servo2', 0)">0&deg;</button>
    <button class="button" onclick="updateServo('servo2', 45)">45&deg;</button>
    <button class="button" onclick="updateServo('servo2', 90)">90&deg;</button>
    <button class="button" onclick="updateServo('servo2', 180)">180&deg;</button>
  </div>
  <div class="slider-container">
    <input type="range" min="0" max="180" value="90" class="slider" id="servo3" oninput="updateServo('servo3', this.value)">
    <button class="button" onclick="updateServo('servo3', 0)">0&deg;</button>
    <button class="button" onclick="updateServo('servo3', 45)">45&deg;</button>
    <button class="button" onclick="updateServo('servo3', 90)">90&deg;</button>
    <button class="button" onclick="updateServo('servo3', 180)">180&deg;</button>
  </div>
  <div class="slider-container">
    <input type="range" min="0" max="180" value="90" class="slider" id="servo4" oninput="updateServo('servo4', this.value)">
    <button class="button" onclick="updateServo('servo4', 0)">0&deg;</button>
    <button class="button" onclick="updateServo('servo4', 45)">45&deg;</button>
    <button class="button" onclick="updateServo('servo4', 90)">90&deg;</button>
    <button class="button" onclick="updateServo('servo4', 180)">180&deg;</button>
  </div>
</body>
</html>
)=====";

First open the Arduino IDE and Paste the all code step by step which you need to add one tab and rename it.
After Pasting all the code Select the ESP8266 board as your specifications and choose the right Com port then Compile and Upload the code on ESP8266 NodeMCU and Power it up. 

LED Update 




 In this project, I added a 16 bit NeoPixel Ring LED to visually indicate the servo motor movements. The Neopixel ring is connected to the ESP8266, typically using a single data pin. For this project, we use pin D5 on the ESP8266 to control the Neopixel LEDs. The Adafruit Neopixel library is essential for managing the LED animations which is In the loop, you can synchronize the Neopixel LEDs with the servo motor positions. For instance, when you update the servo angles, you can call the startLoadingEffect() to visually represent the change:

  void updateServoAndLED(int servoAngle) {
    servo.write(servoAngle);
    startLoadingEffect();
  }

This integration not only makes the project functional but also adds a dynamic visual element, enhancing the user experience by providing immediate feedback through the LED ring. The Neopixel LEDs change color and brightness in sync with the servo motor movements, making it easier to monitor the servo positions visually.

Now Fun 

This project not only enhances your skills in working with microcontrollers and IoT but also opens up numerous possibilities for your own creative applications in robotics and home automation.

Feel free to customize the code and hardware setup to suit your specific needs and share your own modifications and ideas in the comments below. Your feedback is invaluable and helps us improve and bring more exciting projects to the community.

Thank you for following along with this tutorial. Don't forget to check out my other projects and subscribe to my YouTube channel for more in-depth guides and innovative ideas. Happy building!


Comments