شِفر (کود) جستجو

کنترل ۳۲ سروو از راه Wi-Fi با استفاده از ESP32 و PCA9685 از طریق دسکتاپ یا گوشی موبایل V5

کنترل ۳۲ سروو از راه Wi-Fi با استفاده از ESP32 و PCA9685 از طریق دسکتاپ یا گوشی موبایل V5

در این آموزش، یاد خواهیم گرفت که چگونه ۳۲ موتور سرو را با استفاده از ماجیول کنترلر PWM PCA9685 متصل به ESP32 از طریق Wi-Fi کنترل کنیم. این تنظیم امکان کنترل هر سرو به صورت جداگانه یا همه آن‌ها به‌صورت همزمان از طریق یک رابط وب که از طریق دستگاه‌های دسکتاپ یا موبایل در دسترس است را فراهم می‌کند. در پایان این راهنما، شما یک سیستم کاملاً کاربردی خواهید داشت که قادر به مدیریت چندین سرو به راحتی باشد.

PCA9685 module-0

ماجیول PCA9685 راهی ساده برای کنترل چندین سروو با استفاده از سیگنال‌های PWM فراهم می‌کند، در حالی که ESP32 وظیفه ارتباط Wi-Fi و عملکرد سرور وب را بر عهده دارد. شما می‌توانید زاویه هر موتور سروو را از طریق یک رابط کاربری دوست‌داشتنی که دکمه‌هایی برای هر سروو نمایش می‌دهد، تنظیم کنید. برای مرجع بصری، حتماً ویدیو را مشاهده کنید (در ویدیو در 00:00).

توضیح سخت‌افزار

این پروژه عمدتاً از میکروکنترلر ESP32 و کنترل‌کننده PWM PCA9685 استفاده می‌کند. ESP32 میکروکنترلر قدرتمندی است که دارای قابلیت‌های Wi-Fi داخلی است و آن را برای پروژه‌های IoT ایده‌آل می‌سازد. PCA9685 یک کنترل‌کننده PWM 16 کاناله است که می‌تواند به صورت زنجیره‌ای برای کنترل حداکثر 64 سروو استفاده شود. این دستگاه از طریق پروتکل I2C با ESP32 ارتباط برقرار می‌کند که امکان اتصال و آدرس‌دهی جداگانه چندین کنترلر را فراهم می‌کند.

هر ماجیول PCA9685 دارای یک آدرس پیش‌فرض I2C معادل 0x40 است. هنگام استفاده از چندین ماجیول، می‌توانید آدرس‌های آنها را با لحیم‌کاری جامپرهای خاص تغییر دهید. به عنوان مثال، ماجیول اول می‌تواند در 0x40، ماجیول دوم در 0x41 و به همین ترتیب باشد. این قابلیت زنجیره‌ای اجازه می‌دهد تا بسیاری از سروها را بدون نیاز به پایه‌های اضافی بر روی ESP32 کنترل کنید.

اتصال دو صفحه PCA9685

همانطور که در تصویر بالا نشان داده شده است، برای بورد PCA9685 شماره ۲ (در سمت چپ)، مطمئن شوید که آن مسیر را لحیم کنید تا آدرس I2C تنظیم شود و با بورد ۱ (در سمت راست) متفاوت باشد.

جزئیات برگه مشخصات

تولیدکننده آدافرونت
شماره قطعه PCA9685
ولتاژ منطقی/ورودی و خروجی ۲.۳ ولت تا ۵.۵ ولت
ولتاژ تامین ۲.۳ ولت تا ۵.۵ ولت
جریان خروجی (به ازای هر کانال) ۲۵ میلی آمپر
جریان اوج (برای هر کانال) 100 میلی‌آمپر
راهنمایی فرکانس PWM ۴۰ هرتز تا ۱۰۰۰ هرتز
آستانه‌های منطقی ورودی 0.3 ولت Vcc (پایین) / 0.7 ولت Vcc (بالا)
افت ولتاژ / RDS(on)/ اشباع ۰.۵ ولت حداکثر
محدودیت‌های دما حداکثر ۱۲۵ درجه سانتی‌گراد
پکیج TSSOP-28
یادداشت‌ها / واریانت‌ها تا ۶۴ سروو با سسکادینگ

  • تأمین منبع تغذیه مناسب (5 ولت، 2 آمپر توصیه می‌شود).
  • در صورت نیاز از مقاومت‌های کشش به بالا در خطوط SDA و SCL استفاده کنید.
  • هنگام استفاده از چند ماجیول PCA9685، آدرس‌های I2C را به دقت بررسی کنید.
  • به خنک‌سازی حرارتی برای کاربردهای پرقدرت توجه کنید.
  • سروها را به صورت جداگانه آزمایش کنید تا از عملکرد صحیح آنها اطمینان حاصل شود.

