Arduino Điều khiển động cơ servo thông qua web

Hướng dẫn này sẽ cho bạn biết cách sử dụng Arduino để điều khiển một động cơ servo từ trình duyệt web trên điện thoại thông minh hoặc máy tính của bạn. Chúng ta sẽ sử dụng công nghệ WebSocket để cho phép điều khiển mượt mà và linh hoạt của động cơ servo thông qua một giao diện người dùng web đồ họa.

Arduino điều khiển động cơ servo thông qua web

Bây giờ, tại sao chúng ta nên sử dụng WebSocket? Đây là lý do:

Chúng ta hãy bắt đầu!

Phần cứng cần chuẩn bị

1×Arduino UNO R4 WiFi
1×Alternatively, DIYables STEM V4 IoT
1×(Tùy chọn) DIYables STEM V4 IoT
1×USB Cable Type-A to Type-C (for USB-A PC)
1×USB Cable Type-C to Type-C (for USB-C PC)
1×động cơ servo
1×breadboard
1×dây jumper
1×(Tùy chọn) DC Power Jack
1×(Khuyến nghị) Screw Terminal Block Shield for Arduino UNO R4
1×(Khuyến nghị) Breadboard Shield for Arduino UNO R4
1×(Khuyến nghị) Enclosure for Arduino UNO R4
1×(Khuyến nghị) Power Splitter for Arduino UNO R4
1×(Khuyến nghị) Prototyping Base Plate & Breadboard Kit for Arduino UNO

Or you can buy the following kits:

1×DIYables STEM V4 IoT Starter Kit (Arduino included)
1×DIYables Sensor Kit (30 sensors/displays)
1×DIYables Sensor Kit (18 sensors/displays)

Về Động cơ Servo và WebSocket

Chúng tôi có các bài hướng dẫn cụ thể về động cơ servo và WebSocket. Mỗi bài hướng dẫn chứa thông tin chi tiết và hướng dẫn từng bước về sơ đồ chân của phần cứng, nguyên lý hoạt động, cách kết nối dây với Arduino, mã Arduino... Tìm hiểu thêm về chúng tại các liên kết sau:

Cách hoạt động

Mã Arduino thiết lập cả máy chủ web và máy chủ WebSocket. Dưới đây là quy trình theo từng bước:

  • Khi bạn gõ địa chỉ IP của Arduino vào trình duyệt web, nó gửi một yêu cầu cho trang web (Giao diện người dùng) được lưu trữ trên Arduino.
  • Máy chủ web của Arduino phản hồi bằng cách gửi lại nội dung của trang web (HTML, CSS, JavaScript).
  • Trình duyệt web của bạn sau đó hiển thị trang web.
  • Mã JavaScript được nhúng vào trang web bắt đầu một kết nối WebSocket với máy chủ WebSocket trên Arduino.
  • Khi kết nối WebSocket được thiết lập, nếu bạn điều chỉnh thanh điều khiển trên trang web, mã JavaScript sẽ âm thầm truyền giá trị góc tới Arduino thông qua kết nối WebSocket này ở chế độ nền.
  • Máy chủ WebSocket trên Arduino, khi nhận được giá trị góc này, sẽ điều chỉnh động cơ servo tương ứng.

Về bản chất, kết nối WebSocket tạo điều kiện cho việc điều khiển góc của động cơ servo một cách mượt mà và theo thời gian thực.

Sơ đồ nối dây giữa động cơ servo và Arduino

sơ đồ đấu dây động cơ servo Arduino

This image is created using Fritzing. Click to enlarge image

Vì sự đơn giản, sơ đồ kết nối ở trên được sử dụng cho mục đích thử nghiệm hoặc học tập và cho động cơ servo có mô-men xoắn nhỏ. Trong thực tế, chúng tôi khuyến nghị mạnh mẽ sử dụng nguồn cấp ngoài cho động cơ servo. Sơ đồ kết nối dưới đây cho thấy cách kết nối động cơ servo với nguồn cấp ngoài.

sơ đồ cấp nguồn cho động cơ servo Arduino

Mã Arduino

