سوال دارید؟ در انجمن آیرنکس مطرح کنید ورود به انجمن
تخفیف انواع برد و قطعات الکترونیکی ورود به فروشگاه
آموزش آردوینوپروژه های آردوینو

ساخت اسلایدر دوربین با آردوینو برای ضبط فیلم

حتما شده است زمانی که از چیزی فیلم برداری میکنید و مجبور به حرکت هستید، لرزش دست شما ویدئو را خراب کند. اگر میخواهید لرزش دست را حین فیلم برداری از بین ببرید یا اگر میخواهید چند نما سینمایی داشته باشید، باید از اسلایدر دوربین استفاده کنید. اسلایدر های دوربین با قیمت های مختلف در بازار موجود هستند اما غالبا قیمت آن ها بالا هست. ما در این پروژه با استفاده از برد آردوینو و استپر موتور یک اسلایدر دوربین حرفه ای میسازیم.

اسلایدر دوربین آردوینو چطور کار میکند؟

عملکرد اسلایدر دوربین بسیار ساده است. ما برای محور های حرکت از دو موتور پله ای استفاده خواهیم کرد. یک سوئیچ  برای تنظیم موقعیت استفاده می شود. به محض روشن شدن دستگاه، آردوینو موتور حرکت خطی را فعال می کند و آن را به موقعیت اولیه (Home) میرساند. هنگامی که پلت فرم به موقعیت اولیه رسید آردوینو این موقعیت را به عنوان موقعیت اصلی یا موقعیت صفر برای محور خطی تنظیم می کند. پس از آن، آردوینو ما را طی مراحلی راهنمایی می‌کند که در آن می‌توانیم موقعیت‌های Slide in، Slide out، Pan in و Pan out را به همراه سرعت حرکت تنظیم کنیم. کل منو با استفاده از یک روتاری انکودر EC11 کنترل می شود. بعد از کامل کردن تنظیمات، میتوانید حرکت را شروع کنید و همچنین میتوانید با استفاده از دکمه لغو، فرآیند را مجددا راه اندازی کنید. فیلم زیر نحوه عملکرد این پروژه را بهتر نشان میدهد:

قطعات مورد نیاز

تمام قطعاتی که برای ساختن لغزنده دوربین نیاز دارید در زیر لیست شده است. برای درایور موتور، می توانید از A4988 یا DRV8825 یا TMC2209 استفاده کنید. در پروژه زیر از TMC2209 V1.2 شرکت BigTreeTech استفاده کرده ایم.

  • آردوینو نانو
  • 2* درایور موتور (A4988/DRV8825/TMC2209)
  • نمایشگر OLED SSD1306
  • ماژول روتاری انکودر HW-040
  • 2* موتور پله ای NEMA N17
  • 2* لیمیت سوئیچ 3 پین SPDT
  • کلید روشن/خاموش
  • سوکت DC 5521
قطعات مورد نیاز را از فروشگاه قطعات آیرنکس تهیه کنید.

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

مدار ساخت اسلاید دوربین با آردوینو

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

مدار ساخت اسلاید دوربین با آردوینو

شماتیک اسلایدر دوربین بسیار ساده است. OLED به پایه های A4 و A5 آردوینو به همراه پایه های 5 ولت و GND متصل است. پایه SW رمزگذار چرخشی به D2 وصل است، CLK به D3 و پایه DT به D4 متصل است. VCC و GND به ترتیب به پایه های 5 ولت و GND متصل می شوند. سوئیچ های انتهایی به D9 و D10 متصل می شوند.

اتصالات به درایور موتور نیز ساده است. منبع تغذیه 12 ولت به پایه های VMOT درایورها و پایه VIN آردوینو از طریق یک سوئیچ ON/OFF متصل می شود. پین های RST و SLP به یکدیگر متصل می شوند. پین‌های MS1 و MS2 به پایه 5 ولت وصل شده‌اند، در حالی که پایه‌های EN به زمین متصل هستند. تمام پایه های زمین به یکدیگر متصل می شوند. پایه های A1، A2، B1 و B2 به استپر موتور مربوطه متصل هستند. یک خازن الکترولیتی با مقدار حداقل 100uF به پین‌های VMOT و GND متصل می‌شود تا از درایورهای موتور و همچنین آردوینو در برابر هرگونه EMF محافظت کند.

پروژه اسلایدر دوربین آردوینو

کد آردوینو اسلایدر دوربین فیلمبرداری