نقشه‌برداری پایه‌های رایج I2C:SDA= GPIO 21،SCL= GPIO 22.

دستورالعمل‌های سیم‌کشی

ESP32 wiring for PCA99685 for 32 sevo motors

برای اتصال PCA9685 و ESP32، ابتدا باید منبع تغذیه و زمین را وصل کنید. پایه مثبت (V+) از PCA9685 به خروجی ۵ ولت منبع تغذیه خود وصل کنید. زمین (GND) PCA9685 را به زمین ESP32 وصل کنید. مطمئن شوید که هر دو دستگاه یک زمین مشترک دارند.

سپس، برای ارتباط I2C، پایه SDA PCA9685 را به GPIO 21 روی ESP32 و پایه SCL را به GPIO 22 متصل کنید. اگر از چندین ماجیول PCA9685 استفاده می‌کنید، اطمینان حاصل کنید که آن‌ها به درستی آدرس‌دهی شده‌اند با لحیم کردن جامپر A0 تا آدرس ماجیول دوم به 0x41 تغییر کند و به همین ترتیب. پس از آن، می‌توانید موتورها را به پایه‌های خروجی PWM PCA9685 متصل کنید.

نمونه‌های شِفر (کود) و راهنمایی

شِفر (کود) با وارد کردن کتابخانه‌های لازم و راه‌اندازی دو بورد PCA9685 آغاز می‌شود. شناسه‌هایی مانندmaximumServoوservoAngleتعداد سرووها و زاویه فعلی را به ترتیب تعریف کنید.

Adafruit_PWMServoDriver board1 = Adafruit_PWMServoDriver(0x40);
Adafruit_PWMServoDriver board2 = Adafruit_PWMServoDriver(0x41);
int maximumServo = 32; // how many servos are connected

این بخش نحوه‌ی راه‌اندازی اشیاء PCA9685 را با آدرس‌های مربوطه‌شان نشان می‌دهد. متغیرmaximumServoتعداد کل سرووهایی که می‌توان کنترل کرد را تعیین می‌کند.

در setup()تابع، بوردها راه‌اندازی می‌شوند و اتصال Wi-Fi ایجاد می‌شود. موقعیت اولیه همه سرووها با استفاده از یک حلقه تنظیم می‌شود.

void setup() {
  board1.begin();
  board2.begin();  
  board1.setPWMFreq(60);  // Analog servos run at ~60 Hz updates
  board2.setPWMFreq(60);
  //initial position of all servos
  for(int i=0; i < maximumServo; i++) {
    if(i < 16) {
      board1.setPWM(i, 0, angleToPulse(allServoPosition[i]));
    } else {
      board2.setPWM(i-15, 0, angleToPulse(allServoPosition[i]));
    }
  }
}

این شِفر (کود)، بردهای PCA9685 را پیکربندی کرده و فرکانس PWM را تنظیم می‌کند. همچنین، تمام سرووها را به موقعیت‌های ابتدایی خود که تعریف شده‌اند، راه‌اندازی می‌کند.allServoPositionآرایه.

در نهایت، حلقه اصلی درخواست‌های ورودی مشتری را برای کنترل سروها بر اساس ورودی کاربر مدیریت می‌کند.

void loop() {
  server.handleClient();
  if (buttonPushed && (servoNumber >= 0 && servoNumber < maximumServo)) {
    if (servoNumber < 16) {
      board1.setPWM(servoNumber, 0, angleToPulse(allServoPosition[servoNumber]));
    } else {
      board2.setPWM(servoNumber-15, 0, angleToPulse(allServoPosition[servoNumber]));
    }
  }
  buttonPushed = 0;
}

این حلقه به طور مداوم درخواست‌های مشتری را پردازش کرده و موقعیت‌های سرو را بر اساس دکمه‌ای که فشار داده شده به‌روز می‌کند. متغیرbuttonPushedپس از هر عمل برای اطمینان از کنترل مناسب، دوباره تنظیم می‌شود.

برای شِفر (کود) کامل، لطفاً به بخش زیر مقاله مراجعه کنید.

نمایش / چه چیزی باید انتظار داشت

