webserver控制伺服馬達-ESP32


webserver控制伺服馬達-ESP32

伺服馬達對於微控板玩家一定是再熟悉不過,也是入門必學的元件之一,只是特別要注意如果要控制2個以上的伺服馬達,一定要使用外接電源或者PCA9685。

伺服馬達有很多款,小型常用的就屬SG-90,它是塑膠齒輪,還有一種是金屬齒輪

伺服馬達規格

SG-90規格

  • 工作電壓:4.8V.
  • 轉矩:1.8kg-cm
  • 運轉速度:0.1秒∕ 60度
  • 轉動角度:最大90°
  • 脈衝寬度範圍:500~2400µs.

MG90S規格

  • 金屬銅齒、空心杯電機、雙滾珠軸承
  • 產品型號:MG90s.
  • 扭力:2.0kg(4.8v)
  • 運轉速度:0.11s(4.8v)
  • 轉動角度:最大90°/180°
  • 舵機類型:數字舵機

  1. 此次實驗以MG-90為主
  2. 要控制伺服馬達有兩種方式,一種是利用PWM,另一種是使用現有的庫包來控制,本次實驗以庫包為主

首先安裝

ESP32 Arduino Servo Library

接線方式

  • GND -> ESP32 GND pin;

  • Power -> ESP32 VIN pin;

  • Signal -> GPIO 13 (or any PWM pin).

進行實驗

#include <ESP32Servo.h>
 
Servo myservo;
 
int pos = 20;
const int pin = 12;
 
void setup(){
  Serial.begin(115200);
  myservo.attach(pin, 500, 2400);
}
 
void loop(){
  for (pos=20; pos<=160; pos+=3){
    myservo.write(pos);
    delay(100);
  }
  for (pos=160; pos>=20; pos-=3){
    myservo.write(pos);
    delay(100);
  }
}

ESP32網頁伺服器

上面伺服馬達簡單的測試完成後,就可以納入網頁伺服器來控制伺服馬達,這裡我覺得有點難度的是網頁的編寫,因為寫HTML+CSS我沒學過,所以參考網路上教學文的網頁範例。

這是我參考教學網站上的網頁範例

<!DOCTYPE html>
<html>
<head>
    <meta name="viewport" content="width=device-width, initial-scale=1">
    <link rel="icon" href="data:,">
    <style>
    body {
        text-align: center;
        font-family: "Trebuchet MS", Arial;
        margin-left:auto;
        margin-right:auto;
    }
    .slider {
        width: 300px;
    }
    </style>
    <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
</head>
<body>
    <h1>ESP32 with Servo</h1>
    <p>Position: <span id="servoPos"></span></p>
    <input type="range" min="0" max="180" class="slider" id="servoSlider" onchange="servo(this.value)"/>
    <script>
    var slider = document.getElementById("servoSlider");
    var servoP = document.getElementById("servoPos");
    servoP.innerHTML = slider.value;
    slider.oninput = function() {
        slider.value = this.value;
        servoP.innerHTML = this.value;
    }
    $.ajaxSetup({timeout:1000});
    function servo(pos) {
        $.get("/?value=" + pos + "&");
        {Connection: close};
    }
    </script>
</body>
</html>

使用 script 和 /script 標籤將一些 JavaScript 代碼添加到您的 HTML 文件中。此代碼片段使用當前滑塊位置更新網頁

var slider = document.getElementById("servoSlider");
var servoP = document.getElementById("servoPos");
servoP.innerHTML = slider.value;
slider.oninput = function() {
    slider.value = this.value;
    servoP.innerHTML = this.value;
}
  

接下來的幾行在此特定 URL 路徑 /?value\u003d[SLIDER_POSITION]& 中的 ESP IP 地址上發出 HTTP GET 請求。

$.ajaxSetup({timeout:1000});
function servo(pos) {
    $.get("/?value=" + pos + "&");
    {Connection: close};
}

例如,當滑塊位於 0 時,您在以下 URL 上發出 HTTP GET 請求:

http://192.168.1.135/?value=0&

完整程式碼

#include <ESP32Servo.h>
#include <WiFi.h>
 
//定義伺服馬達
Servo myservo;
 
//伺服馬達的起始值和腳位
int pos = 0;
const int servoPin = 12;
 
//WIFI
const char *ssid = "---";
const char *password = "-----";
//將 Web 服務器端口號設置為 80
WiFiServer server(80);
 
//用於存儲 HTTP 請求的變量
String header;
 
//解碼 HTTP GET 值
String valueString = String(0);
int pos1 = 0;
int pos2 = 0;
 
// 當下的時間
unsigned long currentTime = millis();
// 之前的時間
unsigned long previousTime = 0; 
// 超時
const long timeoutTime = 2000;
 
void setup(){
  Serial.begin(115200);
  //指定伺服器上的pin
  myservo.attach(servoPin, 500, 2400);
  //連接wifi
  WiFi.begin(ssid, password);
  while (WiFi.isConnected() == false){
    Serial.print(".");
    delay(1000);
  }
  Serial.println("Connected successful!");
  Serial.print("IP: ");
  Serial.print(WiFi.localIP());
  //連接伺服器
  server.begin();
}
 
void loop(){
  //監聽客戶端傳入的資料
  WiFiClient client = server.available();
  //如果有新客戶端連接進來,
  if (client){
    currentTime = millis();
    previousTime = currentTime;
    Serial.println("New Client.");     
    //製作一個字符串來保存來自客戶端的傳入數據
    String currentLine = "";
    while (client.connected() && (currentTime - previousTime <= 2000)){
      currentTime = millis();
      if (client.available()){ //如果有字節要從客戶端讀取,
        char c = client.read(); //讀取字節
        Serial.write(c); //印到序列監測窗口
        header += c;
        if (c == '\n'){ //如果字節是換行符 //如果當前行為空,則表示一行中有兩個換行符。
          //這是客戶端 HTTP 請求的結束,因此發送響應:
          if (currentLine.length() == 0){
            client.println("HTTP/1.1 200 OK");
            client.println("Content-type:text/html; charset=utf-8");
            client.println("Connection: close");
            client.println();
            //接下來就是顯示網頁
            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:,\">");
            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>ESP32 控制伺服馬達練習</h1>");
            client.println("<p>Position: <span id=\"servoPos\"></span></p>");          
            client.println("<input type=\"range\" min=\"0\" max=\"180\" 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);
              
              //轉換成整數後傳入伺服馬達令其動作
              myservo.write(valueString.toInt());
              delay(15);
              Serial.println(valueString); 
            }         
            // The HTTP response ends with another blank line
            client.println();
            break;
          }else { //如果有一個換行符,就清除 currentLine
            currentLine = "";
          }
        }else if (c != '\r'){ //否則如果除了enter以外還有別的字串,把它加入currentLine末端
          currentLine += c; 
        }
      }
    }
    // 將header清空
    header = "";
    // 關閉連結
    client.stop();
    Serial.println("Client disconnected.");
    Serial.println("");
  }
}

文章作者: blairan
版權聲明: 本博客所有文章除特別聲明外,均採用 CC BY 4.0 許可協議。轉載請註明來源 blairan !
评论
  目錄