ساخت بازوی رباتیک و کنترل آن توسط تلفن هوشمند

الکترونیک و رباتیک -> ماژول ها و سنسور ها 12168 11 کاربر آکادمی پارتینه

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

امکان کنترل سروو موتورهای ربات و ذخیره‌ی هر موقعیت و اجرای خودکار حرکت ذخیره شده توسط برنامه اندرویدی وجود دارد. در نهایت بازوی ربات می‌تواند بطور خودکار این مراحل را اجرا و تکرار کند. همچنین توسط اپلیکیشن می‌توان حرکت خودکار را متوقف یا حذف کرد .

مواد اولیه :
# عنوان تعداد لینک
0 خرید برد آردوینو 1 لینک خرید

مرحله 1 : مدل سه بعدی بازوی ربات

مدل سه بعدی این ربات 5 درجه آزادی در نرم افزار مدل‌سازی سالیدورکس طراحی شده است.

برای سه محور مربوط به کمر ، شانه و آرنج از سروو موتور  MG996R استفاده شده و برای 2 محور دیگر ( حرکت رول و پیچ مچ دست) از میکرو سرووهای مدل SG90 استفاده شده است.

مدل‌های سه بعدی را از لینک‌های زیر دریافت کنید. 

Arduino Robot Arm 3D Model Solidworks Files
 
Arduino Robot Arm 3D Model STEP File
 
Arduino Robot Arm STL Files

مرحله 2 : پرینت سه بعدی بازوی ربات

 تمام قسمت‌های بازوی ربات را به صورت سه بعدی پرینت می‌کنیم. قبل از مونتاژ توصیه می‌شود که چرخ‌های غلتکی را به اندازه کافی محکم کنید.

مرحله 3 : مونتاژ بازوی ربات (گام اول)

اولین مرحله را با مونتاژ پایه‌ی ربات و اتصال اولین سروو موتور آغاز می‌کنیم. 

مرحله 4 : مونتاژ بازوی ربات (گام دوم)

و در قسمت بالای پایه، قسمت بعدی بازو را قرار داده و توسط دوتا پیچ محکم می‌کنیم.

مرحله 5 : مونتاژ بازوی ربات (گام سوم)

در این مرحله شفت سروو موتور اول را روی قسمت بعدی توسط پیچ متصل می‌کنیم.

مرحله 6 : مونتاژ بازوی ربات (گام چهارم)

به دلیل اینکه سروو موتور اول تمام وزن و تعادل بازو در حالت استاتیک و دینامیک را باید تحمل کند، بهتر است از یک فنر یا بند پلاستیکی برای کم کردن این میزان بار بر روی سروو موتور استفاده شود.

مرحله 7 : مونتاژ بازوی ربات (گام پنجم)

به همین ترتیب سایر لینک‌های ربات را تا قبل از مجری نهایی ربات یعنی گیریپر مونتاژ می‌کنیم. جهت نصب مکانیزم گیریپر از پیچ و مهره 4 میلی‌متری استفاده شده است.

مرحله 8 : مونتاژ بازوی ربات (گام ششم)

سرانجام گریپر را به آخرین سروو متصل کرده تا مونتاژ لینک‌های ربات کامل شود.

 

مرحله 9 : دیاگرام مداری بازوی رباتیک

در این بخش اتصال الکترونیکی ربات بررسی می‌شود. برای ارتباط با تلفن هوشمند یک بورد آردوینو و یک ماژول بلوتوث HC-05 لازم است. پین‌های کنترلی سروو موتور به شش پین دیجیتال آردوینو متصل می‌شوند. به منظور تغذیه‌ی سروو موتورها باید از یک منبع تغذیه خارجی 5 ولت با جریان خروجی حداقل 2 آمپر استفاده شود. آردوینو به تنهایی قادر به تامین چنین جریان نیست.

مرحله 10 : کدنویسی و تنظیمات نرم‌افزاری

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

 در ابتدا به منظور برقرای ارتباط سریال ماژول بلوتوث کتابخانه SoftwareSerial و همچنین کتابخانه سروو موتور را باید فراخوانی کنیم. هر دو  کتابخانه به صورت پیش‌فرض در کامپایلر آردوینو آردوینو نصب شده‌اند. بنابراین نیازی به نصب آنها نیست. سپس باید شش سروو موتور، ماژول بلوتوث HC-05 و برخی متغیرها را برای ذخیره موقعیت فعلی و قبلی سروو موتورها و همچنین آرایه‌هایی را برای ذخیره موقعیت مربوط به حالت اتوماتیک تعریف کنیم.

