ค้นหาโค้ด

บทช่วยสอน ESP32 49/55 - ควบคุมมอเตอร์ DC ผ่านอินเทอร์เน็ตโดยใช้ Adafruit IoT | ชุด ESP32 ของ SunFounder

บทช่วยสอน ESP32 49/55 - ควบคุมมอเตอร์ DC ผ่านอินเทอร์เน็ตโดยใช้ Adafruit IoT | ชุด ESP32 ของ SunFounder

ในบทช่วยสอนนี้ เราจะสำรวจวิธีการควบคุมมอเตอร์ไฟฟ้ากระแสตรงผ่านอินเทอร์เน็ตโดยใช้ ESP32 และบริการ Adafruit IO MQTT ความเร็วและทิศทางของมอเตอร์ไฟฟ้ากระแสตรงสามารถควบคุมได้จากระยะไกล ทำให้สามารถควบคุมได้อย่างมีประสิทธิภาพจากทุกที่ที่มีการเชื่อมต่ออินเทอร์เน็ต โปรเจกต์นี้แสดงให้เห็นถึงความสามารถของไมโครคอนโทรลเลอร์ ESP32 ซึ่งมี Wi-Fi ในตัว ทำให้เหมาะสำหรับการใช้งานอินเทอร์เน็ตของสรรพสิ่ง (IoT)

esp32-49-DC-motor-mqtt-main

เราจะ implement ระบบที่มอเตอร์สามารถเริ่มทำงาน หยุด และปรับความเร็วได้ผ่านเว็บอินเทอร์เฟซที่เชื่อมต่อกับ Adafruit IO ผู้ใช้สามารถสมัครรับหัวข้อเฉพาะสำหรับการควบคุมมอเตอร์และปรับพารามิเตอร์ตามต้องการ เพื่อให้เข้าใจกระบวนการได้ดีขึ้น โปรดดูวิดีโอที่มาพร้อมกับบทช่วยสอนนี้ (ในวิดีโอที่ 00:00)

อธิบายฮาร์ดแวร์

สำหรับโปรเจกต์นี้ เราจะใช้ไมโครคอนโทรลเลอร์ ESP32 ซึ่งเป็นหัวใจของระบบของเรา ESP32 สามารถจัดการการสื่อสาร Wi-Fi ทำให้เหมาะสำหรับแอปพลิเคชัน IoT ของเรา มันเชื่อมต่อกับแพลตฟอร์ม Adafruit IO ทำให้เราสามารถส่งและรับข้อความผ่านโปรโตคอล MQTT

นอกจากนี้ เราจะใช้ไดรเวอร์มอเตอร์ L293D ซึ่งจำเป็นสำหรับการควบคุมมอเตอร์ไฟฟ้ากระแสตรง L293D สามารถขับมอเตอร์ไฟฟ้ากระแสตรงสองตัวและอนุญาตให้ควบคุมทั้งทิศทางและความเร็วผ่าน Pulse Width Modulation (PWM) โดยพื้นฐานแล้วมันทำหน้าที่เป็นอินเทอร์เฟซระหว่าง ESP32 และมอเตอร์ จัดการกระแสที่สูงขึ้นซึ่งมอเตอร์ต้องการ ในขณะที่แยก ESP32 จากสัญญาณ back-emf ที่อาจเป็นอันตราย

รายละเอียด Datasheet