در مرحله اول مطمئن شوید که کتابخانه های Adafruit GFX، Adafruit SSD1306 و AccelStepper را از Library Manager نصب کرده اید. این کتابخانه ها برای کامپایل کد ضروری هستند. همچنین فایل bitmap.h را در پوشه sketch قرار دهید. این فایل حاوی تمام نمادها و تصاویری است که قرار است از آنها برای نمایش در صفحه نمایش OLED استفاده کنیم. و کد زیر به طور خاص برای TMC2209 V1.2 از BigTreeTech نوشته شده است. اگر نوع دیگری از درایور موتور را انتخاب کنید، ممکن است لازم باشد مقادیر خاصی مانند maxspeed و stepPerRevolution را تغییر دهید.

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

#include <Wire.h>
#include <Adafruit_GFX.h>
#include <Adafruit_SSD1306.h>
#include <AccelStepper.h>
#include <MultiStepper.h>
#include "bitmap.h"

در ابتدا، ما تمام کتابخانه های لازم را فراخوانی میکنیم. کتابخانه Wire همراه با Adafruit_GFX و Adafruit_SSD1306 برای کنترل صفحه نمایش OLED استفاده می شود.

کتابخانه AccelStepper برای کنترل موتورهای پله ای استفاده می شود. فایل هدر Multistepper.h نیز بخشی از کتابخانه AccelStepper است. همانطور که قبلا ذکر شد فایل bitmap.h حاوی تمام اطلاعات تصاویر به صورت بیت مپ است.

#define SCREEN_WIDTH 128  // عرض نمایشگر
#define SCREEN_HEIGHT 64  // طول نمایشگر
#define I2Cspeed 1000000
#define limitSwitch 10
#define PinSW 2
#define PinCLK 3
#define PinDT 4
#define OLED_RESET -1
#define SCREEN_ADDRESS 0x3C
Adafruit_SSD1306 display(SCREEN_WIDTH, SCREEN_HEIGHT, &Wire, OLED_RESET);
AccelStepper stepper2(1, 8, 7);  // (Type:driver, STEP, DIR)
AccelStepper stepper1(1, 6, 5);
MultiStepper StepperControl;
long gotoposition[2];
int selection;
volatile long XInPoint = 0;
volatile long YInPoint = 0;
volatile long XOutPoint = 0;
volatile long YOutPoint = 0;
volatile long totaldistance = 0;
int flag = 0;
int temp = 0;
int i, j;
unsigned long switch0 = 0;
unsigned long rotary0 = 0;
float setspeed = 200;
float motorspeed;
float timeinsec;
float timeinmins;
volatile boolean TurnDetected;
volatile boolean rotationdirection;
const int stepsPerRevolution =200;
const int maxspeed = 6000;

سپس متغیرهایی مانند وضوح صفحه، سرعت I2C، آدرس I2C نمایشگر و اتصالات مربوط به روتاری انکودر را تعریف میکنیم. پس از آن، نمونه هایی را برای نمایشگر و دو موتور پله ای ایجاد میکنیم.

void oledDisplayCenter(const char* text, int x, int y) {
  int16_t x1;
  int16_t y1;
  uint16_t width;
  uint16_t height;
  display.getTextBounds(text, x, y, &x1, &y1, &width, &height);
  display.setCursor((SCREEN_WIDTH - width) / 2, y);
  display.print(text);  // نمایش متن
}

تابع OledDisplayCentre برای وسط قرار دادن متن روی نمایشگر استفاده می شود. این تابع میزان متن را دریافت می کند و عرض متن را محاسبه می کند. پس از آن، مکان نما روی نقطه مناسب تنظیم می شود تا متن با توجه به محور X در مرکز قرار گیرد.

اگر در مورد این مطلب سوالی دارید در قسمت نظرات بپرسید
void Switch() {
  if (flag == 7 && selection == 0 && millis() - switch0 > 500)
  {
    flag = 10;
  }
  else if (millis() - switch0 > 500) {
    flag = flag + 1;
    selection = 1;
  }
  switch0 = millis();
}

تابع سوئیچ کلیک های دکمه رمزگذار چرخشی را کنترل می کند. این عملکرد فرآیند تغییر و تنظیم صفحه را انجام می دهد. این تابع به وقفه سخت افزاری متصل است. و به محض اینکه یک وقفه ایجاد شود، یعنی سوئیچ فشار داده شود، این تابع اجرا می شود.

void Rotary() {
  delay(75);
  if (digitalRead(PinCLK)) 
    rotationdirection = digitalRead(PinDT);
  else
    rotationdirection = !digitalRead(PinDT);
  TurnDetected = true;
  delay(75);
}

