Search Code

Hướng dẫn ESP32 30/55 - Điều khiển Servo qua web bằng MQTT sử dụng dịch vụ Adafruit IO | Bộ kit học IoT ESP32 của SunFounder

Hướng dẫn ESP32 30/55 - Điều khiển Servo qua web bằng MQTT sử dụng dịch vụ Adafruit IO | Bộ kit học IoT ESP32 của SunFounder

Trong hướng dẫn này, chúng ta sẽ học cách điều khiển vị trí của động cơ servo bằng vi điều khiển ESP32 và giao thức MQTT qua web. Bằng cách tận dụng dịch vụ Adafruit IO, bạn sẽ có thể định vị servo ở các góc khác nhau như 0°, 90°, hoặc 180° từ xa. Dự án này chứng minh khả năng của ESP32, bao gồm Wi-Fi và Bluetooth tích hợp, khiến nó trở thành công cụ mạnh mẽ cho các ứng dụng IoT.

ESP32-30_MQTT_diagram-0

Trong dự án này, chúng ta sẽ thiết lập một MQTT broker bằng Adafruit IO, tạo một bảng điều khiển để điều khiển servo, và kết nối ESP32 với nó. Vị trí servo sẽ có thể điều chỉnh thông qua một thanh trượt trên bảng điều khiển, cho phép điều khiển thời gian thực từ bất kỳ thiết bị kết nối internet nào (trong video tại 5:30).

Giải thích phần cứng

Các thành phần chính của dự án này bao gồm vi điều khiển ESP32 và động cơ servo. ESP32 là một vi điều khiển đa năng với khả năng Wi-Fi và Bluetooth tích hợp, lý tưởng cho các ứng dụng IoT. Nó giao tiếp với dịch vụ Adafruit IO bằng giao thức MQTT, nhẹ và hiệu quả để truyền tin nhắn qua internet.

Động cơ servo là một bộ truyền động quay cho phép điều khiển chính xác vị trí góc. Nó hoạt động bằng cách nhận tín hiệu điều chế độ rộng xung (PWM) quyết định vị trí của nó. Trong dự án này, chúng ta sẽ kết nối servo với một trong các chân kỹ thuật số trên ESP32, cho phép chúng ta điều khiển góc của nó từ xa.

Chi tiết bảng dữ liệu

Nhà sản xuất Parallax
Số bộ phận SG90
Điện áp logic/IO 3.3 V - 5 V
Điện áp cung cấp 4.8 V - 6.0 V
Dòng điện đầu ra (mỗi kênh) 1 A tối đa
Hướng dẫn tần số PWM 50 Hz
Ngưỡng logic đầu vào 0.3 V - 0.7 V
Sụt áp / RDS(on) / bão hòa 0.2 V tối đa
Giới hạn nhiệt Nhiệt độ hoạt động: -10°C đến 60°C
Đóng gói Vỏ nhựa
Ghi chú / biến thể Servo mini, xoay 180°

 

  • Đảm bảo cung cấp điện áp phù hợp cho servo (4.8 V - 6.0 V).
  • Sử dụng chung một điểm nối đất giữa ESP32 và servo.
  • Theo dõi tín hiệu PWM để tránh vượt quá giới hạn của servo.
  • Kết nối servo chắc chắn để tránh mất kết nối trong quá trình hoạt động.
  • Cập nhật thư viện Adafruit MQTT để đảm bảo tương thích.

Sơ đồ MQTT

ESP32-30_MQTT_diagram-2
ESP32-30_MQTT_diagram
ESP32-28_dht_temperature-sensor-main

Hướng dẫn nối dây

ESP32-17-Sevo_motor-wiring

Để nối động cơ servo với ESP32, bắt đầu bằng cách kết nối dây nối đất của servo với chân nối đất trên ESP32. Tiếp theo, kết nối dây nguồn (thường màu đỏ) của servo với chân 5V trên ESP32. Cuối cùng, kết nối dây tín hiệu (thường màu vàng hoặc trắng) với chân kỹ thuật số 25 trên ESP32. Đảm bảo các kết nối chắc chắn để tránh mất kết nối trong quá trình hoạt động.

Nếu bạn sử dụng pin để cấp nguồn cho ESP32, hãy đảm bảo điện áp pin nằm trong phạm vi chấp nhận được cho cả ESP32 và servo. Ngoài ra, hãy kiểm tra kỹ rằng việc nối dây khớp với định nghĩa chân trong mã của bạn để tránh mọi sự cố (trong video tại 12:45).

Ví dụ mã & hướng dẫn chi tiết