زمانی که همه چیز آماده شد، باید بتوانید هر سروو را به طور جداگانه یا همه را به طور همزمان از یک واسط وب کنترل کنید. می‌توانید زوایای سرووها را با کلیک بر روی دکمه‌های مربوط به هر سروو در دستگاه خود تنظیم کنید. سیستم باید به سرعت پاسخ دهد، اما به خاطر داشته باشید که محدودیت‌های قدرت می‌توانند بر عملکرد تأثیر بگذارند (در ویدئو در ساعت ۱۴:۳۰).

مشکلات رایج شامل اطمینان از اختصاص صحیح آدرس‌های I2C و اینکه قدرت کافی به سروها تأمین شده است، می‌باشد. اگر سروها پاسخ نمی‌دهند، سیم‌کشی و اتصالات خود را دوباره بررسی کنید.

برچسب‌های زمانی ویدیو

  • ۰۰:۰۰ شروع
  • ۰۱:۱۹ مقدمه
  • تنظیم آدرس I2C 02:32
  • 05:07 توضیح سیم‌کشی
  • 07:44 آماده‌سازی Arduino IDE برای ESP32
  • 09:53 توضیح شِفر (کود) آردوینو
  • 25:49 نمایش بر روی دسکتاپ
  • نمایش در تلفن همراه 31:52

تصاویر

PCA9685 module-0
PCA9685 module-0
PCA9685 module-1
PCA9685 module-1
PCA9685 module-2
PCA9685 module-2
PCA9685 module-3
PCA9685 module-3
PCA9685 module
PCA9685 module
ESP32-2
ESP32-2
Connecting two PCA9685 board
Connecting two PCA9685 board
ESP32 wiring for PCA99685 for 32 sevo motors
ESP32 wiring for PCA99685 for 32 sevo motors
881-new- PCA9685 Video V5, Arduino ESP32 Code : Controlling all 32 servo motor over WiFi
زبان: C++
/*
 * کتابخانه منبع ماجیول PCA9685 اصلی: https://github.com/adafruit/Adafruit-PWM-Servo-Driver-Library
 * 
 * این شِفر (کود) آردوینو PCA6985 کنترلر سروو 32 کاناله است
 * برای کنترل 32 موتور سروو از طریق WiFi با استفاده از میکروکنترلر ESP32
 * این شِفر (کود) و اتصالات را از ویدیو زیر دریافت کنید: http://robojax.com/RJT365
 * 
 * ویدیو را برای این شِفر (کود) تماشا کنید: https://youtu.be/bvqfv-FrrLM
 * 
 * ویدیوهای مرتبط
 * ویدیوی V4 از PCA9685 32 سروو با ESP32: https://youtu.be/JFdXB8Za5Os
 * ویدیوی V3 از PCA9685 نحوه کنترل 32 موتور سروو https://youtu.be/6P21wG7N6t4
 * ویدیوی V2 از PCA9685 3 روش مختلف برای کنترل موتورهای سروو: https://youtu.be/bal2STaoQ1M
 * ویدیوی V1 معرفی PCA9685 برای کنترل 16 سروو https://youtu.be/y8X9X10Tn1k
 * 
 * نوشته احمد شمشیری برای کانال ویدیویی Robojax www.Robojax.com
 * تاریخ: 17 فوریه 2020، در اِجَکس، انتاریو، کانادا
 * 
 * یا با استفاده از PayPal کمک مالی کنید http://robojax.com/L/?id=64
 * 
 * این شِفر (کود) "به حالت فعلی" بدون گارانتی یا مسئولیت است. به صورت رایگان قابل استفاده است به شرطی که این یادداشت دست نخورده باقی بماند.*
 * این شِفر (کود) از Robojax.com دانلود شده است
 * این برنامه نرم‌افزار رایگان است: شما می‌توانید آن را بازتوزیع کنید و/یا تحت شرایط GNU General Public License که توسط
 * بنیاد نرم‌افزار آزاد منتشر شده، تغییر دهید؛ نسخه 3 از لایسنس یا
 * (به انتخاب شما) هر نسخه بعدی.
 * 
 * این برنامه با این امید توزیع شده است که مفید خواهد بود،
 * اما بدون هیچ گونه تضمینی؛ حتی بدون تضمین ضمنی
 * قابلیت فروش یا تناسب برای هدف خاص. جزئیات بیشتر را در
 * GNU General Public License ببینید.
 * 
 * شما باید یک نسخه از GNU General Public License را
 * همراه با این برنامه دریافت کرده باشید. اگر نه، به <https://www.gnu.org/licenses/> مراجعه کنید.
 * /
 * ////////////////////// تنظیمات PCA9685 آغاز شد
 */
#include <Wire.h>

#include <Adafruit_PWMServoDriver.h>

 // به این شکل نامیده می‌شود، از آدرس پیش‌فرض 0x40 استفاده می‌کند
