Kabar Terkini

Servo + NodeMCU Esp8266

 


Download file BIN:










Coding 1

( Link Simulasi: https://wokwi.com/projects/343390109446439507 )

Servo + NodeMCU Esp8266:


#include <Servo.h>


Servo myservo;  

int sudut= 90;


void setup(){

 myservo.attach(D0); 

}


void loop(){

myservo.write(sudut); 

}



Coding 2

Servo + OTA + NodeMCU Esp8266


/*******************

Servo Gerak 3 Sudut dg Esp8266

plus:

- AccessPoint AP

- WebServer

- OTA

iot2 - fajar himawan

********************/


#include <ESP8266WiFi.h> 

#include <ESP8266WebServer.h> 

#include <ArduinoOTA.h>


#include <Servo.h>


Servo myservo;  

int sudut1= 0;

int sudut2= 90;

int sudut3= 180;


const int wifiLedPin = D0;  // set digital pin D0 as indication, the LED turn on if NodeMCU connected to WiFi as STA mode



ESP8266WebServer server(80);      // Create a webserver object that listens for HTTP request on port 80


unsigned long previousMillis = 0;


String sta_ssid = "ota";      // set Wifi networks you want to connect to

String sta_password = "12345678";  // set password for Wifi networks



void setup(){

    

    myservo.attach(D4); 

    

  Serial.begin(115200);    // set up Serial library at 115200 bps

  Serial.println();

  Serial.println("*WiFi Robot Remote Control Mode - L298N 2A*");

  Serial.println("------------------------------------------------");

 


  pinMode(wifiLedPin, OUTPUT);  // sets the Wifi LED pin as an Output


  digitalWrite(wifiLedPin, HIGH);  

      


  

  // set NodeMCU Wifi hostname based on chip mac address

  String chip_id = String(ESP.getChipId(), HEX);

  int i = chip_id.length()-4;

  chip_id = chip_id.substring(i);

  chip_id = "07-IOT-" + chip_id;

  String hostname(chip_id);

  

  Serial.println();

  Serial.println("Hostname: "+hostname);


  // first, set NodeMCU as STA mode to connect with a Wifi network

  WiFi.mode(WIFI_STA);

  WiFi.begin(sta_ssid.c_str(), sta_password.c_str());

  Serial.println("");

  Serial.print("Connecting to: ");

  Serial.println(sta_ssid);

  Serial.print("Password: ");

  Serial.println(sta_password);


  // try to connect with Wifi network about 1 seconds

  unsigned long currentMillis = millis();

  previousMillis = currentMillis;

  while (WiFi.status() != WL_CONNECTED && currentMillis - previousMillis <= 1500) {

    delay(500);

    Serial.print(".");

    currentMillis = millis();

  }


  // if failed to connect with Wifi network set NodeMCU as AP mode

  if (WiFi.status() == WL_CONNECTED) {

    Serial.println("");

    Serial.println("*WiFi-STA-Mode*");

    Serial.print("IP: ");

    Serial.println(WiFi.localIP());

    digitalWrite(wifiLedPin, LOW);    // Wifi LED on when connected to Wifi as STA mode

    delay(3000);

  } else {

    WiFi.mode(WIFI_AP);

    WiFi.softAP(hostname.c_str());

    IPAddress myIP = WiFi.softAPIP();

    Serial.println("");

    Serial.println("WiFi failed connected to " + sta_ssid);

    Serial.println("");

    Serial.println("*WiFi-AP-Mode*");

    Serial.print("AP IP address: ");

    Serial.println(myIP);

    digitalWrite(wifiLedPin, HIGH);   // Wifi LED off when status as AP mode

    delay(1000);

  }

 


  server.on ( "/", HTTP_handleRoot );       // call the 'handleRoot' function when a client requests URI "/"

  server.onNotFound ( HTTP_handleRoot );    // when a client requests an unknown URI (i.e. something other than "/"), call function "handleNotFound"

  server.begin();                           // actually start the server

  

  ArduinoOTA.begin();                       // enable to receive update/uploade firmware via Wifi OTA

}




void loop() {

       

    ArduinoOTA.handle();          // listen for update OTA request from clients

    server.handleClient();        // listen for HTTP requests from clients

    

    delay (1000);

    myservo.write(sudut1);

    delay (1000);

    myservo.write(sudut2);

    delay (1000);

    myservo.write(sudut3);

      

}



// function prototypes for HTTP handlers

void HTTP_handleRoot(void){

  server.send ( 200, "text/html", "" );       // Send HTTP status 200 (Ok) and send some text to the browser/client

  

  if( server.hasArg("State") ){

     Serial.println(server.arg("State"));

  }

}


void handleNotFound(){

  server.send(404, "text/plain", "404: Not found"); // Send HTTP status 404 (Not Found) when there's no handler for the URI in the request

}



Coding 3

Servo + RECORD + NodeMCU Esp8266

Rekam Gerak Servo ESP8266


/*


#include <Arduino.h>

#include <WiFi.h>

#include <AsyncTCP.h>

#include <ESPAsyncWebServer.h>


#include <ESP32Servo.h>

#include <iostream>

#include <sstream>


*/


#include <Arduino.h>

#include <ESP8266WiFi.h>

#include <ESPAsyncTCP.h>

#include <ESPAsyncWebServer.h>


#include <Servo.h>

#include <iostream>

#include <sstream>



#include <ArduinoOTA.h>

    



struct ServoPins

{

  Servo servo;

  int servoPin;

  String servoName;

  int initialPosition;  

};

std::vector<ServoPins> servoPins = 

{

  { Servo(), D1 , "Base", 90},

  { Servo(), D2 , "Shoulder", 90},

  { Servo(), D3 , "Elbow", 90},

  { Servo(), D4 , "Gripper", 90},

};


struct RecordedStep

{

  int servoIndex;

  int value;

  int delayInStep;

};

std::vector<RecordedStep> recordedSteps;


bool recordSteps = false;

bool playRecordedSteps = false;


unsigned long previousTimeInMilli = millis();


const char* ssid     = "wificarjurnalku";

const char* password = "wificarjurnalku";


AsyncWebServer server(80);

AsyncWebSocket wsRobotArmInput("/RobotArmInput");


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>


    input[type=button]

    {

      background-color:red;color:white;border-radius:30px;width:100%;height:40px;font-size:20px;text-align:center;

    }

        

    .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: 20px;

      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: 40px;

      height: 40px;

      border-radius: 50%;

      background: red;

      cursor: pointer;

    }


    .slider::-moz-range-thumb {

      width: 40px;

      height: 40px;

      border-radius: 50%;

      background: red;

      cursor: pointer;

    }


    </style>

  

  </head>

  <body class="noselect" align="center" style="background-color:white">

     

    <h1 style="color: teal;text-align:center;">Hash Include Electronics</h1>

    <h2 style="color: teal;text-align:center;">Robot Arm Control</h2>

    

    <table id="mainTable" style="width:400px;margin:auto;table-layout:fixed" CELLSPACING=10>

      <tr/><tr/>

      <tr/><tr/>

      <tr>

        <td style="text-align:left;font-size:25px"><b>Gripper:</b></td>

        <td colspan=2>

         <div class="slidecontainer">

            <input type="range" min="0" max="180" value="90" class="slider" id="Gripper" oninput='sendButtonInput("Gripper",value)'>

          </div>

        </td>

      </tr> 

      <tr/><tr/>

      <tr>

        <td style="text-align:left;font-size:25px"><b>Elbow:</b></td>

        <td colspan=2>

         <div class="slidecontainer">

            <input type="range" min="0" max="180" value="90" class="slider" id="Elbow" oninput='sendButtonInput("Elbow",value)'>

          </div>

        </td>

      </tr> 

      <tr/><tr/>      

      <tr>

        <td style="text-align:left;font-size:25px"><b>Shoulder:</b></td>

        <td colspan=2>

         <div class="slidecontainer">

            <input type="range" min="0" max="180" value="90" class="slider" id="Shoulder" oninput='sendButtonInput("Shoulder",value)'>

          </div>

        </td>

      </tr>  

      <tr/><tr/>      

      <tr>

        <td style="text-align:left;font-size:25px"><b>Base:</b></td>

        <td colspan=2>

         <div class="slidecontainer">

            <input type="range" min="0" max="180" value="90" class="slider" id="Base" oninput='sendButtonInput("Base",value)'>

          </div>

        </td>

      </tr> 

      <tr/><tr/> 

      <tr>

        <td style="text-align:left;font-size:25px"><b>Record:</b></td>

        <td><input type="button" id="Record" value="OFF" ontouchend='onclickButton(this)'></td>

        <td></td>

      </tr>

      <tr/><tr/> 

      <tr>

        <td style="text-align:left;font-size:25px"><b>Play:</b></td>

        <td><input type="button" id="Play" value="OFF" ontouchend='onclickButton(this)'></td>

        <td></td>

      </tr>      

    </table>

  

    <script>

      var webSocketRobotArmInputUrl = "ws:\/\/" + window.location.hostname + "/RobotArmInput";      

      var websocketRobotArmInput;

      

      function initRobotArmInputWebSocket() 

      {

        websocketRobotArmInput = new WebSocket(webSocketRobotArmInputUrl);

        websocketRobotArmInput.onopen    = function(event){};

        websocketRobotArmInput.onclose   = function(event){setTimeout(initRobotArmInputWebSocket, 2000);};

        websocketRobotArmInput.onmessage    = function(event)

        {

          var keyValue = event.data.split(",");

          var button = document.getElementById(keyValue[0]);

          button.value = keyValue[1];

          if (button.id == "Record" || button.id == "Play")

          {

            button.style.backgroundColor = (button.value == "ON" ? "green" : "red");  

            enableDisableButtonsSliders(button);

          }

        };

      }

      

      function sendButtonInput(key, value) 

      {

        var data = key + "," + value;

        websocketRobotArmInput.send(data);

      }

      

      function onclickButton(button) 

      {

        button.value = (button.value == "ON") ? "OFF" : "ON" ;        

        button.style.backgroundColor = (button.value == "ON" ? "green" : "red");          

        var value = (button.value == "ON") ? 1 : 0 ;

        sendButtonInput(button.id, value);

        enableDisableButtonsSliders(button);

      }

      

      function enableDisableButtonsSliders(button)

      {

        if(button.id == "Play")

        {

          var disabled = "auto";

          if (button.value == "ON")

          {

            disabled = "none";            

          }

          document.getElementById("Gripper").style.pointerEvents = disabled;

          document.getElementById("Elbow").style.pointerEvents = disabled;          

          document.getElementById("Shoulder").style.pointerEvents = disabled;          

          document.getElementById("Base").style.pointerEvents = disabled; 

          document.getElementById("Record").style.pointerEvents = disabled;

        }

        if(button.id == "Record")

        {

          var disabled = "auto";

          if (button.value == "ON")

          {

            disabled = "none";            

          }

          document.getElementById("Play").style.pointerEvents = disabled;

        }        

      }

           

      window.onload = initRobotArmInputWebSocket;

      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 onRobotArmInputWebSocketEvent(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());

      sendCurrentRobotArmState();

      break;

    case WS_EVT_DISCONNECT:

      Serial.printf("WebSocket client #%u disconnected\n", client->id());

      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);

        std::istringstream ss(myData);

        std::string key, value;

        std::getline(ss, key, ',');

        std::getline(ss, value, ',');

        Serial.printf("Key [%s] Value[%s]\n", key.c_str(), value.c_str()); 

        int valueInt = atoi(value.c_str()); 

        

        if (key == "Record")

        {

          recordSteps = valueInt;

          if (recordSteps)

          {

            recordedSteps.clear();

            previousTimeInMilli = millis();

          }

        }  

        else if (key == "Play")

        {

          playRecordedSteps = valueInt;

        }

        else if (key == "Base")

        {

          writeServoValues(0, valueInt);            

        } 

        else if (key == "Shoulder")

        {

          writeServoValues(1, valueInt);           

        } 

        else if (key == "Elbow")

        {

          writeServoValues(2, valueInt);           

        }         

        else if (key == "Gripper")

        {

          writeServoValues(3, valueInt);     

        }   

             

      }

      break;

    case WS_EVT_PONG:

    case WS_EVT_ERROR:

      break;

    default:

      break;  

  }

}