Trong mã được cung cấp, trước tiên chúng ta bao gồm các thư viện cần thiết cho ESP32 và MQTT. Chúng ta định nghĩa đối tượng servo và chỉ định chân mà nó được kết nối với const int servoPin = 25;. Góc mặc định cũng được đặt với const int defaultServoAngle = 90;, đây sẽ là vị trí ban đầu khi ESP32 khởi động.


Servo myServo;
const int servoPin = 25;
const int defaultServoAngle = 90;
int servoAngle = defaultServoAngle;

Đoạn mã này khởi tạo servo trên chân 25 và đặt góc mặc định của nó là 90°. Biến servoAngle sẽ được cập nhật dựa trên các tin nhắn nhận được từ MQTT broker.

Trong hàm setup(), chúng ta kết nối với Wi-Fi và thiết lập MQTT client. Thông tin đăng nhập cho Adafruit IO được định nghĩa ở đây, bao gồm tên người dùng và khóa:


#define AIO_USERNAME "robojax"
#define AIO_KEY "aio_xmIW58uNNsjJCSOqzZ9QoHyq29wu"

Phần này thiết lập kết nối với dịch vụ Adafruit IO. Đảm bảo thay thế các giá trị này bằng thông tin đăng nhập Adafruit IO của riêng bạn khi triển khai mã.

Cuối cùng, vòng lặp chính đảm bảo kết nối với máy chủ MQTT luôn hoạt động và xử lý các tin nhắn đến. Vị trí servo được cập nhật dựa trên góc nhận được:


mqtt.processPackets(500);
int pulseWidth = map(servoAngle, 0, 180, minPulseWidth, maxPulseWidth);
myServo.writeMicroseconds(pulseWidth);

Đoạn mã này ánh xạ góc servo sang độ rộng xung tương ứng và gửi đến động cơ servo. Hàm processPackets() cho phép ESP32 xử lý các thông điệp MQTT đến, đảm bảo servo phản ứng với các lệnh được gửi qua bảng điều khiển Adafruit IO.

Trình diễn / Điều mong đợi

Sau khi mọi thứ được thiết lập, bạn sẽ có thể điều khiển servo từ bảng điều khiển Adafruit IO bằng thanh trượt bạn đã tạo. Khi bạn di chuyển thanh trượt, servo sẽ điều chỉnh góc của nó theo thời gian thực. Đảm bảo ESP32 của bạn được kết nối với Wi-Fi và kết nối MQTT ổn định. Nếu servo không phản hồi, hãy kiểm tra dây nối và nguồn điện cấp cho servo (trong video tại 20:15).

Lưu ý về giới hạn phạm vi của servo; gửi giá trị ngoài khoảng 0° đến 180° có thể khiến nó hoạt động không như mong muốn. Mã bao gồm các kiểm tra để ngăn chặn các trường hợp như vậy bằng cách giới hạn góc trong phạm vi này.

Mốc thời gian video

  • 00:00 Bắt đầu
  • 1:54 Giới thiệu dự án
  • 2:52 Giới thiệu về MQTT
  • 6:50 Thiết lập Adafruit IO
  • 9:54 Đấu dây servo
  • 11:07 Giải thích mã
  • 18:59 Chọn bo mạch ESP32 và cổng COM
  • 22:10 Trình diễn dự án

Hình ảnh

ESP32-17-Sevo_motor-schematic
ESP32-17-Sevo_motor-schematic
ESP32-17-Sevo_motor-wiring
ESP32-17-Sevo_motor-wiring
ESP32-28_dht_temperature-sensor-main
ESP32-28_dht_temperature-sensor-main
ESP32-30_MQTT_diagram
ESP32-30_MQTT_diagram
ESP32-30_MQTT_diagram-0
ESP32-30_MQTT_diagram-0
ESP32-30_MQTT_diagram-2
ESP32-30_MQTT_diagram-2
831-ESP32 Tutorial 30/55- ESP32 to control Servo motor using MQTT service of Adafruit
Ngôn ngữ: C++
/***********************************************************************
 This is Arduino sketch for ESP32 to control Servo motor using MQTT service of Adafruit
 www.Robojax.com
 Written By Ahamd Shamshiri
 on Feb 2nd, 2024
Watch video instruction for this code on YouTube https://youtu.be/T4DhWNg2Rb8
  Adafruit MQTT Library ESP32 Adafruit IO SSL/TLS example
  this code can be downloaded from  https://robojax.com/RJT671

  

/// ref: https://www.electronicwings.com/esp32/esp32-mqtt-client
*/
#include <ESP32Servo.h>

// Define the servo and the pin it is connected to
Servo myServo;
const int servoPin = 25;
const int defaultServoAngle = 90;
int servoAngle =defaultServoAngle;