Adafruit_PWMServoDriver board1 = Adafruit_PWMServoDriver(0x40);
Adafruit_PWMServoDriver board2 = Adafruit_PWMServoDriver(0x41);
int maximumServo = 32; // چند سروو متصل است

 // با توجه به نوع سروو موتور شما، حداقل و حداکثر عرض پالس ممکن است متفاوت باشد، شما
 // می‌خواهم این‌ها تا حد ممکن کوچک/بزرگ باشند بدون اینکه به توقف سخت برخورد کنند.
 // برای حداکثر برد. شما باید آنها را به گونه‌ای تنظیم کنید که با سروهای شما مطابقت داشته باشد.
 // نداشته باشید!
 // ویدیو V1 را تماشا کنید تا دو خط زیر را درک کنید: http://youtu.be/y8X9X10Tn1k
#define SERVOMIN  125 // این تعداد طول پالس 'حداقل' است (از ۴۰۹۶)
#define SERVOMAX  575 // این تعداد طول پالس «حداکثر» است (از ۴۰۹۶)

int servoAngle =0;
int servoStep = 10;

int stepDelay = 50; // 50 میلی‌ثانیه
int servoAngleMin =0;
int servoAngleMax = 180;

 // حداقل زاویه هر سرو موتورها
int allServoMin[]={
      0,    0,    0,    0,    0,    0,    0,    0, // ۱ تا ۸
      0,    0,    0,    0,    0,    0,    0,    0, // ۹ تا ۱۶
      0,    0,    0,    0,    0,    0,    0,    0, // ۱۷ تا ۲۴
      0,    0,    0,    0,    0,    0,    0,    0}; // ۲۵ تا ۳۲

 // حداکثر مقدار هر سروو
int allServoMax[]={
      180,    180,    180,    180,    180,    180,    180,    180, // ۱ تا ۸
      180,    180,    180,    180,    180,    180,    180,    180, // ۹ تا ۱۶
      180,    180,    180,    180,    180,    180,    180,    180, // ۱۷ تا ۲۴
      180,    180,    180,    180,    180,    180,    180,    180}; // ۲۵ تا ۳۲

 // وضعیت اولیه سرووها
int allServoPosition[] ={
      0,    0,    0,    0,    0,    0,    0,    0, // ۱ تا ۸
      0,    0,    0,    0,    0,    0,    0,    0, // ۹ تا ۱۶
      0,    0,    0,    0,    0,    0,    0,    0, // ۱۷ تا ۲۴
      0,    0,    0,    0,    0,    0,    0,    0}; // ۲۵ تا ۳۲

int servoNumber = 100; // سرعت جابه‌جایی
int buttonPushed =0;
int allServo =0;

void handleServo(); // این نمونه‌ای از تابعی است که در انتهای این شِفر (کود) تعریف شده است.
int angleToPulse(int ang); // این نمونه‌ای از تابعی است که در انتهای این شِفر (کود) تعریف شده است.
 // //////////////////////PCA9685 به پایان رسید

#include "PCA9684_32Servo_ESP32.h"

#include <WiFi.h>
#include <WiFiClient.h>
#include <WebServer.h>
#include <ESPmDNS.h>

const char *ssid = "Robojax";
const char *password = "YouTube2020";

WebServer server(80);

const int led = 13;



 // ///////////////////////////////////
void handleRoot() {

String HTML_page = pageHeader_p1;

 if(allServo)
 {
 HTML_page.concat("<div class=\"btn\"><a class=\"angleButton colorAll\"  href=\"/servo?do=stop\">Stop Servo</a></div>");

 }else{
 HTML_page.concat("<div class=\"btn\"><a class=\"angleButton colorAll\"  href=\"/servo?do=all\">All Servo</a></div>");
 }

 for (int i=0; i < maximumServo; i++)
 {

  HTML_page.concat("<div class=\"btn\"><a class=\"angleButton colorBtn\"  href=\"/servo?move=");
  HTML_page.concat(i);
  HTML_page.concat("\">SRV ");
  HTML_page.concat(i+1);
  HTML_page.concat(" </a></div>");
 }

 HTML_page.concat("</body>\n</html>");
 server.send(200, "text/html", HTML_page);
}

void handleNotFound() {
  digitalWrite(led, 1);
  String message = "File Not Found\n\n";
  message += "URI: ";
  message += server.uri();
  message += "\nMethod: ";
  message += (server.method() == HTTP_GET) ? "GET" : "POST";
  message += "\nArguments: ";
  message += server.args();
  message += "\n";

  for (uint8_t i = 0; i < server.args(); i++) {
    message += " " + server.argName(i) + ": " + server.arg(i) + "\n";
  }

  server.send(404, "text/plain", message);
  digitalWrite(led, 0);
}


