Introduction: How to Control ELEGOO 28BYJ-48 Stepper Motors With ESP32 Wirelessly

This Is My First Time Creating An Instructables So Sorry If Its Bad Im Just try To Help People. I Use This For Many This Including Opening And Closing My Blinds And My Vent. If You Have Questions Or Need Help Or Even Have Any Suggestions Comment Them Below

Supplies

  • ELEGOO 28BYJ-48 Stepper Motor With ULN2003 Driver Board (Amazon Link)
  • Some Jumper Wires
  • ESP32

Step 1: Connect ULN2003 Driver Board to ESP32

Connect IN1 To Pin 13 On ESP32 (Could Also Be D13 Or G13)

Connect IN2 To Pin 12 On ESP32 (Could Also Be D12 Or G12)

Connect IN3 To Pin 14 On ESP32 (Could Also Be D14 Or G14)

Connect IN4 To Pin 27 On ESP32 (Could Also Be D27 Or G27)

You Can Either Connect The Positive And Negative To The 5V (As VIN On ESP32) And The GND On The ESP32 Or You Can Use A Separate Adapter For 12V To Make It More Powerful

Step 2: Arduino Setting

Step 3: Upload Code to ESP32

Open Arduino IDE And Paste The Code Below

const int CW =1;
const int CCW =2;
const int STOP =3;


int Pin1 = 13;//IN1 is connected to 13
int Pin2 = 12;//IN2 is connected to 12  
int Pin3 = 14;//IN3 is connected to 14
int Pin4 = 27;//IN4 is connected to 27


long angles[] = {360, 270, 90, 20, 287, 2000, 2000};//angles of each push button
int directions[] ={CW, CCW, CW, CCW, CW, CW, CCW};//direction of eacch push button
int speedFactors[] = {10, 1, 4, 10, 2, 1, 1};//speed for each push button
const String statusTitle[]={
            "Motor sent to ",
            "Motor sent to ",
            "Motor sent to ",
            "Motor sent to ",
            "Motor sent to "};


const String directionTitle[]={"CW", "CCW"};
const String stopPushButtonTitle="STOP";
const String topTitle1 ="° in ";
const String topTitle2 ="Speed factor: ";


const String topTitle3 ="Angle: ";
const String topTitle4 ="Direction: ";
const String topTitle5 =", Speed: ";
const String topTitle6 ="Send";
const String customMainTitle ="( C )Motor sent to ";


const int customValueButtonID=99;
const String motorStopped ="Motor Stopped";


int correction_CW = 150;//watch video for details
int correction_CCW = 150;//watch video for details

int poleStep = 0;
long stepVale =0;
const int SPR=64*64;
long goToAngle=0;
int activeButton=0;
int speedValue =1;


int pole1[] ={0,0,0,0, 0,1,1,1, 0};//pole1, 8 step values
int pole2[] ={0,0,0,1, 1,1,0,0, 0};//pole2, 8 step values
int pole3[] ={0,1,1,1, 0,0,0,0, 0};//pole3, 8 step values
int pole4[] ={1,1,0,0, 0,0,0,1, 0};//pole4, 8 step values

int count=0;
int  dirStatus = STOP;// stores direction status 3= stop (do not change)


#include <WiFi.h>
#include <WiFiClient.h>
#include <WebServer.h>
#include <ESPmDNS.h>


const char *ssid = "SSIDHERE";
const char *password = "PASSWORDHERE";


WebServer server(80);