// Define the minimum and maximum pulse widths for the servo
const int minPulseWidth = 500; // 0.5 ms
const int maxPulseWidth = 2500; // 2.5 ms




#include <WiFi.h>
#include "WiFiClientSecure.h"
#include "Adafruit_MQTT.h"
#include "Adafruit_MQTT_Client.h"

/************************* WiFi Access Point *********************************/


#define WLAN_SSID "Barqasaa"
#define WLAN_PASS "wan9&Jang~5"

/************************* Adafruit.io Setup *********************************/

#define AIO_SERVER "io.adafruit.com"

// Using port 8883 for MQTTS
#define AIO_SERVERPORT 8883

// Adafruit IO Account Configuration
// (to obtain these values, visit https://io.adafruit.com and click on Active Key)
// #define AIO_USERNAME "YOUR_ADAFRUIT_IO_USERNAME"
// #define AIO_KEY      "YOUR_ADAFRUIT_IO_KEY"

#define AIO_USERNAME "robojax"
#define AIO_KEY "aio_xmIW58uNNsjJCSOqzZ9QoHyq29wu"

/************ Global State (you don't need to change this!) ******************/

// WiFiFlientSecure for SSL/TLS support
WiFiClientSecure client;

// Setup the MQTT client class by passing in the WiFi client and MQTT server and login details.
Adafruit_MQTT_Client mqtt(&client, AIO_SERVER, AIO_SERVERPORT, AIO_USERNAME, AIO_KEY);


// io.adafruit.com root CA
const char* adafruitio_root_ca = \
      "-----BEGIN CERTIFICATE-----\n"
      "MIIEjTCCA3WgAwIBAgIQDQd4KhM/xvmlcpbhMf/ReTANBgkqhkiG9w0BAQsFADBh\n"
      "MQswCQYDVQQGEwJVUzEVMBMGA1UEChMMRGlnaUNlcnQgSW5jMRkwFwYDVQQLExB3\n"
      "d3cuZGlnaWNlcnQuY29tMSAwHgYDVQQDExdEaWdpQ2VydCBHbG9iYWwgUm9vdCBH\n"
      "MjAeFw0xNzExMDIxMjIzMzdaFw0yNzExMDIxMjIzMzdaMGAxCzAJBgNVBAYTAlVT\n"
      "MRUwEwYDVQQKEwxEaWdpQ2VydCBJbmMxGTAXBgNVBAsTEHd3dy5kaWdpY2VydC5j\n"
      "b20xHzAdBgNVBAMTFkdlb1RydXN0IFRMUyBSU0EgQ0EgRzEwggEiMA0GCSqGSIb3\n"
      "DQEBAQUAA4IBDwAwggEKAoIBAQC+F+jsvikKy/65LWEx/TMkCDIuWegh1Ngwvm4Q\n"
      "yISgP7oU5d79eoySG3vOhC3w/3jEMuipoH1fBtp7m0tTpsYbAhch4XA7rfuD6whU\n"
      "gajeErLVxoiWMPkC/DnUvbgi74BJmdBiuGHQSd7LwsuXpTEGG9fYXcbTVN5SATYq\n"
      "DfbexbYxTMwVJWoVb6lrBEgM3gBBqiiAiy800xu1Nq07JdCIQkBsNpFtZbIZhsDS\n"
      "fzlGWP4wEmBQ3O67c+ZXkFr2DcrXBEtHam80Gp2SNhou2U5U7UesDL/xgLK6/0d7\n"
      "6TnEVMSUVJkZ8VeZr+IUIlvoLrtjLbqugb0T3OYXW+CQU0kBAgMBAAGjggFAMIIB\n"
      "PDAdBgNVHQ4EFgQUlE/UXYvkpOKmgP792PkA76O+AlcwHwYDVR0jBBgwFoAUTiJU\n"
      "IBiV5uNu5g/6+rkS7QYXjzkwDgYDVR0PAQH/BAQDAgGGMB0GA1UdJQQWMBQGCCsG\n"
      "AQUFBwMBBggrBgEFBQcDAjASBgNVHRMBAf8ECDAGAQH/AgEAMDQGCCsGAQUFBwEB\n"
      "BCgwJjAkBggrBgEFBQcwAYYYaHR0cDovL29jc3AuZGlnaWNlcnQuY29tMEIGA1Ud\n"
      "HwQ7MDkwN6A1oDOGMWh0dHA6Ly9jcmwzLmRpZ2ljZXJ0LmNvbS9EaWdpQ2VydEds\n"
      "b2JhbFJvb3RHMi5jcmwwPQYDVR0gBDYwNDAyBgRVHSAAMCowKAYIKwYBBQUHAgEW\n"
      "HGh0dHBzOi8vd3d3LmRpZ2ljZXJ0LmNvbS9DUFMwDQYJKoZIhvcNAQELBQADggEB\n"
      "AIIcBDqC6cWpyGUSXAjjAcYwsK4iiGF7KweG97i1RJz1kwZhRoo6orU1JtBYnjzB\n"
      "c4+/sXmnHJk3mlPyL1xuIAt9sMeC7+vreRIF5wFBC0MCN5sbHwhNN1JzKbifNeP5\n"
      "ozpZdQFmkCo+neBiKR6HqIA+LMTMCMMuv2khGGuPHmtDze4GmEGZtYLyF8EQpa5Y\n"
      "jPuV6k2Cr/N3XxFpT3hRpt/3usU/Zb9wfKPtWpoznZ4/44c1p9rzFcZYrWkj3A+7\n"
      "TNBJE0GmP2fhXhP1D/XVfIW/h0yCJGEiV9Glm/uGOa3DXHlmbAcxSyCRraG+ZBkA\n"
      "7h4SeM6Y8l/7MBRpPCz6l8Y=\n"
      "-----END CERTIFICATE-----\n";