#include <SoftwareSerial.h>
  #include <Servo.h>

Servo servo01;

Servo servo02;

Servo servo03;

Servo servo04;

Servo servo05;

Servo servo06;

SoftwareSerial Bluetooth(3, 4); // Arduino(RX, TX) - HC-05 Bluetooth (TX, RX)

 int servo1Pos, servo2Pos, servo3Pos, servo4Pos, servo5Pos, servo6Pos; // current position

int servo1PPos, servo2PPos, servo3PPos, servo4PPos, servo5PPos, servo6PPos; // previous position

 int servo01SP[50], servo02SP[50], servo03SP[50], servo04SP[50], servo05SP[50], servo06SP[50]; // for storing positions/steps

 int speedDelay = 20;

int index = 0;
String dataIn = "";

در بخش تنظیمات برنامه باید سروو موتورها و ماژول بلوتوث را راه‌اندازی اولیه و بازوی ربات را به موقعیت اولیه خود منتقل کنیم.  توسط دستور () write سروو موتور را به هر موقعیتی از 0 تا 180 درجه منتقل می‌کنیم.

 servo01.attach(5);

 servo02.attach(6);

 servo03.attach(7);

servo04.attach(8);

 servo05.attach(9);

servo06.attach(10);

Bluetooth.begin(38400); // Default baud rate of the Bluetooth module

 Bluetooth.setTimeout(1);

 delay(20);

 // Robot arm initial position

 servo1PPos = 90;

 servo01.write(servo1PPos);

servo2PPos = 150;

servo02.write(servo2PPos);

servo3PPos = 35;

servo03.write(servo3PPos);

servo4PPos = 140;

servo04.write(servo4PPos);

 servo5PPos = 85;

servo05.write(servo5PPos);

servo6PPos = 80;

servo06.write(servo6PPos);