void sendCurrentRobotArmState()

{

  for (int i = 0; i < servoPins.size(); i++)

  {

    wsRobotArmInput.textAll(servoPins[i].servoName + "," + servoPins[i].servo.read());

  }

  wsRobotArmInput.textAll(String("Record,") + (recordSteps ? "ON" : "OFF"));

  wsRobotArmInput.textAll(String("Play,") + (playRecordedSteps ? "ON" : "OFF"));  

}


void writeServoValues(int servoIndex, int value)

{

  if (recordSteps)

  {

    RecordedStep recordedStep;       

    if (recordedSteps.size() == 0) // We will first record initial position of all servos. 

    {

      for (int i = 0; i < servoPins.size(); i++)

      {

        recordedStep.servoIndex = i; 

        recordedStep.value = servoPins[i].servo.read(); 

        recordedStep.delayInStep = 0;

        recordedSteps.push_back(recordedStep);         

      }      

    }

    unsigned long currentTime = millis();

    recordedStep.servoIndex = servoIndex; 

    recordedStep.value = value; 

    recordedStep.delayInStep = currentTime - previousTimeInMilli;

    recordedSteps.push_back(recordedStep);  

    previousTimeInMilli = currentTime;         

  }

  servoPins[servoIndex].servo.write(value);   

}