/****************************** Feeds ***************************************/

// Setup a feed called 'test' for publishing and 'test2' for subscription.
// Notice MQTT paths for AIO follow the form: <username>/feeds/<feedname>
Adafruit_MQTT_Subscribe SERVO = Adafruit_MQTT_Subscribe(&mqtt, AIO_USERNAME "/feeds/servo-angle-1");


/*************************** Sketch Code ************************************/


void setup() {
    // Attach the servo to the specified pin and set its pulse width range
  myServo.attach(servoPin, minPulseWidth, maxPulseWidth);

  // Set the PWM frequency for the servo
  myServo.setPeriodHertz(50); // Standard 50Hz servo

  Serial.begin(115200);
  delay(10);

  Serial.println(F("Adafruit IO MQTTS (SSL/TLS) Example"));

  // Connect to WiFi access point.
  Serial.println();
  Serial.println();
  Serial.print("Connecting to ");
  Serial.println(WLAN_SSID);

  delay(1000);

  WiFi.begin(WLAN_SSID, WLAN_PASS);
  delay(2000);

  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }
  Serial.println();

  Serial.println("WiFi connected");
  Serial.println("IP address: ");
  Serial.println(WiFi.localIP());

  // Set Adafruit IO's root CA
  client.setCACert(adafruitio_root_ca);

  // register callback for feed
  SERVO.setCallback(servoCallback);
  // Setup MQTT subscription for time feed.
  mqtt.subscribe(&SERVO);


}

// uint32_t x=0;


void loop() {

  // Ensure the connection to the MQTT server is alive (this will make the first
  // connection and automatically reconnect when disconnected).  See the MQTT_connect
  // function definition further below.
  MQTT_connect();

  Serial.print("Angle: ");
  Serial.println(servoAngle);

  // wait 0.5 seconds for subscription messages
  mqtt.processPackets(500);

  //from lesson 17
  int pulseWidth = map(servoAngle, 0, 180, minPulseWidth, maxPulseWidth);
  myServo.writeMicroseconds(pulseWidth);
  delay(15);
  // wait a couple seconds to avoid rate limit
  //delay(2000);
}

void servoCallback(char* message, uint16_t len) {
  char messageBuffer[40];
  snprintf(messageBuffer, sizeof(messageBuffer), "Servo status is :: %s, len :: %u", message, len);
  Serial.println(messageBuffer);
  Serial.println(message);
  String inString = message;//sotre the message to String
 
  servoAngle  =  inString.toInt();//convert the message to Integer
  if(servoAngle >180 || servoAngle < 0)
  {
    servoAngle =0;
  }

}




// Function to connect and reconnect as necessary to the MQTT server.
// Should be called in the loop function and it will take care if connecting.
void MQTT_connect() {
  int8_t ret;
  // Stop if already connected.
  if (mqtt.connected()) {
    return;
  }
  Serial.print("Connecting to MQTT... ");
  uint8_t retries = 3;
  while ((ret = mqtt.connect()) != 0) {  // connect will return 0 for connected
    Serial.println(mqtt.connectErrorString(ret));
    Serial.println("Retrying MQTT connection in 5 seconds...");
    mqtt.disconnect();
    delay(5000);  // wait 5 seconds
    retries--;
    if (retries == 0) {
      // basically die and wait for WDT to reset me
      while (1)
        ;
    }
  }
  Serial.println("MQTT Connected!");
}

Nghĩ bạn có thể cần

Tài nguyên & tài liệu tham khảo

Tập tin📁

Các tập tin khác