void handleRoot() {
  //Robojax.com ESP32 Stepper Push button Any Angle ESPSTP-2
 String HTML ="<!DOCTYPE html>\
  <html>\
  <head>\
  \t\n<title>Robojax ESP32 Stepper Motor</title>\
  \t\n<meta name=\"viewport\" content=\"width=device-width, initial-scale=1\">\
  \n<style>\
 \nhtml,body{\t\nwidth:100%\;\nheight:100%\;\nmargin:0}\n*{box-sizing:border-box}\n.colorAll{\n\tbackground-color:#90ee90}\n.colorBtn{\n\tbackground-color:#add8e6}\n.angleButtdon,a{\n\tfont-size:30px\;\nborder:1px solid #ccc\;\ndisplay:table-caption\;\npadding:7px 10px\;\ntext-decoration:none\;\ncursor:pointer\;\npadding:5px 6px 7px 10px}a{\n\tdisplay:block}\n.btn{\n\tmargin:5px\;\nborder:none\;\ndisplay:inline-block\;\nvertical-align:middle\;\ntext-align:center\;\nwhite-space:nowrap}\n";

  HTML +="</style>\n\n</head>\n\n<body>\n<h1>Robojax ESP32 Stepper ESPSTP-2  </h1>\n";


    if(dirStatus !=STOP && activeButton !=customValueButtonID ){


          HTML +="\n\t<h2><span style=\"background-color: #FFFF00\">";  
          HTML +=statusTitle[activeButton];    
          HTML +=String(angles[activeButton]);  
          HTML +=topTitle1;                        
          HTML +=directionTitle[directions[activeButton]-1]; //subtract 1 to get proper title  
          HTML +="</span></h2>\n";

          HTML +="\n\t<h2>";                                
          HTML +=topTitle2;          
          HTML +=String(speedFactors[activeButton]);
          HTML +="<span style=\"background-color: #FFFF00\"> (";
          float  timeTakes =(float)speedFactors[activeButton] * float(angles[activeButton]) * ((float)4/(float)360);//calculat the time that takes to move to that angle
          HTML +=String(timeTakes);                              
          HTML +=" seconds)";                    
          HTML +="</span></h2>\n";            

   }if(activeButton ==customValueButtonID ){


          HTML +="\n\t<h2><span style=\"background-color: #FFFF00\">";  
          HTML +=customMainTitle;    
          HTML +=String(goToAngle);  
          HTML +=topTitle1;                        
          HTML +=directionTitle[dirStatus-1]; //subtract 1 to get proper title  
          HTML +="</span></h2>\n";

          HTML +="\n\t<h2>";                                
          HTML +=topTitle2;          
          HTML +=String(speedValue);
          HTML +="<span style=\"background-color: #FFFF00\"> (";
          float  timeTakes =(float)speedValue * float(goToAngle) * ((float)4/(float)360);//calculat the time that takes to move to that angle
          HTML +=String(timeTakes);                              
          HTML +=" seconds)";                    
          HTML +="</span></h2>\n";            

   }else if(dirStatus ==STOP)
   {
    HTML +="\n\t<h2><span style=\"background-color: #FFFF00\">";
    HTML +=motorStopped;
    HTML +="</span></h2>\n";          
   }


        HTML +="\t<div class=\"btn\">\n\t\t<a class=\"angleButton\" style=\"background-color:#";
        HTML +="f59898";//set the color of buttons if active or not
        HTML +="\t\"  href=\"/stop";              
        HTML +="\">";      
        HTML +=stopPushButtonTitle;//tilte on button
       HTML +="</a>\t\n\t</div>\n\n";  
 for (byte i = 0; i < (sizeof(angles) / sizeof(angles[0])); i++) {


        HTML +="\t<div class=\"btn\">\n\t\t<a class=\"angleButton\" style=\"background-color:#";
        if(i ==activeButton)
        {
          HTML +="f59898";//set the color of buttons if active or not
        }else{
          HTML +="90ee90";//set the color of buttons if active or not
        }


        HTML +="\t\"  href=\"/go?";              
        HTML +="angle=";
        HTML +=angles[i];
        HTML +="\">";      
        HTML +=angles[i];//tilte on button


     HTML +="&deg; "; //degree symbol for HTML &deg;
     HTML +=directionTitle[directions[i]-1];
     HTML +="</a>\t\n\t</div>\n\n"; //degree symbol for HTML &deg;    
   }


  //custom angle
  HTML +="<form action=\"/go\" method=\"get\">\n";  


  HTML +="<label for=\"angle\">\n";
  HTML += topTitle3;  
  HTML +="</label> \n";  
  HTML +="<input type=\"text\" id=\"angle\" name=\"angle\" value=\"\n";
  HTML +=String(goToAngle);
  HTML +="\"  maxlength=\"4\" size=\"4\"> \n";    


  HTML +="<input type=\"radio\" id=\"cw\" \n";
  if( dirStatus  ==1){
    HTML +="checked=\"checked\"";
  }
  HTML +=" name=\"d\" value=\"1\">\n";    
  HTML +="<label for=\"cw\">CW</label>\n";

  HTML +="<input type=\"radio\" id=\"ccw\" \n";
  if( dirStatus  ==2){
    HTML +="checked=\"checked\"";
  }
  HTML +=" name=\"d\" value=\"2\">\n";  
  HTML +="<label for=\"female\">CCW</label>\n";


  HTML +="<label for=\"spd\">\n";
  HTML +=topTitle5;
  HTML +="</label> \n";    
  HTML +="<input type=\"text\" id=\"spd\" name=\"s\" value=\"1\"  maxlength=\"2\" size=\"4\"><br>\n";

  HTML +="<input type=\"submit\" value=\"\n";  
  HTML +=topTitle6;
  HTML +="\">\n";    
  HTML +="</form> \n\n";


  HTML +="\t\n</body>\n</html>\n";
  server.send(200, "text/html", HTML);  
  //Robojax.com ESP32 Stepper Push button Any Angle ESPSTP-2  
}//handleRoot()