تابع Rotary به محض ایجاد وقفه در پایه D3 که به پایه CLK رمزگذار چرخشی متصل است، اجرا می شود. هنگامی که این تابع اجرا می شود، جهت چرخش را تشخیص می دهد و پرچم rotationdirection را بر اساس آن تنظیم می کند. همچنین پرچم دیگری به نام TurnDetected را تنظیم می کند تا تابع حلقه بفهمد که یک چرخش شناسایی شده است.

void setup() {
  Serial.begin(9600);
  stepper1.setMaxSpeed(3000);
  stepper1.setSpeed(200);
  stepper2.setMaxSpeed(3000);
  stepper2.setSpeed(200);
  pinMode(limitSwitch, INPUT_PULLUP);
  pinMode(PinSW, INPUT_PULLUP);
  pinMode(PinCLK, INPUT_PULLUP);
  pinMode(PinDT, INPUT_PULLUP);
  display.begin(SSD1306_SWITCHCAPVCC, 0x3C);
  display.clearDisplay();
  // اضافه کردن دو موتور
  StepperControl.addStepper(stepper1);
  StepperControl.addStepper(stepper2);
  attachInterrupt(digitalPinToInterrupt(PinSW), Switch, RISING);  // SW متصل است به D2
  attachInterrupt(digitalPinToInterrupt(PinCLK), Rotary, RISING);  // CLK متصل است به D3
  // display Boot logo
  for (int i = 124; i > 0; i = i - 4) {
    display.drawBitmap(i, 0, CamSlider, 128, 64, 1);
    display.display();
    display.clearDisplay();
  }
  delay(1000);
  display.clearDisplay();
  Home();  // حرکت دادن اسلایدر به موقعیت خانه
}

در تابع Setup ابتدا، ما ارتباط سریال را با نرخ باود 9600 برای اهداف اشکال زدایی مقداردهی اولیه کردیم. بعداً ما درایور استپر را مقداردهی اولیه کردیم. ما همچنین تمام پین های ورودی را به عنوان INPUT تنظیم کردیم و کتابخانه OLED را نیز مقداردهی اولیه کردیم. سپس یک نمونه  برای کنترل دو موتور پله ای ایجاد کردیم. سپس توابع Switch و Rotary را با استفاده از attachInterrupt به پین های مربوطه متصل میکنیم. پس از آن، یک انیمیشن بوت کوچک نمایش داده می شود و سپس تابع Home فراخوانی می شود.

void Home() {
  stepper1.setMaxSpeed(3000);
  stepper1.setSpeed(200);
  stepper2.setMaxSpeed(3000);
  stepper2.setSpeed(200);
  if (digitalRead(limitSwitch) == 1) {
    for (int i = 92; i > 3; i = i - 4) {
      display.drawBitmap(17, 5, Homing, 92, 27, 1);
      display.drawBitmap(0, 51, slider, 128, 13, 1);
      display.drawBitmap(i, 40, camera, 20, 17, 1);
      display.display();
      display.clearDisplay();
    }
  }
  while (digitalRead(limitSwitch) == 1) {
    stepper1.setSpeed(-3000);
    stepper1.runSpeed();
  }
  delay(20);
  stepper1.setCurrentPosition(0);
  stepper1.moveTo(200);
  while (stepper1.distanceToGo() != 0) {
    stepper1.setSpeed(3000);
    stepper1.runSpeed();
  }
  stepper1.setCurrentPosition(0);
  display.clearDisplay();
}

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

void SetSpeed() {
  display.clearDisplay();
  while (flag == 6) {
    if (TurnDetected) {
      TurnDetected = false;  // do NOT repeat IF loop until new rotation detected
      if (rotationdirection) {
        setspeed = setspeed + 30;
      }
      if (!rotationdirection) {
        setspeed = setspeed - 30;
        if (setspeed < 0) {
          setspeed = 0;
        }
      }
      display.clearDisplay();
      display.setTextSize(2);
      display.setTextColor(WHITE);
      display.setCursor(30, 0);
      display.print("Speed");
      motorspeed = setspeed / 80;
      display.setCursor(5, 16);
      display.print(motorspeed);
      display.print(" mm/s");
      totaldistance = XOutPoint - XInPoint;
      if (totaldistance < 0) {
        totaldistance = totaldistance * (-1);
      } 
      timeinsec = (totaldistance / setspeed);
      timeinmins = timeinsec / 60;
      display.setCursor(35, 32);
      display.print("Time");
      display.setCursor(8, 48);
      if (timeinmins > 1) {
        display.print(timeinmins);
        display.print(" min");
      } else {
        display.print(timeinsec);
        display.print(" sec");
      }
      display.display();
    }
    display.clearDisplay();
    display.setTextSize(2);
    display.setTextColor(WHITE);
    display.setCursor(30, 0);
    display.print("Speed");
    motorspeed = setspeed / 80;
    display.setCursor(5, 16);
    display.print(motorspeed);
    display.print(" mm/s");
    totaldistance = XOutPoint - XInPoint;
    if (totaldistance < 0) {
      totaldistance = totaldistance * (-1);
    } 
    timeinsec = (totaldistance / setspeed);
    timeinmins = timeinsec / 60;
    display.setCursor(35, 32);
    display.print("Time");
    display.setCursor(8, 48);
    if (timeinmins > 1) {
      display.print(timeinmins);
      display.print(" min");
    } else {
      display.print(timeinsec);
      display.print(" sec");
    }
    display.display();
  }
}