void setup() {
  board1.begin();
  board2.begin();
  board1.setPWMFreq(60); // سرعت به‌روزرسانی سرووهای آنالوگ حدود ~60 هرتز است
  board2.setPWMFreq(60);
 // موقعیت اولیه تمام سروها
  for(int i=0; i < maximumServo; i++) {
    if(i < 16)
    {
      board1.setPWM(i, 0, angleToPulse(allServoPosition[i]) );
    }else{
      board2.setPWM(i-15, 0, angleToPulse(allServoPosition[i]) );
    }
  } // برای پایان

    Serial.begin(115200);
    Serial.println("32 channel Servo test!");


 // کنترل سروو با استفاده از ESP32 از Robojax.com

  WiFi.mode(WIFI_STA);
  WiFi.begin(ssid, password);
  Serial.println("");


 // منتظر اتصال باشید
  while (WiFi.status() != WL_CONNECTED) {
    delay(500);
    Serial.print(".");
  }

  Serial.println("");
  Serial.print("Connected to ");
  Serial.println(ssid);
  Serial.print("IP address: ");
  Serial.println(WiFi.localIP());


  if (MDNS.begin("robojaxESP32")) {
    Serial.print("MDNS responder started at http: // ");
    Serial.println("robojaxESP32");
  }

  server.on("/", handleRoot);
  server.on("/servo", HTTP_GET, handleServo);

  server.onNotFound(handleNotFound);
  server.begin();
  Serial.println("HTTP server started");
}

void loop() {
	server.handleClient();
  if(allServo ){

    for( int angle =servoAngleMin; angle <= servoAngleMax; angle +=servoStep){
      for(int i=0; i<16; i++)
        {

            board2.setPWM(i, 0, angleToPulse(angle) );
            board1.setPWM(i, 0, angleToPulse(angle) );
        }
        delay(stepDelay);
    }

 // رابوجكس PCA9865 کنترل سروو ۳۲ کاناله
  delay(100);

  } // اگر فشار داده شود
  if(false){
  Serial.print("Servo #");
  Serial.print (servoNumber);
  Serial.print(" Angle ");
  Serial.println(allServoPosition[servoNumber]);
  }


  if( buttonPushed && (servoNumber >=0 && servoNumber < maximumServo) ){
    if(servoNumber < 16)
    {
      board1.setPWM(servoNumber, 0, angleToPulse(allServoPosition[servoNumber]) );
    }else{
      board2.setPWM(servoNumber-15, 0, angleToPulse(allServoPosition[servoNumber]) );
    }
  }

   buttonPushed =0;
}



/*
 * handleServo()
 * متغیر buttonPushed را بروزرسانی کنید
 * هیچ چیزی برنمی‌گرداند
 * نوشته شده توسط احمد شمشیری در 29 دسامبر 2019
 * www.Robojax.com
 * http://youTube.com/robojaxTV
 */
void handleServo() {
  if(server.arg("do") == "all" )
  {
    allServo =1;

  }else{
    allServo =0;
  }
   int servoNumberRequested= server.arg("move").toInt();

  if(servoNumberRequested >=0 && servoNumberRequested < maximumServo)
  {

    buttonPushed = 1;
    if(allServoPosition[servoNumberRequested] == allServoMin[servoNumberRequested] ) {
     allServoPosition[servoNumberRequested] = allServoMax[servoNumberRequested];
    }else{
     allServoPosition[servoNumberRequested] = allServoMin[servoNumberRequested];
    }
    servoNumber =servoNumberRequested;
  }

  handleRoot();
} // handleServo() پایان


/*
 * زاویهToPulse(int ang)
 * زاویه را به درجه دریافت کرده و عرض پالس را بازمی‌گرداند
 * همچنین مقدار را در نمایشگر مسلسل چاپ می‌کند
 * نوشته شده توسط احمد شمشیری برای Robojax، Robojax.com
 */
int angleToPulse(int ang){
   int pulse = map(ang,0, 180, SERVOMIN,SERVOMAX); // زاویه نقشه را از ۰ تا ۱۸۰ به حداقل و حداکثر سروو نگاشت کنید
 // زاویه: 
 // سریال.چاپ(" پالس: ");سریال.خط.چاپ(pulse);
   return pulse;
}

مواردی که ممکن است به آن‌ها نیاز داشته باشید

منابع و مراجع

فایل‌ها📁

هیچ فایلی موجود نیست.