ผู้ผลิต Texas Instruments
หมายเลขชิ้นส่วน L293D
แรงดันไฟฟ้าลอจิก/IO 4.5 - 36 V
แรงดันไฟฟ้าจ่าย 4.5 - 36 V
กระแสเอาต์พุต (ต่อช่อง) 600 mA
กระแสสูงสุด (ต่อช่อง) 1.2 A
คำแนะนำความถี่ PWM 10 kHz (โดยทั่วไป)
เกณฑ์ลอจิกอินพุต 0.8 V (สูง), 2.0 V (ต่ำ)
แรงดันตก / RDS(on) / ความอิ่มตัว 1.5 V สูงสุด
ขีดจำกัดความร้อน 150 °C
แพ็คเกจ DIP-16
หมายเหตุ / รุ่นต่างๆ ไดรเวอร์ half-H กระแสสูงสี่ช่อง

 

  • ตรวจสอบให้แน่ใจว่ามีการระบายความร้อนที่เหมาะสมสำหรับการทำงานต่อเนื่อง
  • ใช้ PWM เพื่อควบคุมความเร็วมอเตอร์อย่างมีประสิทธิภาพ
  • สังเกตขีดจำกัดแรงดันไฟฟ้าอินพุตเพื่อป้องกันความเสียหาย
  • ตรวจสอบการเชื่อมต่อกราวด์ที่ถูกต้องระหว่างส่วนประกอบทั้งหมด
  • ระวัง back-emf; ใช้ไดโอดหากจำเป็น
  • ตรวจสอบการเดินสายอีกครั้งเนื่องจากขั้วสามารถส่งผลต่อทิศทางของมอเตอร์
  • ทดสอบด้วยแรงดันไฟฟ้าที่ต่ำกว่าก่อนการทำงานเต็มรูปแบบ
  • สังเกตความร้อนสูงเกินไประหว่างการใช้งานเป็นเวลานาน
  • ตรวจสอบให้แน่ใจว่าได้ debounce สวิตช์เชิงกลหากใช้
  • ตรวจสอบให้แน่ใจว่า ESP32 ไม่ได้รับกระแสเกินจากมอเตอร์

คำแนะนำการเดินสาย

ESP32-15_L293D_motor_schematic

เริ่มต้นโดยการเชื่อมต่อแหล่งจ่ายไฟ เชื่อมต่อขั้วบวกของแหล่งจ่ายไฟภายนอกของคุณเข้ากับพิน VCC ของ L293D (พิน 8) และกราวด์เข้ากับพิน GND (พิน 4) ตรวจสอบให้แน่ใจว่า ESP32 ได้รับพลังงานแยกต่างหากหากจำเป็น โดยทั่วไปผ่านการเชื่อมต่อ micro USB

ถัดไป เชื่อมต่อมอเตอร์เข้ากับ L293D ขั้วหนึ่งของมอเตอร์ควรเชื่อมต่อกับพินเอาต์พุต 3 (พิน 2 ของ L293D) และขั้วอื่นเข้ากับพินเอาต์พุต 6 (พิน 7 ของ L293D) สำหรับสัญญาณควบคุม เชื่อมต่อพิน 13 ของ ESP32 เข้ากับพินอินพุต 2 (พิน 1 ของ L293D) และพิน 14 เข้ากับพินอินพุต 7 (พิน 2 ของ L293D) พิน enable (พิน 1) ควรเชื่อมต่อกับแหล่งจ่าย 5V เพื่อเปิดใช้งานไดรเวอร์ สุดท้าย ตรวจสอบให้แน่ใจว่ากราวด์ของ ESP32 เชื่อมต่อกับกราวด์ของ L293D เพื่อการอ้างอิงร่วมกัน

ตัวอย่างโค้ดและคำอธิบาย

โค้ดที่ให้มาจะเริ่มต้นไลบรารีที่จำเป็นและตั้งค่าไคลเอนต์ Wi-Fi และ MQTT ตัวระบุหลักรวมถึง motorSpeed, motorDirection และ motorStart ซึ่งจัดการการทำงานของมอเตอร์ตามคำสั่งที่ได้รับจาก Adafruit IO

bool debug = false;
#define motor1A 13
#define motor2A 14
int motorSpeed = 0;
int motorDirection = 1;
int motorStart = 1;

ในส่วนนี้ พินมอเตอร์ถูกกำหนดพร้อมกับตัวแปรเริ่มต้นสำหรับการควบคุมความเร็ว ทิศทาง และสถานะเริ่ม/หยุดของมอเตอร์ ตัวแปร motorSpeed จะถูกปรับตามอินพุตจาก Adafruit IO

void setup() {
  Serial.begin(115200);
  WiFi.begin(WLAN_SSID, WLAN_PASS);
  delay(2000);
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
  }
}