Nội dung của trang web (HTML, CSS, JavaScript) được lưu riêng trong một tệp index.h. Vì vậy, chúng ta sẽ có hai tệp mã trong Arduino IDE:

  • Một tệp .ino chứa mã Arduino, dùng để tạo máy chủ web và máy chủ WebSocket, và điều khiển động cơ servo
  • Một tệp .h chứa nội dung của trang web

Hướng dẫn từng bước

  • Nếu đây là lần đầu bạn sử dụng Arduino Uno R4, hãy xem Cách bắt đầu với Arduino UNO R4.
  • Thực hiện nối dây theo hình ở trên.
  • Kết nối bo mạch Arduino với máy tính của bạn bằng cáp micro USB.
  • Mở Arduino IDE trên máy tính của bạn.
  • Chọn bo mạch Arduino đúng (ví dụ Arduino Uno R4 WiFi) và cổng COM.
  • Mở Library Manager bằng cách nhấp vào biểu tượng Library Manager trên thanh điều hướng bên trái của Arduino IDE.
  • Tìm kiếm Web Server for Arduino Uno R4 WiFi và tìm thư viện Web Server do DIYables phát triển.
  • Nhấp nút Install để cài đặt thư viện Web Server.
thư viện máy chủ web cho Arduino UNO R4
  • Trong Arduino IDE, tạo một sketch mới, đặt cho nó một tên, ví dụ, ArduinoGetStarted.com.ino
  • Sao chép đoạn mã bên dưới và mở bằng Arduino IDE