void handleNotFound() {
  //Robojax.com ESP32 Stepper Push button Any Angle ESPSTP-2
  String message = "File Not Found\n\n";
  message += "URI: ";
  message += server.uri();
  message += "\nMethod: ";
  message += (server.method() == HTTP_GET) ? "GET" : "POST";
  message += "\nArguments: ";
  message += server.args();
  message += "\n";


  for (uint8_t i = 0; i < server.args(); i++) {
    message += " " + server.argName(i) + ": " + server.arg(i) + "\n";
  }


  server.send(404, "text/plain", message);
  //Robojax.com ESP32 Stepper Push button Any Angle ESPSTP-2
}//end of handleNotFound()


void setup(void) {
  //Robojax.com 28BYJ-48 Stepper Motor Control

 pinMode(Pin1, OUTPUT);//define pin for ULN2003 in1
 pinMode(Pin2, OUTPUT);//define pin for ULN2003 in2  
 pinMode(Pin3, OUTPUT);//define pin for ULN2003 in3  
 pinMode(Pin4, OUTPUT);//define pin for ULN2003 in4    



  Serial.begin(115200);//initialize the serial monitor
  Serial.println("Robojax 28BYJ-48 Stepper Motor Control");


  //Robojax.com ESP32 Stepper Push button Any Angle ESPSTP-2

  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);
  Serial.println("");

  // Wait for connection
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }


  Serial.println("");
  Serial.print("Connected to ");
  Serial.println(ssid);
  Serial.print("IP address: http://");
  Serial.println(WiFi.localIP());


//multicast DNS   //Robojax.com 28BYJ-48 Steper Motor Control
  if (MDNS.begin("robojaxESP32")) {
    Serial.println("MDNS responder started");
    Serial.println("access via http://robojaxESP32");
  }


  server.on("/", handleRoot);
  server.on("/go", HTTP_GET, motorControl);
  server.on("/stop",HTTP_GET, stopMotor);

  server.onNotFound(handleNotFound);
  server.begin();
  Serial.println("HTTP server started");


}//end of setup


void loop(void) {
  //Robojax.com ESP32 Stepper Push button Any Angle ESPSTP-2
  server.handleClient();


    stepVale = (SPR * goToAngle)/360 ;


 if(poleStep>7){
   poleStep=0;
 }
 if(poleStep<0){
   poleStep=7;
 }



 if(dirStatus ==CCW){

   poleStep++;
   count++;  
   if(count+correction_CCW <= stepVale)
   {
    driveStepper(poleStep);      
   }else{
      driveStepper(8);  
   }
  //full explannation at Arduino Course on Udemy.com see link above
 }else if(dirStatus ==CW){
   poleStep--;
   count++;  
   if(count+correction_CW <=stepVale)
   {
    driveStepper(poleStep);      
   }else{
      driveStepper(8);  
   }  
 }else{
  driveStepper(8);    
 }

  delay(speedValue);

   //Robojax.com ESP32 Stepper Push button Any Angle ESPSTP-2
}//end of loop