void playRecordedRobotArmSteps()

{

  if (recordedSteps.size() == 0)

  {

    return;

  }

  //This is to move servo to initial position slowly. First 4 steps are initial position    

  for (int i = 0; i < 4 && playRecordedSteps; i++)

  {

    RecordedStep &recordedStep = recordedSteps[i];

    int currentServoPosition = servoPins[recordedStep.servoIndex].servo.read();

    while (currentServoPosition != recordedStep.value && playRecordedSteps)  

    {

      currentServoPosition = (currentServoPosition > recordedStep.value ? currentServoPosition - 1 : currentServoPosition + 1); 

      servoPins[recordedStep.servoIndex].servo.write(currentServoPosition);

      wsRobotArmInput.textAll(servoPins[recordedStep.servoIndex].servoName + "," + currentServoPosition);

      delay(50);

    }

  }

  delay(2000); // Delay before starting the actual steps.

  

  for (int i = 4; i < recordedSteps.size() && playRecordedSteps ; i++)

  {

    RecordedStep &recordedStep = recordedSteps[i];

    delay(recordedStep.delayInStep);

    servoPins[recordedStep.servoIndex].servo.write(recordedStep.value);

    wsRobotArmInput.textAll(servoPins[recordedStep.servoIndex].servoName + "," + recordedStep.value);

  }

}


