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

ماجیول 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 شماره ۲ (در سمت چپ)، مطمئن شوید که آن مسیر را لحیم کنید تا آدرس 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.
دستورالعملهای سیمکشی

برای اتصال 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
- شِفر (کود) آردوینو و ویدیو برای کنترلکننده سروو PCA9685، 16 کاناله، 12 بیتی، V1
- کنترل 16 موتور سروو با استفاده از ماجیول PCA9685 و شِفر (کود) آردوینو V2 نمونه #1: یکی یکی
- کنترل ۲۴ موتور سروو با استفاده از ماجیول PCA9685 و شِفر (کود) Arduino V2: کنترل موتور سروو فردی
- Controlling 16 Servo Motors Using a PCA9685 Module and Arduino V2 Sketch #3: All Servos Together
- کنترل یک سروو موتور ۳۲ با استفاده از ماجیول PCA9685 و برنامه آردوینو V3 طرح #۱: همه سرووها با هم
- کنترل یک موتور سرو 32 با استفاده از ماجیول PCA9685 و یک ESP32 V4
/*
* Original PCA9685 Module library source: https://github.com/adafruit/Adafruit-PWM-Servo-Driver-Library
*
* This is the Arduino code PCA6985 32 channel servo controller
* to control 32 Servo Motors over WiFi using ESP32 MCU
* get this code and wiring from for this video: http://robojax.com/RJT365
* Watch video for this code: https://youtu.be/bvqfv-FrrLM
*
* Related Videos
V4 video of PCA9685 32 Servo with ESP32: https://youtu.be/JFdXB8Za5Os
V3 video of PCA9685 how to control 32 Servo motors https://youtu.be/6P21wG7N6t4
V2 Video of PCA9685 3 different ways to control Servo motors: https://youtu.be/bal2STaoQ1M
V1 Video introduction to PCA9685 to control 16 Servo https://youtu.be/y8X9X10Tn1k
*
* Written by Ahmad Shamshiri for Robojax Video channel www.Robojax.com
* Date: Feb 17, 2020, in Ajax, Ontario, Canada
or make donation using PayPal http://robojax.com/L/?id=64
* * This code is "AS IS" without warranty or liability. Free to be used as long as you keep this note intact.*
* This code has been download from Robojax.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <https://www.gnu.org/licenses/>.
*/
////////////////////// PCA9685 settings started
#include <Wire.h>
#include <Adafruit_PWMServoDriver.h>
// called this way, it uses the default address 0x40
Adafruit_PWMServoDriver board1 = Adafruit_PWMServoDriver(0x40);
Adafruit_PWMServoDriver board2 = Adafruit_PWMServoDriver(0x41);
int maximumServo = 32;//how many servos are connected
// Depending on your servo make, the pulse width min and max may vary, you
// want these to be as small/large as possible without hitting the hard stop
// for max range. You'll have to tweak them as necessary to match the servos you
// have!
// Watch video V1 to understand the two lines below: http://youtu.be/y8X9X10Tn1k
#define SERVOMIN 125 // this is the 'minimum' pulse length count (out of 4096)
#define SERVOMAX 575 // this is the 'maximum' pulse length count (out of 4096)
int servoAngle =0;
int servoStep = 10;
int stepDelay = 50;// 50 milliseconds
int servoAngleMin =0;
int servoAngleMax = 180;
// minimum angle of each servo
int allServoMin[]={
0, 0, 0, 0, 0, 0, 0, 0,// 1 to 8
0, 0, 0, 0, 0, 0, 0, 0,//9 to 16
0, 0, 0, 0, 0, 0, 0, 0,//17 to 24
0, 0, 0, 0, 0, 0, 0, 0};//25 to 32
//maximum value of each servo
int allServoMax[]={
180, 180, 180, 180, 180, 180, 180, 180,// 1 to 8
180, 180, 180, 180, 180, 180, 180, 180,//9 to 16
180, 180, 180, 180, 180, 180, 180, 180,//17 to 24
180, 180, 180, 180, 180, 180, 180, 180};//25 to 32
// initial position of servos
int allServoPosition[] ={
0, 0, 0, 0, 0, 0, 0, 0,// 1 to 8
0, 0, 0, 0, 0, 0, 0, 0,//9 to 16
0, 0, 0, 0, 0, 0, 0, 0,//17 to 24
0, 0, 0, 0, 0, 0, 0, 0};//25 to 32
int servoNumber = 100;//servo to move
int buttonPushed =0;
int allServo =0;
void handleServo();//this is prototype of function defined at the end of this code
int angleToPulse(int ang); //this is prototype of function defined at the end of this code
////////////////////////PCA9685 ended
#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); // 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]) );
}
}//for end
Serial.begin(115200);
Serial.println("32 channel Servo test!");
//Servo control using ESP32 from Robojax.com
WiFi.mode(WIFI_STA);
WiFi.begin(ssid, password);
Serial.println("");
// Wait for connection
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);
}
// robojax PCA9865 32 channel Servo control
delay(100);
}//if pushed
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()
* update the buttonPushed varialbe
* returns nothing
* Written by Ahmad Shamshiri on Dec 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() end
/*
* angleToPulse(int ang)
* gets angle in degree and returns the pulse width
* also prints the value on seial monitor
* written by Ahmad Shamshiri for Robojax, Robojax.com
*/
int angleToPulse(int ang){
int pulse = map(ang,0, 180, SERVOMIN,SERVOMAX);// map angle of 0 to 180 to Servo min and Servo max
//Serial.print("Angle: ");Serial.print(ang);
//Serial.print(" pulse: ");Serial.println(pulse);
return pulse;
}
مواردی که ممکن است به آنها نیاز داشته باشید
-
آمازون
-
آمازونموتور سروو در اَمه زونamzn.to
-
ایبیخرید PCA9685 از eBayebay.us
-
علیاکسپرسخرید PCA9685 از علیاکسپرسs.click.aliexpress.com
-
علیاکسپرسموتور سرو SG90 با زاویه ۱۸۰ یا ۳۶۰ را از علیاکسپرس خریداری کنیدs.click.aliexpress.com
-
بنگ گودپیش خرید PCA9685 از بانگودbanggood.com
منابع و مراجع
-
خارجیکتابخانه PAC9685 (از گیتهاب)github.com
فایلها📁
هیچ فایلی موجود نیست.