/*
 * motorControl()
 * updates the motor parameters upon receiving request from web interface
 * returns nothing
 * written by Ahmad Shamshiri
 * on Wednesday Jun 13, 2020 in Ajax, Ontario, Canada
 * www.robojax.com
 */
void motorControl() {
  //Robojax.com ESP32 Stepper Push button Any Angle ESPSTP-2
//Watch details at my Arduino Course at Udemy.com
   //see this https://www.arduino.cc/reference/en/language/variables/utilities/sizeof/
 for (byte i = 0; i < (sizeof(angles) / sizeof(angles[0])); i++) {
   if(server.arg("angle") == String(angles[i]) )
   {
      goToAngle =angles[i];
      dirStatus =directions[i];
      count =0;
      activeButton =i;  
      speedValue=speedFactors[i];
   }//if
 }//for
//Watch details at my Arduino Course at Udemy.com
   if(server.arg("d").toInt() >0 )
   {
      goToAngle =server.arg("angle").toInt();
      dirStatus =server.arg("d").toInt();
      count =0;
      activeButton =customValueButtonID;  
      speedValue=server.arg("s").toInt();    
   }


  handleRoot();
  //Robojax.com ESP32 Stepper Push button Any Angle ESPSTP-2 code  
}//motorControl end


/*
 * @brief sends signal to the motor
 * @param "c" is integer representing the pol of motor
 * @return does not return anything
 *
 * www.Robojax.com code June 2019
 */
void driveStepper(int c)
{
  //Watch details at my Arduino Course at Udemy.com
     digitalWrite(Pin1, pole1[c]);  
     digitalWrite(Pin2, pole2[c]);
     digitalWrite(Pin3, pole3[c]);
     digitalWrite(Pin4, pole4[c]);  
  //Robojax.com ESP32 Stepper Push button Any Angle ESPSTP-2 code    
}//driveStepper end here


/*
 * @brief stops the motor immediately
 * @param none
 * @return does not return anything
 * written by Ahmad Shamshiri
 * www.Robojax.com code June 13, 2020 in Ajax, Ontario, Canada
 */
void stopMotor()
{
  //Robojax.com ESP32 Stepper Push button Any Angle ESPSTP-2 code
  //Watch details at my Arduino Course at Udemy.com
  dirStatus=STOP;
  handleRoot();
}//stopMotor()


Step 4: Code Explained

Change The SSID And PASSWORD To Your Internet Details

const char *ssid = "SSIDHERE";
const char *password = "PASSOWORDHERE";


There Are Custom Angle Already Set But You Can Set Your Own By Changing The Code. You Can Add The Angle By Adding A Comma Then Space Then Your Angle

long angles[] = {360, 270, 90, 20, 287};//angles of each push button


Make Sure You Set Weather It Turns Clockwise Or Counter Clockwise By Adding CW Or CCW

int directions[] ={CW, CCW, CW, CCW, CW};//direction of eacch push button


You Can Set The Speed Of It By Adding A Number 1 Thorough 10, 1 Being The Fastest And 10 Being The Slowest

int speedFactors[] = {10, 1, 4, 10, 2, 1, 1};//speed for each push button

Step 5: How to Start

After You Upload The Code Open Serial Monitor By Pressing CONTROL+SHIFT+M Or By Going To TOOLS Then Serial Monitor. Make Sure The Baud Is Set To 115200

Step 6: Next

After You Open Serial Monitor Unplug Then Plug Back In Your ESP32 You Will See A Link Go To That Link And You Will See The Image Above


Step 7: Help

If You Need Any Help Or Have Any Questions Post A Comment Below Or Join My Discord Server https://discord.gg/Cq7tSEfaC2