void setUpPinModes()

{

  for (int i = 0; i < servoPins.size(); i++)

  {

    servoPins[i].servo.attach(servoPins[i].servoPin);

    servoPins[i].servo.write(servoPins[i].initialPosition);    

  }

}



void setup(void) 

{

  setUpPinModes();

  Serial.begin(115200);


  WiFi.softAP(ssid, password);

  IPAddress IP = WiFi.softAPIP();

  Serial.print("AP IP address: ");

  Serial.println(IP);


  server.on("/", HTTP_GET, handleRoot);

  server.onNotFound(handleNotFound);

      

  wsRobotArmInput.onEvent(onRobotArmInputWebSocketEvent);

  server.addHandler(&wsRobotArmInput);


  server.begin();

  Serial.println("HTTP server started");

    

ArduinoOTA.begin();                       // enable to receive update/uploade firmware via Wifi OTA


}


void loop() 

{

  wsRobotArmInput.cleanupClients();

  if (playRecordedSteps)

  { 

    playRecordedRobotArmSteps();

        


ArduinoOTA.handle();          // listen for update OTA request from clients


  }

}









No comments

Featured Post

Pengelolaan Kinerja Guru (PKG) tahun 2025

📑 [PKG 2025] Berikut ini materi/panduan untuk Penilaian Pengelolaan Kinerja Guru (PKG) tahun 2025. 1. Pengelolaan Kinerja Guru 2. Pengelola...