تابع Setspeed زمانی که آن را در تابع loop فراخوانی می کنیم، سرعت حرکت را محاسبه و ثبت می کند. این عملکرد همچنین سرعت و زمان را به OLED نیز ارسال میکند و نمایش میدهد.

void select() {
  if (TurnDetected)
  {
    TurnDetected = false;
    if (rotationdirection && selection == 0)
    {
      selection = 1;
      Serial.print("selection: ");
      Serial.println(selection);
    }
    if (!rotationdirection && selection == 1)
    {
      selection = 0;
      Serial.print("selection: ");
      Serial.println(selection);
    }
  }
}

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

void stepperposition(int n) {
  stepper1.setMaxSpeed(maxspeed);
  stepper1.setSpeed(stepsPerRevolution);
  stepper2.setMaxSpeed(maxspeed);
  stepper2.setSpeed(stepsPerRevolution);
  if (TurnDetected) {
    TurnDetected = false;  // تا زمانی که چرخش جدید شناسایی نشده کاری را انجام نده
    if (n == 1) {
      if (!rotationdirection) {
        if (stepper1.currentPosition() - 200 > 0) {
          stepper1.move(-200);
          while (stepper1.distanceToGo() != 0) {
            stepper1.setSpeed(-maxspeed/2);
            stepper1.runSpeed();
          }
        } else {
          while (stepper1.currentPosition() != 0) {
            stepper1.setSpeed(-maxspeed/2);
            stepper1.runSpeed();
          }
        }
      }
      if (rotationdirection) {
        if (stepper1.currentPosition() + 200 < 149000) {
          stepper1.move(200);
          while (stepper1.distanceToGo() != 0) {
            stepper1.setSpeed(maxspeed/2);
            stepper1.runSpeed();
          }
        } else {
          while (stepper1.currentPosition() != 149000) {
            stepper1.setSpeed(maxspeed/2);
            stepper1.runSpeed();
          }
        }
      }
    }
    if (n == 2) {
      if (rotationdirection) {
        stepper2.move(-10);
        while (stepper2.distanceToGo() != 0) {
          stepper2.setSpeed(-maxspeed);
          stepper2.runSpeed();
        }
      }
      if (!rotationdirection) {
        stepper2.move(10);
        while (stepper2.distanceToGo() != 0) {
          stepper2.setSpeed(maxspeed);
          stepper2.runSpeed();
        }
      }
    }
  }
}

تابع stepperpositionموتورها را کنترل می کند و دوربین را در طول مراحل راه اندازی حرکت می دهد. این عملکرد موتور را مطابق با حرکت رمزگذار چرخشی در طول فرآیند حرکت می دهد.

موارد موجود در فایل : سورس کامل ، فایل های چاپ سه بعدی

5 (1 نفر)

دوره آموزش آردوینوثبت نام
دوره آموزش اینترنت‌اشیاثبت نام
دوره آموزش آلتیوم‌دیزاینرثبت نام
دوره آموزش AVR ثبت نام
دوره آموزش الکترونیکثبت نام
دوره آموزش رزبری‌پایثبت نام
دوره آموزش پروتئوسثبت نام
دوره آموزش STM32ثبت نام
برای دریافت مطالب جدید کانال تلگرام یا پیج اینستاگرام ما را دنبال کنید.
تصویر از محمد رحیمی

محمد رحیمی

محمد رحیمی هستم. سعی میکنم در آیرنکس مطالب مفید قرار بدهم. سوالات مربوط به این مطلب را در قسمت نظرات همین مطلب اعلام کنید. سعی میکنم در اسرع وقت به نظرات شما پاسخ بدهم.

دیدگاهتان را بنویسید

نشانی ایمیل شما منتشر نخواهد شد. بخش‌های موردنیاز علامت‌گذاری شده‌اند *