資料介紹
pcb圖:
描述
通過 Web 服務器控制雙直流電機和伺服電機 - ESP8266 DRV8848 電機驅動板
在這個項目中,您將看到如何使用 ESP 構建一個 Web 服務器,該服務器使用四個按鈕和一個滑塊控制雙直流電機方向和一個伺服電機位置。我將使用我上次設計的基于 ESP8266 的 DRV8848 電機驅動器開發(fā)板,但該項目的源代碼兼容 L298N 和 L293D 等電機驅動器。
如果您需要一款可以驅動雙直流電機的ESP8266 WiFi開發(fā)板,您可以從PCBWay訂購這款PCB,質優(yōu)價廉。您可以從鏈接中了解該板的特性,包括焊接和組裝等所有階段
https://www.pcbway.com/project/shareproject/ESP_12F_DRV88xx_Motor_Driver_Development_Board_bc4e7391.html
讓我們看一下允許通過 Web 服務器控制直流電機方向和伺服電機位置的源代碼。
添加了必要的 WiFi 和伺服庫以使用 Arduino IDE。
?
#include #include #include #include
?
已創(chuàng)建名為“My Servo”的伺服對象。
?
伺服我的伺服;
?
定義了連接伺服電機和直流電機的 GPIO 引腳。
?
// 伺服器連接到 GPIO static const int servoPin = 0 ; //電機連接到 GPIO static const int M1forwardPin = 14 ; static const int M1backwardPin = 12 ; static const int M2forwardPin = 5 ; static const int M2backwardPin = 4 ; 靜態(tài)常量int sleepPin = 16 ;
?
如果您的驅動器不包含“睡眠”引腳,請將“睡眠模式”行更改為注釋行。
?
//static const int sleepPin = 16;
?
電機速度已定義,可根據(jù)需要進行更改。
?
#define M1SPEED 200 #define M2SPEED 200
?
?
const char * ssid = "REPLACE_WITH_YOUR_SSID" ; const char * password = "REPLACE_WITH_YOUR_PASSWORD" ;
?
創(chuàng)建了一個變量來存儲 HTTP 請求的標頭。
?
字符串頭;
?
然后又創(chuàng)建了幾個變量,用于從 HTTP 請求中提取滑塊位置。
?
字符串值字符串 = 字符串( 5 ); int pos1 = 0 ; int pos2 = 0 ;
?
在“設置”部分,啟動串行通信并指定連接引腳的模式。如果不使用“sleep pin”,則可以移除該線。
?
序列號.begin(115200); pinMode(M1forwardPin,輸出);pinMode(M1backwardPin,輸出);pinMode(M2forwardPin,輸出);pinMode(M2backwardPin,輸出);pinMode(sleepPin,輸出);myServo.attach(servoPin); 數(shù)字寫入(sleepPin,高);
?
然后 Wi-Fi 連接開始,IP 地址打印在串口監(jiān)視器上。
?
串行。打印(“連接到”); 序列號.println(ssid); WiFi.begin(ssid, 密碼); while (WiFi.status() != WL_CONNECTED) { delay( 500 ); 串行。打印(“。”); } // 打印本地IP 地址并啟動 Web 服務器 Serial.println( "" ); Serial.println( “WiFi 已連接。” ); Serial.println( "IP地址:" ); Serial.println(WiFi.localIP()); 服務器.開始();
?
最后,在進入循環(huán)部分之前,為電機的移動和方向創(chuàng)建了函數(shù)。
?
void forward () { analogWrite(M1forwardPin, M1SPEED); 模擬寫入(M2forwardPin,M2SPEED);模擬寫入(M1backwardPin, 0);模擬寫入(M2backwardPin, 0);} void backward () { analogWrite(M1backwardPin, M1SPEED); 模擬寫入(M2backwardPin,M2SPEED);模擬寫入(M1forwardPin, 0);模擬寫入(M2forwardPin, 0);} void turnLeft () { analogWrite(M1backwardPin, M1SPEED); 模擬寫入(M2forwardPin,M2SPEED);模擬寫入(M1forwardPin, 0);模擬寫入(M2backwardPin, 0);} void 右轉() { 模擬寫入(M1forwardPin,M1SPEED);模擬寫入(M2backwardPin,M2SPEED);模擬寫入(M1backwardPin,0);模擬寫入(M2forwardPin,0);} void stopMotors () { analogWrite(M1forwardPin, 0 ); 模擬寫入(M2forwardPin,0);模擬寫入(M1backwardPin,0);模擬寫入(M2backwardPin,0);}
?
在循環(huán)部分,定義了當新客戶端首次與 Web 服務器建立連接時會發(fā)生什么。當從客戶端收到請求時,傳入的數(shù)據(jù)將被保存。只要客戶端保持連接,后面的 while 循環(huán)就會運行。
?
WiFiClient client = server.available(); 如果(客戶端){ currentTime = millis(); 上一個時間 = 當前時間;Serial.println( “新客戶。” ); 字符串 currentLine = "" ; while (client.connected() && currentTime - previousTime <= timeoutTime) { currentTime = millis(); 如果(client.available()) { char c = client.read(); 串口.write(c); 標題 += c; 如果(c == '\n' ) {如果(currentLine.length() == 0 ) {
?
然后生成 Web 服務器并發(fā)送一些 HTML 文本以顯示網(wǎng)頁。使用“客戶端打印”功能將網(wǎng)頁發(fā)送到客戶端。您必須輸入要作為參數(shù)發(fā)送給客戶端的內(nèi)容。
?
client.println("HTTP/1.1 200 OK"); client.println("內(nèi)容類型:文本/html"); client.println("連接:關閉"); 客戶端.println(); // 顯示 HTML 網(wǎng)頁 client.println(" < html >< head >< meta name = \ " viewport \" content = \ " width = device-width, initial-scale = 1\ "> "); // 按鈕和滑塊的樣式部分。您可以更改自定義設置,例如顏色等。client.println(" <樣式> "); 客戶。顯示:塊;彈性方向:列;對齊項目:居中;}"); client.println(".slider { width : 275px ; accent-color : #ede100 ; cursor : pointer;}"); client.println(".button-container { display : flex ; flex-direction : column; align-items : center;}"); client.println(".row-container { display : flex; flex-direction : row; justify-content : center; align-items : center;} "); client.println(".button {寬度: 135px ;邊界:0;背景色:#ede100;框陰影:插圖2px 2px 3px #b2b2b2,插圖 - 2px - 2px 3px #000;填充:10px 25px;文本對齊:居中;顯示:內(nèi)聯(lián)塊;邊界半徑:5px;字體大小:16px;邊距:10px 25px;光標:指針;}"); client.println(".button:hover {背景顏色:#fff200 ;}"); client.println(".button:active{ box-shadow : inset 2px 2px 3px #000 , inset - 2px - 2px 3px #b2b2b2 ;}"); client.println(" footer { text-align : center; margin : 50px ; width : 400px ; background-color : #ede100 ;}"); client.println(" style >>< script src = \ " https: //ajax.googleapis . com /ajax / libs / jquery / 3.3.1 / jquery.min.js \"> " ) ; // 正文部分。包含按鈕和滑塊的功能。client.println(" <正文> "); client.println(" < div class = \ "容器\"> "); client.println(" < div class = \ " row-container \">< h2 > ESP8266電機控制面板 h2 >"); client.println(" < div >< div class = \ " button-container \"> "); client.println(" < div class = \ " row-container \">< button class = \ "按鈕\" id = \ " forward-btn \" onmousedown = \ " btnVal (' forward ')\" onmouseup = \ " btnVal ('停止')\">前進
?
" ) ;client.println(" < div class = \ " row-container \">< button class = \ " button \ " id = \ " left-btn \ " onmousedown = \ " btnVal (' left ' )\" onmouseup = \ " btnVal (' stop ' )\"> Left "); client.println("
" ); client.println(" div > "); client.println(" < div class = \ " row-container \">< p > Servo Position:<跨度 標識= \ " servoPos \"> span > p > div > "); client.println(" < div class = \ " row-container \">< input type = \ " range \" min = \ " 0 \" max = \ " 180 \" class = \ " slider \" id = \ "servoSlider \" onchange =\ " servo ( this.value )\" value = "+valueString+" /> div > "); client.println(" < div class = \ " row-container \">< footer > < p > @Maker101io p > footer > div > div > "); // 腳本部分。獲取按鈕和滑塊值并執(zhí)行函數(shù)。client.println(" < script > "); client.println("var滑塊 =文檔.getElementById(\ "servoSlider");" ); client.println( "var servoP = document.getElementById("servoPos"); servoP.innerHTML = slider.value;" ); client.println( "滑塊。 oninput = function() { slider.value = this.value; servoP.innerHTML = this.value; }" ); client.println( "$.ajaxSetup({timeout:1000});" ); client.println( " function btnVal(dir) { $.get("/?btnVal=" + dir, true);}" ); client.println( "function servo(pos) { $.get("/?value=\ " + pos + "&");}" ); client.println( "{Connection: close}; script > "); client.println("< /正文> ");
讓我們看一下 ESP 發(fā)送給瀏覽器的 HTML 代碼。該網(wǎng)頁有一些用于按鈕和滑塊的 CSS。如果您確定自己在做什么,則可以更改此部分中定義的一些屬性,例如顏色和大小。
如果您想在網(wǎng)頁上進行更改,我會將這些 HTML 代碼與源代碼一起共享。請記住,您必須更新您對 Arduino IDE 共享源代碼中找到的 HTML 行所做更改的 HTML 行。修改時要注意的一點是需要在HTML代碼中的“雙引號”符號前加上“反斜杠”符號。
?
< html >< head >< meta name = "viewport" content = "width=device-width, initial-scale=1" > <樣式> .container {字體:標題;顯示:塊;彈性方向:列;對齊項目:居中;} .slider {寬度:275px ; 強調色:#ede100;游標:指針;} .button-container {顯示:flex; 彈性方向:列;對齊項目:居中;} .row-container {顯示:flex; 彈性方向:行;證明內(nèi)容:居中;對齊項目:居中;} .button {寬度: 135px ; 邊界:0;背景色:#ede100;框陰影:插圖2px 2px 3px #b2b2b2,插圖 - 2px - 2px 3px #000;填充:10px 25px;文本對齊:居中;顯示:內(nèi)聯(lián)塊;邊界半徑:5px;字體大小:16px;保證金:10px 25px; 游標:指針;} .button:hover {背景顏色:#fff200 ;} .button:active{ box-shadow : inset 2px 2px 3px #000 , inset - 2px - 2px 3px #b2b2b2 ;} 頁腳 {文本對齊:居中;邊距:50px;寬度:400px;背景色:#ede100 ;} style >< script src = "https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js" > script > 頭>
?
添加了四個按鈕類,并為每個按鈕定義了電機方向。只要按鈕一直被按下,按鈕的“方向”值就會被獲取,當按鈕被釋放時,“停止”值就會被獲取。然后添加一個滑塊,為滑塊定義最小和最大范圍。創(chuàng)建了一個“值字符串”變量來保存滑塊值。
?
< div class = " container" > ? < div class = "row-container" >
?
ESP8266電機控制面板
< ? div class = " ? ? ? button - container " > < div class = "row-container" >> < button class = "button" onmousedown = "btnVal('forward')" onmouseup = "btnVal('stop')" > Forward button > div > ? ? ? < div class = "row-container" >> < button class = "button" id = " left-btn" onmousedown = "btnVal('left')" onmouseup = "btnVal('stop')" > Left button > ? ? ? ? < button class = "button" id = "right-btn" onmousedown= "btnVal('right')" onmouseup = "btnVal('stop')" > Right button > div > ? ? ? < div class = "row-container" >> < button class = "button" id = "backward -btn" onmousedown = "btnVal('backward')" onmouseup = "btnVal('stop')" > Backward button > div > div > ? div > ? < div 類="row-container" >
伺服位置: < span id = "servoPos" >
< ? div class = " row-container" >< input type ? = "range " min = “0” max = “180”類= “滑塊” id = “servoSlider” onchange = “servo(this.value)” value = “+valueString+" /> div >
@ Maker101io
_ _
最后,您發(fā)出 HTTP GET 請求以獲取值。執(zhí)行兩個處理按鈕方向值和滑塊值的函數(shù)。
?
<腳本> 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({超時:1000 }); function btnVal ( dir ) { $.get( "/?btnVal=" + dir);} function servo ( pos ) { $.get( "/?value=" + pos + "&" );} {連接:關閉}; 腳本>< /正文>
?
讓我們加載源代碼并測試功能。上傳代碼后,打開串行監(jiān)視器。復制串行監(jiān)視器上顯示的 IP 地址。打開瀏覽器,粘貼 IP 地址,您將看到之前創(chuàng)建的網(wǎng)頁。按住電機方向按鈕并松開。在串行監(jiān)視器中,您可以看到發(fā)送到 ESP 的 HTTP 請求。
“If”和“Else”語句是一個條件。它控制按下哪個按鈕并運行根據(jù)接收到的數(shù)據(jù)確定的功能。此數(shù)據(jù)包含為按鈕定義的變量。當您移動滑塊時,兩個符號之間的滑塊位置將被獲取并存儲在“值字符串”變量中。然后將此字符串值轉換為整數(shù)值。該轉換值被寫入伺服電機位置。伺服電機移動到該位置值。
?
如果(header.indexOf( "GET /?value=" )>= 0 ) { pos1 = header.indexOf( '=' ); pos2 = header.indexOf( '&' ); valueString = header.substring(pos1+ 1 , pos2); myServo.write(valueString.toInt()); // 旋轉舵機 Serial.println(valueString); } else if (header.indexOf( "GET /?btnVal=forward" )!= -1 ) { Serial.println( “轉發(fā)” ); 向前();// 向前轉 } else if (header.indexOf( "GET /?btnVal=left" )!= -1 ) { Serial.println( “左” ); 左轉(); // 向左轉 } else if (header.indexOf( "GET /?btnVal=right" )!= -1 ) { Serial.println( “正確” ); 右轉();// 右轉 } else if (header.indexOf( "GET /?btnVal=backward" )!= -1 ) { Serial.println( “返回” ); 落后(); // 向后轉 } else if (header.indexOf( "GET /?btnVal=stop" )!= -1 ) { Serial.println( “停止” ); 停止電機();// 停止 } // HTTP 響應以另一個空行結束 客戶端.println(); // 跳出 while 循環(huán) break ; } else { // 如果你有換行符,則清除 currentLine currentLine = "" ; } } else if (c != '\r' ) { // 如果除了回車符之外還有其他任何內(nèi)容,則 currentLine += c;// 將其添加到當前行的末尾 } } } // 清除頭變量 header = "" ; // 關閉連接 客戶端停止(); Serial.println( "客戶端斷開連接。" ); 序列號.println( "" ); } }
?
感謝您的關注和閱讀。如果您有任何問題或建議,請在評論中告訴我。
代碼
ESP8266 直流電機和伺服電機通過網(wǎng)絡服務器控制
ESP8266-Motor-Control-Web-Server-Code.ino
下載(18)
網(wǎng)頁的 HTML 代碼
HTML
? | html> |
? | ? |
? | |
? | .container {font: caption; display: block; flex-direction: column; align-items: center;} |
? | .slider {width: 275px; accent-color: #ede100; cursor: pointer;} |
? | .button-container {display: flex; flex-direction: column; align-items: center;} |
? | .row-container {display: flex; flex-direction: row; justify-content: center; align-items: center;} |
? | .button {width: 135px; border: 0; background-color: #ede100; box-shadow: inset 2px 2px 3px #b2b2b2, inset -2px -2px 3px #000; padding: 10px 25px; text-align: center; display: inline-block; border-radius: 5px; font-size: 16px; margin: 10px 25px; cursor: pointer;} |
? | .button:hover {background-color: #fff200;} |
? | .button:active{box-shadow: inset 2px 2px 3px #000, inset -2px -2px 3px #b2b2b2;} |
? | footer {text-align: center; margin: 50px; width: 400px; background-color: #ede100;} |
? | style> |