/* * Mã Arduino này được phát triển bởi newbiely.vn * Mã Arduino này được cung cấp để sử dụng công khai, không có ràng buộc. * Để xem hướng dẫn chi tiết và sơ đồ kết nối, vui lòng truy cập: * https://newbiely.vn/tutorials/arduino/arduino-controls-servo-motor-via-web */ #include <Servo.h> #include <UnoR4WiFi_WebServer.h> #include "index.h" #define SERVO_PIN 9 // Arduino pin 9 connected to servo motor // WiFi credentials const char WIFI_SSID[] = "YOUR_WIFI_SSID"; const char WIFI_PASSWORD[] = "YOUR_WIFI_PASSWORD"; // Create web server instance UnoR4WiFi_WebServer server(80); UnoR4WiFi_WebSocket *webSocket; Servo servo; // Page handlers void handleHome(WiFiClient& client, const String& method, const String& request, const QueryParams& params, const String& jsonData) { server.sendResponse(client, HTML_CONTENT); } // WebSocket event handlers void onWebSocketOpen(net::WebSocket& ws) { Serial.println("New WebSocket connection"); } void onWebSocketMessage(net::WebSocket& ws, const net::WebSocket::DataType dataType, const char* message, uint16_t length) { String angle = String(message); int angle_value = angle.toInt(); servo.write(angle_value); Serial.print(F("Rotate Servo Motor to ")); Serial.println(angle_value); } void onWebSocketClose(net::WebSocket& ws, const net::WebSocket::CloseCode code, const char* reason, uint16_t length) { Serial.println("WebSocket client disconnected"); } void setup() { Serial.begin(9600); delay(1000); servo.attach(SERVO_PIN); // attaches the servo on Arduino pin Serial.println("Arduino Uno R4 WiFi - WebSocket Server controls Servo Motor"); // Configure web server routes server.addRoute("/", handleHome); // Start web server with WiFi connection server.begin(WIFI_SSID, WIFI_PASSWORD); // Enable WebSocket functionality webSocket = server.enableWebSocket(81); if (webSocket != nullptr) { // Set up WebSocket event handlers webSocket->onOpen(onWebSocketOpen); webSocket->onMessage(onWebSocketMessage); webSocket->onClose(onWebSocketClose); } else { Serial.println("Failed to start WebSocket server"); } } void loop() { // Handle HTTP requests and WebSocket connections using the library server.handleClient(); server.handleWebSocket(); delay(10); }
  • Chỉnh sửa thông tin WiFi (SSID và mật khẩu) trong mã để khớp với thông tin mạng của bạn.
  • Tạo tệp index.h bằng Arduino IDE:
    • Hoặc nhấp vào nút ngay dưới biểu tượng Serial Monitor và chọn Tab mới, hoặc dùng tổ hợp phím Ctrl+Shift+N.
    Arduino ide 2 thêm tệp
    • Hãy đặt tên cho tệp tin index.h và nhấn nút OK
    Arduino ide 2 thêm tệp index.h
    • Sao chép đoạn mã dưới đây và dán nó vào index.h.
    /* * Mã Arduino này được phát triển bởi newbiely.vn * Mã Arduino này được cung cấp để sử dụng công khai, không có ràng buộc. * Để xem hướng dẫn chi tiết và sơ đồ kết nối, vui lòng truy cập: * https://newbiely.vn/tutorials/arduino/arduino-controls-servo-motor-via-web */ const char *HTML_CONTENT = R"=====( <!DOCTYPE html> <html> <head> <title>Arduino Controls Servo Motor via Web</title> <meta name="viewport" content="width=device-width, initial-scale=0.7"> <style> body { text-align: center; } canvas { background-color: #ffffff; } </style> <script> var canvas_width = 401, canvas_height = 466; var pivot_x = 200, pivot_y = 200; var bracket_radius = 160, bracket_angle = 0; var bracket_img = new Image(); var click_state = 0; var last_angle = 0; var mouse_xyra = {x:0, y:0, r:0.0, a:0.0}; var ws; bracket_img.src = "https://esp32io.com/images/tutorial/servo-bracket.png"; function init() { var servo = document.getElementById("servo"); servo.width = canvas_width; servo.height = canvas_height; servo.style.backgroundImage = "url('https://esp32io.com/images/tutorial/servo-body.png')"; servo.style.backgroundPosition = "center"; servo.style.backgroundSize = "contain"; servo.addEventListener("touchstart", mouse_down); servo.addEventListener("touchend", mouse_up); servo.addEventListener("touchmove", mouse_move); servo.addEventListener("mousedown", mouse_down); servo.addEventListener("mouseup", mouse_up); servo.addEventListener("mousemove", mouse_move); var ctx = servo.getContext("2d"); ctx.translate(pivot_x, pivot_y); rotate_bracket(0); ws = new WebSocket("ws://" + window.location.host + ":81"); document.getElementById("ws_state").innerHTML = "CONNECTING"; ws.onopen = function(){ document.getElementById("ws_state").innerHTML = "CONNECTED" }; ws.onclose = function(){ document.getElementById("ws_state").innerHTML = "CLOSED"}; ws.onerror = function(){ alert("websocket error " + this.url) }; ws.onmessage = ws_onmessage; } function ws_onmessage(e_msg) { e_msg = e_msg || window.event; // MessageEvent alert("msg : " + e_msg.data); } function rotate_bracket(angle) { var servo = document.getElementById("servo"); var ctx = servo.getContext("2d"); ctx.clearRect(-pivot_x, -pivot_y, canvas_width, canvas_height); ctx.rotate(angle / 180 * Math.PI); ctx.drawImage(bracket_img, -pivot_x, -pivot_y); ctx.rotate(-angle / 180 * Math.PI); } function check_range_xyra(event, mouse_xyra) { var x, y, r, a, rc_x, rc_y, radian; var min_r, max_r, width; if(event.touches) { var touches = event.touches; x = (touches[0].pageX - touches[0].target.offsetLeft) - pivot_x; y = pivot_y - (touches[0].pageY - touches[0].target.offsetTop); min_r = 60; max_r = pivot_x; width = 40; } else { x = event.offsetX - pivot_x; y = pivot_y - event.offsetY; min_r = 60; max_r = bracket_radius; width = 20; } /* cartesian to polar coordinate conversion */ r = Math.sqrt(x * x + y * y); a = Math.atan2(y, x); mouse_xyra.x = x; mouse_xyra.y = y; mouse_xyra.r = r; mouse_xyra.a = a; radian = bracket_angle / 180 * Math.PI; /* rotate coordinate */ rc_x = x * Math.cos(radian) - y * Math.sin(radian); rc_y = x * Math.sin(radian) + y * Math.cos(radian); if((r < min_r) || (r > max_r)) return false; if((rc_y < -width) || (rc_y > width)) return false; return true; } function mouse_down() { if(event.touches && (event.touches.length > 1)) click_state = event.touches.length; if(click_state > 1) return; if(check_range_xyra(event, mouse_xyra)) { click_state = 1; last_angle = mouse_xyra.a / Math.PI * 180.0; } } function mouse_up() { click_state = 0; } function mouse_move() { var angle; if(event.touches && (event.touches.length > 1)) click_state = event.touches.length; if(click_state > 1) return; if(!click_state) return; if(!check_range_xyra(event, mouse_xyra)) { click_state = 0; return; } angle = mouse_xyra.a / Math.PI * 180.0; if((Math.abs(angle) > 90) && (angle * last_angle < 0)) { if(last_angle > 0) last_angle = -180; else last_angle = 180; } bracket_angle += (last_angle - angle); last_angle = angle; if(bracket_angle > 90) bracket_angle = 90; if(bracket_angle < -90) bracket_angle = -90; rotate_bracket(bracket_angle); if(ws.readyState == 1) ws.send(Math.floor(90 - bracket_angle) + "\r\n"); debug = document.getElementById("debug"); debug.innerHTML = Math.floor(90 - bracket_angle); event.preventDefault(); } window.onload = init; </script> </head> <body> <h2> Arduino - Servo Motor via Web<br> <canvas id="servo"></canvas> <p> WebSocket : <span id="ws_state" style="color:blue">null</span><br> Angle : <span id="debug" style="color:blue">90</span> </p> </h2> <div class="sponsor">Sponsored by <a href="https://amazon.com/diyables">DIYables</a></div> </body> </html> )=====";
    • Bây giờ bạn có mã nguồn ở hai tệp: ArduinoGetStarted.com.inoindex.h
    • Nhấp vào Tải lên nút trên IDE Arduino để tải mã lên Arduino.
    • Mở Serial Monitor
    • Xem kết quả trên Serial Monitor.
    COM6
    Send
    Arduino Uno R4 WiFi - WebSocket Server controls Servo Motor Connected! IP Address: 192.168.0.254 SSID: YOUR_WIFI_SSID IP Address: 192.168.0.254 Signal strength (RSSI): -44 dBm WebSocket server started on port 81 WebSocket URL: ws://192.168.0.254:81 WebSocket server enabled successfully
    Autoscroll Show timestamp
    Clear output
    9600 baud  
    Newline  
    • Ghi nhớ địa chỉ IP được hiển thị và nhập địa chỉ này vào thanh địa chỉ của trình duyệt web trên điện thoại thông minh hoặc máy tính của bạn.
    • Bạn sẽ thấy trang web như dưới đây:
    Arduino điều khiển động cơ servo thông qua trình duyệt web
    • Mã JavaScript của trang web tự động thiết lập kết nối WebSocket tới Arduino.
    • Bây giờ bạn có thể điều khiển góc của động cơ servo bằng cách xoay tay cầm của động cơ trên giao diện web.
    • Hãy kiểm tra kết quả trên Serial Monitor; bạn cũng sẽ thấy các giá trị góc từ trang web.
    COM6
    Send
    WebSocket server enabled successfully WebSocket client connected from: 192.168.0.7 New WebSocket connection Rotate Servo Motor to 90 Rotate Servo Motor to 89 Rotate Servo Motor to 88 Rotate Servo Motor to 87
    Autoscroll Show timestamp
    Clear output
    9600 baud  
    Newline  

    Để tiết kiệm bộ nhớ của Arduino, hình ảnh của động cơ servo KHÔNG được lưu trữ trên Arduino. Thay vào đó, chúng được lưu trữ trên Internet, vì vậy điện thoại hoặc máy tính của bạn cần có kết nối Internet để tải hình ảnh cho trang điều khiển web.

    ※ Lưu ý:

    • Nếu bạn chỉnh sửa nội dung HTML trong index.h và không chỉnh sửa bất kỳ thứ gì trong tệp ArduinoGetStarted.com.ino, khi bạn biên dịch và tải mã lên Arduino, Arduino IDE sẽ không cập nhật nội dung HTML.
    • Để Arduino IDE cập nhật nội dung HTML trong trường hợp này, hãy thực hiện một thay đổi trong tệp ArduinoGetStarted.com.ino (ví dụ: thêm một dòng trống, thêm một chú thích...)

    Giải thích mã nguồn theo từng dòng

    Đoạn mã Arduino ở trên chứa lời giải thích theo từng dòng. Vui lòng đọc các chú thích trong mã.