در حلقه اصلی برنامه با استفاده از دستور () Bluetooth.available دائما وجود اطلاعات دریافتی از تلفن هوشمند را بررسی و در صورت وجود اطلاعات با استفاده از تابع  () readString داده را به صورت رشته در متغیر dataIn ذخیره می‌کنیم.  بسته به اطلاعات دریافتی شده به بازوی ربات خواهیم گفت که حرکتی باید انجام شود.

  // Check for incoming data
 if (Bluetooth.available() > 0) {
 dataIn = Bluetooth.readString(); // Read the data as string


 

مرحله 11 : کنترل بازوی ربات توسط اپلیکیشن اندروید

در تصویر بالا داده‌های مورد نیاز برای کنترل و حرکت ربات توسط اپلیکیشن اندرویدی نشان داده شده است.

با استفاده از نرم افزار تحت وب MIT App Inventor ( ابزاری برای توسعه ی اپلیکیشن‌های اندرویدی بدون نیاز به هرگونه کدنویسی ) تهیه شده و نحوه کار با آن در ادامه بررسی می‌شود.

 در قسمت بالای اپلیکیشن دو دکمه به منظو اتصال تلفن همراه هوشمند به ماژول بلوتوث HC-05 قرار داده شده است. در سمت چپ اپلیکیشن یک تصیر از بازوی ربات و در سمت راست شش منوی کشویی برای کنترل سروو موتورها یک منو کشویی دیگر برای کنترل سرعت در نظر گرفته شده است.

هر منو دارای مقدار اولیه ، حداقل و حداکثر متفاوت است که متناسب با فضای کاری مفاصل ربات است.

در قسمت پایین برنامه سه دکمه  SAVE ، RUN و RESET داریم که از طریق آنها می توانیم بازوی ربات را برای اجرای خودکار برنامه‌ریزی کنیم. همچنین یک لیبل در زیر وجود دارد که تعداد گام‌های ذخیره شده را نشان می‌دهد.

در سمت چپ اپلیکیشن بلوک‌هایی برای اتصال تلفن همراه هوشمند به ماژول بلوتوث قرار می‌دهیم. بلوک‌های کشویی را برای کنترل موقعیت سروو موتور و برنامه‌ریزی بازوی ربات در اختیار داریم.

 به این معنا که با استفاده از تابع Bluetooth function .SendText متنی را به آردوینو ارسال می‌کنیم. این متن شامل یک پیشوند  است که  در آردوینو با استفاده از دستور ()startWith برای اجرای فرمان بررسی می‌شود . به عنوان مثال پیشوند "S1" مربوط به حرکت  سروو شماره 1 است.

با استفاده از تابع ()substring بخش بعدی متن ارسالی را که مربوط به مقدار موقعیت است دریافت کرده و آن را به عدد صحیح تبدیل می‌کنیم. از این مقدار برای انتقال سروو موتور به موقعیت مورد نظر استفاده می‌کنیم.

/*  // If "Waist" slider has changed value - Move Servo 1 to position
 if (dataIn.startsWith("s1")) {

 String dataInS = dataIn.substring(2, dataIn.length()); // Extract only the number. E.g. from "s1120" to "120"
 servo1Pos = dataInS.toInt(); // Convert the string into integer*/

در اینجا فایل نصب اپلیکیشن قرار داده شده است.

به راحتی و با استفاده از دستور ()write سروو را به موقعیت مورد نظر انتقال می‌دهیم. با این روش سروو با حداکثر سرعت خود مسیر را طی می‌کند که برای بازوی ربات خیلی زیاد است. برای کنترل سرعت سروو از چندین حلقه FOR استفاده شده تا به صورت تدریجی و با ایجاد تأخیر بین هر تکرار سروو موتور را از موقعیت قبلی به موقعیت فعلی منتقل کنیم. با تغییر زمان تاخیر می‌توان سرعت سروو موتور را نیز تغییر داد. از همین روش برای راه‌اندازی تمامی لینک‌های ربات استفاده می‌شود.

/*// We use for loops so we can control the speed of the servo
// If previous position is bigger then current position

if (servo1PPos > servo1Pos) {

for ( int j = servo1PPos; j >= servo1Pos; j--) { // Run servo down

 servo01.write(j);

 delay(20); // defines the speed at which the servo rotates

  }

 }

// If previous position is smaller then current position

if (servo1PPos < servo1Pos) {

 for ( int j = servo1PPos; j <= servo1Pos; j++) { // Run servo up

 servo01.write(j);

 delay(20);

 }

 }

servo1PPos = servo1Pos; // set current position as previous position
 }*/


 

در زیر آنها دکمه SAVE قرار دارد. در صورت کلیک بر روی آن، موقعیت هر سروو موتور در یک آرایه ذخیره می‌شود.

 /*// If button "SAVE" is pressed
  if (dataIn.startsWith("SAVE")) {

servo01SP[index] = servo1PPos; // save position into the array

servo02SP[index] = servo2PPos;

servo03SP[index] = servo3PPos;

servo04SP[index] = servo4PPos;

servo05SP[index] = servo5PPos;

servo06SP[index] = servo6PPos;

 index++; // Increase the array index
 }*/

در صورت کلیک بر روی RUN ، تابع ()runervo ربات مراحل ذخیره شده را اجرا می‌کند. در اینجا مراحل ذخیره شده تا زمانیکه دکمه RESET فشار داده شود، اجرا می‌شود. با استفاده از حلقه FOR تمامی موقعیت‌های ذخیره شده در آرایه‌ها اجرا شده و در عین حال وجود داده دریافتی از تلفن همراه هوشمند را بررسی می‌شود. این داده می‌تواند دکمه RUN / PAUSE باشد که باعث متوقف شدن ربات می‌شود . همچنین اگر میزان سرعت توسط اپلیکیشن تغییر کند، زمان تاخیر بین هر تکرار در حلقه‌های FOR که کنترل کننده‌ی سرعت هستند، تغییر می‌کند. 

/*// Automatic mode custom function - run the saved steps
void runservo() {
  while (dataIn != "RESET") {   // Run the steps over and over again until "RESET" button is pressed
    for (int i = 0; i <= index - 2; i++) {  // Run through all steps(index)
      if (Bluetooth.available() > 0) {      // Check for incomding data
        dataIn = Bluetooth.readString();
        if ( dataIn == "PAUSE") {           // If button "PAUSE" is pressed
          while (dataIn != "RUN") {         // Wait until "RUN" is pressed again
            if (Bluetooth.available() > 0) {
              dataIn = Bluetooth.readString();
              if ( dataIn == "RESET") {     
                break;
              }
            }
          }
        }
        // If SPEED slider is changed
        if (dataIn.startsWith("ss")) {
          String dataInS = dataIn.substring(2, dataIn.length());
          speedDelay = dataInS.toInt(); // Change servo speed (delay time)
        }
      }
      // Servo 1
      if (servo01SP[i] == servo01SP[i + 1]) {
      }
      if (servo01SP[i] > servo01SP[i + 1]) {
        for ( int j = servo01SP[i]; j >= servo01SP[i + 1]; j--) {
          servo01.write(j);
          delay(speedDelay);
        }
      }
      if (servo01SP[i] < servo01SP[i + 1]) {
        for ( int j = servo01SP[i]; j <= servo01SP[i + 1]; j++) {
          servo01.write(j);
          delay(speedDelay);
        }
      }*/

سرانجام اگر بر روی RESET کلیک کنیم، تمام داده‌های موجود در آرایه‌ها را صفر شده تا  لینک‌های ربات با حرکات جدید مجددا برنامه‌ریزی شوند.

/*// If button "RESET" is pressed
    if ( dataIn == "RESET") {
      memset(servo01SP, 0, sizeof(servo01SP)); // Clear the array data to 0
      memset(servo02SP, 0, sizeof(servo02SP));
      memset(servo03SP, 0, sizeof(servo03SP));
      memset(servo04SP, 0, sizeof(servo04SP));
      memset(servo05SP, 0, sizeof(servo05SP));
      memset(servo06SP, 0, sizeof(servo06SP));
      index = 0;  // Index to 0
    }*/

کد کامل برنامه

/*        
       DIY Arduino Robot Arm Smartphone Control  
   */
#include <SoftwareSerial.h>
#include <Servo.h>

Servo servo01;
Servo servo02;
Servo servo03;
Servo servo04;
Servo servo05;
Servo servo06;

SoftwareSerial Bluetooth(3, 4); // Arduino(RX, TX) - HC-05 Bluetooth (TX, RX)

int servo1Pos, servo2Pos, servo3Pos, servo4Pos, servo5Pos, servo6Pos; // current position
int servo1PPos, servo2PPos, servo3PPos, servo4PPos, servo5PPos, servo6PPos; // previous position
int servo01SP[50], servo02SP[50], servo03SP[50], servo04SP[50], servo05SP[50], servo06SP[50]; // for storing positions/steps
int speedDelay = 20;
int index = 0;
String dataIn = "";

void setup() {
  servo01.attach(5);
  servo02.attach(6);
  servo03.attach(7);
  servo04.attach(8);
  servo05.attach(9);
  servo06.attach(10);
  Bluetooth.begin(38400); // Default baud rate of the Bluetooth module
  Bluetooth.setTimeout(1);
  delay(20);
  // Robot arm initial position
  servo1PPos = 90;
  servo01.write(servo1PPos);
  servo2PPos = 150;
  servo02.write(servo2PPos);
  servo3PPos = 35;
  servo03.write(servo3PPos);
  servo4PPos = 140;
  servo04.write(servo4PPos);
  servo5PPos = 85;
  servo05.write(servo5PPos);
  servo6PPos = 80;
  servo06.write(servo6PPos);
}

void loop() {
  // Check for incoming data
  if (Bluetooth.available() > 0) {
    dataIn = Bluetooth.readString();  // Read the data as string
    
    // If "Waist" slider has changed value - Move Servo 1 to position
    if (dataIn.startsWith("s1")) {
      String dataInS = dataIn.substring(2, dataIn.length()); // Extract only the number. E.g. from "s1120" to "120"
      servo1Pos = dataInS.toInt();  // Convert the string into integer
      // We use for loops so we can control the speed of the servo
      // If previous position is bigger then current position
      if (servo1PPos > servo1Pos) {
        for ( int j = servo1PPos; j >= servo1Pos; j--) {   // Run servo down
          servo01.write(j);
          delay(20);    // defines the speed at which the servo rotates
        }
      }
      // If previous position is smaller then current position
      if (servo1PPos < servo1Pos) {
        for ( int j = servo1PPos; j <= servo1Pos; j++) {   // Run servo up
          servo01.write(j);
          delay(20);
        }
      }
      servo1PPos = servo1Pos;   // set current position as previous position
    }
    
    // Move Servo 2
    if (dataIn.startsWith("s2")) {
      String dataInS = dataIn.substring(2, dataIn.length());
      servo2Pos = dataInS.toInt();

      if (servo2PPos > servo2Pos) {
        for ( int j = servo2PPos; j >= servo2Pos; j--) {
          servo02.write(j);
          delay(50);
        }
      }
      if (servo2PPos < servo2Pos) {
        for ( int j = servo2PPos; j <= servo2Pos; j++) {
          servo02.write(j);
          delay(50);
        }
      }
      servo2PPos = servo2Pos;
    }
    // Move Servo 3
    if (dataIn.startsWith("s3")) {
      String dataInS = dataIn.substring(2, dataIn.length());
      servo3Pos = dataInS.toInt();
      if (servo3PPos > servo3Pos) {
        for ( int j = servo3PPos; j >= servo3Pos; j--) {
          servo03.write(j);
          delay(30);
        }
      }
      if (servo3PPos < servo3Pos) {
        for ( int j = servo3PPos; j <= servo3Pos; j++) {
          servo03.write(j);
          delay(30);
        }
      }
      servo3PPos = servo3Pos;
    }
    // Move Servo 4
    if (dataIn.startsWith("s4")) {
      String dataInS = dataIn.substring(2, dataIn.length());
      servo4Pos = dataInS.toInt();
      if (servo4PPos > servo4Pos) {
        for ( int j = servo4PPos; j >= servo4Pos; j--) {
          servo04.write(j);
          delay(30);
        }
      }
      if (servo4PPos < servo4Pos) {
        for ( int j = servo4PPos; j <= servo4Pos; j++) {
          servo04.write(j);
          delay(30);
        }
      }
      servo4PPos = servo4Pos;
    }
    // Move Servo 5
    if (dataIn.startsWith("s5")) {
      String dataInS = dataIn.substring(2, dataIn.length());
      servo5Pos = dataInS.toInt();
      if (servo5PPos > servo5Pos) {
        for ( int j = servo5PPos; j >= servo5Pos; j--) {
          servo05.write(j);
          delay(30);
        }
      }
      if (servo5PPos < servo5Pos) {
        for ( int j = servo5PPos; j <= servo5Pos; j++) {
          servo05.write(j);
          delay(30);
        }
      }
      servo5PPos = servo5Pos;
    }
    // Move Servo 6
    if (dataIn.startsWith("s6")) {
      String dataInS = dataIn.substring(2, dataIn.length());
      servo6Pos = dataInS.toInt();
      if (servo6PPos > servo6Pos) {
        for ( int j = servo6PPos; j >= servo6Pos; j--) {
          servo06.write(j);
          delay(30);
        }
      }
      if (servo6PPos < servo6Pos) {
        for ( int j = servo6PPos; j <= servo6Pos; j++) {
          servo06.write(j);
          delay(30);
        }
      }
      servo6PPos = servo6Pos; 
    }
    // If button "SAVE" is pressed
    if (dataIn.startsWith("SAVE")) {
      servo01SP[index] = servo1PPos;  // save position into the array
      servo02SP[index] = servo2PPos;
      servo03SP[index] = servo3PPos;
      servo04SP[index] = servo4PPos;
      servo05SP[index] = servo5PPos;
      servo06SP[index] = servo6PPos;
      index++;                        // Increase the array index
    }
    // If button "RUN" is pressed
    if (dataIn.startsWith("RUN")) {
      runservo();  // Automatic mode - run the saved steps 
    }
    // If button "RESET" is pressed
    if ( dataIn == "RESET") {
      memset(servo01SP, 0, sizeof(servo01SP)); // Clear the array data to 0
      memset(servo02SP, 0, sizeof(servo02SP));
      memset(servo03SP, 0, sizeof(servo03SP));
      memset(servo04SP, 0, sizeof(servo04SP));
      memset(servo05SP, 0, sizeof(servo05SP));
      memset(servo06SP, 0, sizeof(servo06SP));
      index = 0;  // Index to 0
    }
  }
}

// Automatic mode custom function - run the saved steps
void runservo() {
  while (dataIn != "RESET") {   // Run the steps over and over again until "RESET" button is pressed
    for (int i = 0; i <= index - 2; i++) {  // Run through all steps(index)
      if (Bluetooth.available() > 0) {      // Check for incomding data
        dataIn = Bluetooth.readString();
        if ( dataIn == "PAUSE") {           // If button "PAUSE" is pressed
          while (dataIn != "RUN") {         // Wait until "RUN" is pressed again
            if (Bluetooth.available() > 0) {
              dataIn = Bluetooth.readString();
              if ( dataIn == "RESET") {     
                break;
              }
            }
          }
        }
        // If speed slider is changed
        if (dataIn.startsWith("ss")) {
          String dataInS = dataIn.substring(2, dataIn.length());
          speedDelay = dataInS.toInt(); // Change servo speed (delay time)
        }
      }
      // Servo 1
      if (servo01SP[i] == servo01SP[i + 1]) {
      }
      if (servo01SP[i] > servo01SP[i + 1]) {
        for ( int j = servo01SP[i]; j >= servo01SP[i + 1]; j--) {
          servo01.write(j);
          delay(speedDelay);
        }
      }
      if (servo01SP[i] < servo01SP[i + 1]) {
        for ( int j = servo01SP[i]; j <= servo01SP[i + 1]; j++) {
          servo01.write(j);
          delay(speedDelay);
        }
      }

      // Servo 2
      if (servo02SP[i] == servo02SP[i + 1]) {
      }
      if (servo02SP[i] > servo02SP[i + 1]) {
        for ( int j = servo02SP[i]; j >= servo02SP[i + 1]; j--) {
          servo02.write(j);
          delay(speedDelay);
        }
      }
      if (servo02SP[i] < servo02SP[i + 1]) {
        for ( int j = servo02SP[i]; j <= servo02SP[i + 1]; j++) {
          servo02.write(j);
          delay(speedDelay);
        }
      }

      // Servo 3
      if (servo03SP[i] == servo03SP[i + 1]) {
      }
      if (servo03SP[i] > servo03SP[i + 1]) {
        for ( int j = servo03SP[i]; j >= servo03SP[i + 1]; j--) {
          servo03.write(j);
          delay(speedDelay);
        }
      }
      if (servo03SP[i] < servo03SP[i + 1]) {
        for ( int j = servo03SP[i]; j <= servo03SP[i + 1]; j++) {
          servo03.write(j);
          delay(speedDelay);
        }
      }

      // Servo 4
      if (servo04SP[i] == servo04SP[i + 1]) {
      }
      if (servo04SP[i] > servo04SP[i + 1]) {
        for ( int j = servo04SP[i]; j >= servo04SP[i + 1]; j--) {
          servo04.write(j);
          delay(speedDelay);
        }
      }
      if (servo04SP[i] < servo04SP[i + 1]) {
        for ( int j = servo04SP[i]; j <= servo04SP[i + 1]; j++) {
          servo04.write(j);
          delay(speedDelay);
        }
      }

      // Servo 5
      if (servo05SP[i] == servo05SP[i + 1]) {
      }
      if (servo05SP[i] > servo05SP[i + 1]) {
        for ( int j = servo05SP[i]; j >= servo05SP[i + 1]; j--) {
          servo05.write(j);
          delay(speedDelay);
        }
      }
      if (servo05SP[i] < servo05SP[i + 1]) {
        for ( int j = servo05SP[i]; j <= servo05SP[i + 1]; j++) {
          servo05.write(j);
          delay(speedDelay);
        }
      }

      // Servo 6
      if (servo06SP[i] == servo06SP[i + 1]) {
      }
      if (servo06SP[i] > servo06SP[i + 1]) {
        for ( int j = servo06SP[i]; j >= servo06SP[i + 1]; j--) {
          servo06.write(j);
          delay(speedDelay);
        }
      }
      if (servo06SP[i] < servo06SP[i + 1]) {
        for ( int j = servo06SP[i]; j <= servo06SP[i + 1]; j++) {
          servo06.write(j);
          delay(speedDelay);
        }
      }
    }
  }
}

نظرات سایر کاربران درباره این پست

محمد

سلام سرو چند درجه داره