ในฟังก์ชัน setup การสื่อสารแบบอนุกรมถูกเริ่มต้น และ ESP32 เชื่อมต่อกับเครือข่าย Wi-Fi ที่ระบุ การเชื่อมต่อนี้สำคัญสำหรับการเปิดใช้งานการสื่อสาร MQTT

void loop() {
  MQTT_connect();
  mqtt.processPackets(500);
  runMotor();
}

ฟังก์ชัน loop นี้สร้างการเชื่อมต่อ MQTT และประมวลผลแพ็กเก็ตที่เข้ามาเพื่อควบคุมมอเตอร์ตามคำสั่งล่าสุดที่ได้รับ ฟังก์ชัน runMotor() ถูกเรียกเพื่อใช้การตั้งค่าปัจจุบันกับมอเตอร์

การสาธิต / สิ่งที่คาดหวัง

เมื่อการตั้งค่าเสร็จสมบูรณ์และอัปโหลดโค้ดแล้ว คุณควรจะสามารถควบคุมมอเตอร์ผ่านแดชบอร์ด Adafruit IO ได้ คุณสามารถปรับความเร็วมอเตอร์ได้โดยใช้แถบเลื่อนและเปลี่ยนทิศทางด้วยสวิตช์สลับ หากทุกอย่างเชื่อมต่ออย่างถูกต้อง มอเตอร์จะตอบสนองต่อคำสั่งเหล่านี้แบบเรียลไทม์ ซึ่งแสดงให้เห็นถึงความหน่วงต่ำของระบบ (ในวิดีโอที่เวลา 00:00)

ปัญหาที่พบบ่อย ได้แก่ ทิศทางการหมุนของมอเตอร์ที่กลับด้านเนื่องจากการเดินสายไฟที่ไม่ถูกต้อง ดังนั้นควรตรวจสอบการเชื่อมต่ออีกครั้งหากมอเตอร์ไม่ทำงานตามที่คาดหวัง นอกจากนี้ ตรวจสอบให้แน่ใจว่า MQTT topics ของคุณถูกตั้งค่าอย่างถูกต้องใน Adafruit IO ให้ตรงกับโค้ด

ไทม์สแตมป์ในวิดีโอ

  • 00:00 เริ่มต้น
  • 2:21 แนะนำโปรเจกต์
  • 4:20 วิธีควบคุม DC Motor
  • 6:39 L293D Motor Driver
  • 11:42 MQTT คืออะไร?
  • 15:03 การตั้งค่า Adafruit IO
  • 19:17 อธิบายการเดินสายไฟ
  • 22:42 อธิบายโค้ด
  • 35:28 การสาธิตโปรเจกต์

ภาพ

ESP32-15_L293D_motor_schematic
ESP32-15_L293D_motor_schematic
esp32-49-DC-motor-mqtt-main
esp32-49-DC-motor-mqtt-main
851-ESP32 Tutorial 49/55- Arduino code using ESP32 to DC Motor using MQTT service of Adafruit
ภาษา: C++
/***********************************************************************
 This is Arduino sketch for ESP32 to DC Motor using MQTT service of Adafruit
 Watch video instruction https://youtu.be/OUgyPXNYg3g
 📚⬇️ Download and resource page https://robojax.com/RJT673
 Written By Ahamd Shamshiri
 on Feb 18, 2024

  Adafruit MQTT Library ESP32 Adafruit IO SSL/TLS example

  

/// ref: https://www.electronicwings.com/esp32/esp32-mqtt-client
*/
bool debug = false;
#define motor1A 13
#define motor2A 14

// PWM settings
const int freq = 500; // PWM frequency: 500 Hz
const int resolution = 8; // PWM resolution: 8 bits
const int channelA = 0; // PWM channel for motor1A: 0
const int channelB = 1; // PWM channel for motor2A: 1

char* dir[]={"CCW", "CW"};

int motorSpeed =0;
int motorDirection =1;
int motorStart = 1;
int dutyCycle =0;

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

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


#define WLAN_SSID "Book"
#define WLAN_PASS "88888888"

/************************* 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_jHpm60SEsWUdU5x472FViZjWzsY9"

/************ 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 MOTOR_SPEED = Adafruit_MQTT_Subscribe(&mqtt, AIO_USERNAME "/feeds/motor.speed");
Adafruit_MQTT_Subscribe MOTOR_DIRECTION = Adafruit_MQTT_Subscribe(&mqtt, AIO_USERNAME "/feeds/motor.direction");
Adafruit_MQTT_Subscribe MOTOR_START = Adafruit_MQTT_Subscribe(&mqtt, AIO_USERNAME "/feeds/motor.start");


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


void setup() {
  // Set up PWM
  ledcSetup(channelA, freq, resolution);
  ledcSetup(channelB, freq, resolution);

  // Attach PWM channels to GPIO pins
  ledcAttachPin(motor1A, channelA);
  ledcAttachPin(motor2A, channelB);

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

  Serial.println(F("DC Motor over MQTT 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
  MOTOR_SPEED.setCallback(MOTOR_SPEED_Callback);
  // Setup MQTT subscription for time feed.
  mqtt.subscribe(&MOTOR_SPEED);

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

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

}

// 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("Speed: ");
  // Serial.print (motorSpeed);
  // Serial.print(" Dir: ");
  // Serial.print (dir[motorDirection]);
  // Serial.print(" Sart: ");
  // Serial.println(motorStart);

  // Serial.print("DutyCycle: ");
  // Serial.println(dutyCycle);

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

   runMotor();//very important
  // wait a couple seconds to avoid rate limit
  //delay(2000);
}

void MOTOR_SPEED_Callback(char* message, uint16_t len) {
  char messageBuffer[40];
  //snprintf(messageBuffer, sizeof(messageBuffer), "Color status is :: %s, len :: %u", message, len);
  //Serial.println(messageBuffer);
  Serial.println(message);
  String inString = message;//sotre the message to String
 
  motorSpeed  =  inString.toInt();//convert the message to Integer
  if(motorSpeed >100 || motorSpeed < 0)
  {
    motorSpeed = 0;
  }
  dutyCycle = map (motorSpeed, 0, 100, 0, 255);
 
}


void MOTOR_DIRECTION_Callback(char* message, uint16_t len) {
  char messageBuffer[40];
  //snprintf(messageBuffer, sizeof(messageBuffer), "Color status is :: %s, len :: %u", message, len);
  //Serial.println(messageBuffer);
  Serial.println(message);
  String inString = message;//sotre the message to String
 
  motorDirection  =  inString.toInt();//convert the message to Integer

 
}


void MOTOR_START_Callback(char* message, uint16_t len) {
  char messageBuffer[40];
  //snprintf(messageBuffer, sizeof(messageBuffer), "Color status is :: %s, len :: %u", message, len);
  //Serial.println(messageBuffer);
  Serial.println(message);

  String inString = message;//sotre the message to String
 
  motorStart  =  inString.toInt();//convert the message to Integer

 
}


void runMotor()
{

  if(motorStart ==1)
  {
      if(debug)
      {
        Serial.print("Motor running:");
        Serial.print(dir[motorDirection]);
        Serial.print(" at ");
        Serial.print(motorSpeed);
        Serial.println("%");
      }
    if(motorDirection)
    {
      ledcWrite(channelA, dutyCycle);
      ledcWrite(channelB, 0);
      delay(50); 
    }else{

      ledcWrite(channelA, 0);
      ledcWrite(channelB, dutyCycle);
      delay(50); 
    }
  }else{
    if(debug)
    {
      Serial.println("***Motor Stopped***");
    }
      ledcWrite(channelA, 0);
      ledcWrite(channelB, 0);   
  }

}//runMotor() end

// 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!");
}

แหล่งข้อมูลและเอกสารอ้างอิง

ยังไม่มีทรัพยากรเลย

ไฟล์📁

ไม่มีไฟล์ที่พร้อมใช้งาน